@@ -164,7 +164,7 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->chainStatus);
statusBar()->addPermanentWidget(ui->blockCount);
- ui->blockCount->setText(QString("PV%2 D%3 H%4 v%5").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(c_ethashVersion).arg(dev::Version));
+ ui->blockCount->setText(QString("PV%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
@@ -707,6 +707,7 @@ void Main::writeSettings()
s.setValue("upnp", ui->upnp->isChecked());
s.setValue("forceAddress", ui->forcePublicIP->text());
s.setValue("forceMining", ui->forceMining->isChecked());
+ s.setValue("turboMining", ui->turboMining->isChecked());
s.setValue("paranoia", ui->paranoia->isChecked());
s.setValue("natSpec", ui->natSpec->isChecked());
s.setValue("showAll", ui->showAll->isChecked());
@@ -777,6 +778,8 @@ void Main::readSettings(bool _skipGeometry)
ui->dropPeers->setChecked(false);
ui->forceMining->setChecked(s.value("forceMining", false).toBool());
on_forceMining_triggered();
+ ui->turboMining->setChecked(s.value("turboMining", false).toBool());
+ on_turboMining_triggered();
ui->paranoia->setChecked(s.value("paranoia", false).toBool());
ui->natSpec->setChecked(s.value("natSpec", true).toBool());
ui->showAll->setChecked(s.value("showAll", false).toBool());
@@ -887,12 +890,16 @@ void Main::on_usePrivate_triggered()
{
m_privateChain = QInputDialog::getText(this, "Enter Name", "Enter the name of your private chain", QLineEdit::Normal, QString("NewChain-%1").arg(time(0)));
if (m_privateChain.isEmpty())
- ui->usePrivate->setChecked(false);
+ {
+ if (ui->usePrivate->isChecked())
+ ui->usePrivate->setChecked(false);
+ else
+ // was cancelled.
+ return;
+ }
}
else
- {
m_privateChain.clear();
- }
on_killBlockchain_triggered();
}
@@ -949,7 +956,7 @@ void Main::on_preview_triggered()
void Main::refreshMining()
{
- MineProgress p = ethereum()->miningProgress();
+ MiningProgress p = ethereum()->miningProgress();
ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining");
if (!ui->miningView->isVisible())
return;
@@ -1024,7 +1031,7 @@ void Main::refreshNetwork()
.arg(sessions[i.id] = QString::fromStdString(i.clientVersion))
.arg(QString::fromStdString(toString(i.caps)))
.arg(QString::fromStdString(toString(i.notes)))
- .arg(i.socket)
+ .arg(i.socketId)
.arg(QString::fromStdString(i.id.abridged())));
auto ns = web3()->nodes();
@@ -1478,7 +1485,7 @@ void Main::on_blocks_currentItemChanged()
s << "Difficulty: " << info.difficulty << "" << "
";
if (info.number)
{
- auto e = Ethasher::eval(info);
+ auto e = EthashAux::eval(info);
s << "Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / info.difficulty) << " (mixhash: " << e.mixHash.abridged() << ")" << "
";
s << "Parent: " << info.parentHash << "" << "
";
}
@@ -1507,7 +1514,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Nonce: " << uncle.nonce << "" << "";
s << line << "Hash w/o nonce: " << uncle.headerHash(WithoutNonce) << "" << "";
s << line << "Difficulty: " << uncle.difficulty << "" << "";
- auto e = Ethasher::eval(uncle);
+ auto e = EthashAux::eval(uncle);
s << line << "Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << " (mixhash: " << e.mixHash.abridged() << ")" << "";
}
if (info.parentHash)
@@ -1749,6 +1756,11 @@ void Main::on_clearPending_triggered()
refreshAll();
}
+void Main::on_retryUnknown_triggered()
+{
+ ethereum()->retryUnkonwn();
+}
+
void Main::on_killBlockchain_triggered()
{
writeSettings();
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index a5c74eeaa..a8579ed01 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -163,6 +163,7 @@ private slots:
void on_usePrivate_triggered();
void on_turboMining_triggered();
void on_jitvm_triggered();
+ void on_retryUnknown_triggered();
// Debugger
void on_debugCurrent_triggered();
diff --git a/alethzero/MiningView.cpp b/alethzero/MiningView.cpp
index 63d1fcf99..e020408ea 100644
--- a/alethzero/MiningView.cpp
+++ b/alethzero/MiningView.cpp
@@ -36,7 +36,7 @@ using namespace dev::eth;
// types
using dev::eth::MineInfo;
-using dev::eth::MineProgress;
+using dev::eth::MiningProgress;
// functions
using dev::toString;
@@ -50,12 +50,13 @@ MiningView::MiningView(QWidget* _p): QWidget(_p)
{
}
-void MiningView::appendStats(list const& _i, MineProgress const& _p)
+void MiningView::appendStats(list const& _i, MiningProgress const& _p)
{
+ (void)_p;
if (_i.empty())
return;
- unsigned o = m_values.size();
+/* unsigned o = m_values.size();
for (MineInfo const& i: _i)
{
m_values.push_back(i.best);
@@ -91,7 +92,7 @@ void MiningView::appendStats(list const& _i, MineProgress const& _p)
m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end());
m_progress = _p;
- update();
+ update();*/
}
void MiningView::resetStats()
@@ -101,6 +102,7 @@ void MiningView::resetStats()
void MiningView::paintEvent(QPaintEvent*)
{
+ /*
Grapher g;
QPainter p(this);
@@ -115,4 +117,5 @@ void MiningView::paintEvent(QPaintEvent*)
g.ruleY(r - 1, QColor(128, 128, 128));
for (auto r: m_completes)
g.ruleY(r, QColor(192, 64, 64));
+ */
}
diff --git a/alethzero/MiningView.h b/alethzero/MiningView.h
index 8f3135f75..65b9f2ec9 100644
--- a/alethzero/MiningView.h
+++ b/alethzero/MiningView.h
@@ -42,14 +42,14 @@ class MiningView: public QWidget
public:
MiningView(QWidget* _p = nullptr);
- void appendStats(std::list const& _l, dev::eth::MineProgress const& _p);
+ void appendStats(std::list const& _l, dev::eth::MiningProgress const& _p);
void resetStats();
protected:
virtual void paintEvent(QPaintEvent*);
private:
- dev::eth::MineProgress m_progress;
+ dev::eth::MiningProgress m_progress;
unsigned m_duration = 300;
std::vector m_values;
std::vector m_bests;
diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp
index f1f7477fe..1ebdf9e23 100644
--- a/alethzero/Transact.cpp
+++ b/alethzero/Transact.cpp
@@ -37,7 +37,7 @@
#include
#include
#include
-#ifndef _MSC_VER
+#if ETH_SERPENT
#include
#include
#endif
@@ -220,7 +220,7 @@ static tuple, bytes, string> userInputToCode(string const& _user,
errors.push_back("Solidity: Uncaught exception");
}
}
-#ifndef _MSC_VER
+#if ETH_SERPENT
else if (sourceIsSerpent(_user))
{
try
diff --git a/cmake/CMakeParseArguments.cmake b/cmake/CMakeParseArguments.cmake
new file mode 100644
index 000000000..8553f38f5
--- /dev/null
+++ b/cmake/CMakeParseArguments.cmake
@@ -0,0 +1,161 @@
+#.rst:
+# CMakeParseArguments
+# -------------------
+#
+#
+#
+# CMAKE_PARSE_ARGUMENTS(
+# args...)
+#
+# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions
+# for parsing the arguments given to that macro or function. It
+# processes the arguments and defines a set of variables which hold the
+# values of the respective options.
+#
+# The argument contains all options for the respective macro,
+# i.e. keywords which can be used when calling the macro without any
+# value following, like e.g. the OPTIONAL keyword of the install()
+# command.
+#
+# The argument contains all keywords for this macro
+# which are followed by one value, like e.g. DESTINATION keyword of the
+# install() command.
+#
+# The argument contains all keywords for this
+# macro which can be followed by more than one value, like e.g. the
+# TARGETS or FILES keywords of the install() command.
+#
+# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
+# keywords listed in , and
+# a variable composed of the given
+# followed by "_" and the name of the respective keyword. These
+# variables will then hold the respective value from the argument list.
+# For the keywords this will be TRUE or FALSE.
+#
+# All remaining arguments are collected in a variable
+# _UNPARSED_ARGUMENTS, this can be checked afterwards to see
+# whether your macro was called with unrecognized parameters.
+#
+# As an example here a my_install() macro, which takes similar arguments
+# as the real install() command:
+#
+# ::
+#
+# function(MY_INSTALL)
+# set(options OPTIONAL FAST)
+# set(oneValueArgs DESTINATION RENAME)
+# set(multiValueArgs TARGETS CONFIGURATIONS)
+# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
+# "${multiValueArgs}" ${ARGN} )
+# ...
+#
+#
+#
+# Assume my_install() has been called like this:
+#
+# ::
+#
+# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
+#
+#
+#
+# After the cmake_parse_arguments() call the macro will have set the
+# following variables:
+#
+# ::
+#
+# MY_INSTALL_OPTIONAL = TRUE
+# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
+# MY_INSTALL_DESTINATION = "bin"
+# MY_INSTALL_RENAME = "" (was not used)
+# MY_INSTALL_TARGETS = "foo;bar"
+# MY_INSTALL_CONFIGURATIONS = "" (was not used)
+# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
+#
+#
+#
+# You can then continue and process these variables.
+#
+# Keywords terminate lists of values, e.g. if directly after a
+# one_value_keyword another recognized keyword follows, this is
+# interpreted as the beginning of the new option. E.g.
+# my_install(TARGETS foo DESTINATION OPTIONAL) would result in
+# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION
+# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
+
+#=============================================================================
+# Copyright 2010 Alexander Neundorf
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+
+if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
+ return()
+endif()
+set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
+
+
+function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
+ # first set all result variables to empty/FALSE
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames})
+ set(${prefix}_${arg_name})
+ endforeach()
+
+ foreach(option ${_optionNames})
+ set(${prefix}_${option} FALSE)
+ endforeach()
+
+ set(${prefix}_UNPARSED_ARGUMENTS)
+
+ set(insideValues FALSE)
+ set(currentArgName)
+
+ # now iterate over all arguments and fill the result variables
+ foreach(currentArg ${ARGN})
+ list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+
+ if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
+ if(insideValues)
+ if("${insideValues}" STREQUAL "SINGLE")
+ set(${prefix}_${currentArgName} ${currentArg})
+ set(insideValues FALSE)
+ elseif("${insideValues}" STREQUAL "MULTI")
+ list(APPEND ${prefix}_${currentArgName} ${currentArg})
+ endif()
+ else()
+ list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
+ endif()
+ else()
+ if(NOT ${optionIndex} EQUAL -1)
+ set(${prefix}_${currentArg} TRUE)
+ set(insideValues FALSE)
+ elseif(NOT ${singleArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "SINGLE")
+ elseif(NOT ${multiArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "MULTI")
+ endif()
+ endif()
+
+ endforeach()
+
+ # propagate the result variables to the caller:
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
+ set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
+ endforeach()
+ set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
+
+endfunction()
diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake
old mode 100755
new mode 100644
diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake
index 61c87efd2..2dfb80ac3 100644
--- a/cmake/EthDependencies.cmake
+++ b/cmake/EthDependencies.cmake
@@ -4,7 +4,11 @@
# by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ...
# this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory
string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name)
-set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}")
+if (CMAKE_CL_64)
+ set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}/x64")
+else ()
+ set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}/Win32")
+endif()
set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR})
# setup directory for cmake generated files and include it globally
@@ -59,7 +63,7 @@ if (JSONRPC)
find_package(MHD)
message(" - microhttpd header: ${MHD_INCLUDE_DIRS}")
message(" - microhttpd lib : ${MHD_LIBRARIES}")
-
+ message(" - microhttpd dll : ${MHD_DLLS}")
endif() #JSONRPC
# TODO readline package does not yet check for correct version number
@@ -86,7 +90,7 @@ endif()
# TODO it is also not required in msvc build
find_package (Gmp 6.0.0)
if (GMP_FOUND)
- message(" - gmp Header: ${GMP_INCLUDE_DIRS}")
+ message(" - gmp header: ${GMP_INCLUDE_DIRS}")
message(" - gmp lib : ${GMP_LIBRARIES}")
endif()
@@ -96,6 +100,19 @@ find_package (CURL)
message(" - curl header: ${CURL_INCLUDE_DIRS}")
message(" - curl lib : ${CURL_LIBRARIES}")
+# cpuid required for eth
+find_package (Cpuid)
+if (CPUID_FOUND)
+ message(" - cpuid header: ${CPUID_INCLUDE_DIRS}")
+ message(" - cpuid lib : ${CPUID_LIBRARIES}")
+endif()
+
+find_package (OpenCL)
+if (OpenCL_FOUND)
+ message(" - opencl header: ${OpenCL_INCLUDE_DIRS}")
+ message(" - opencl lib : ${OpenCL_LIBRARIES}")
+endif()
+
# find location of jsonrpcstub
find_program(ETH_JSON_RPC_STUB jsonrpcstub)
message(" - jsonrpcstub location : ${ETH_JSON_RPC_STUB}")
diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake
index 0c529881f..be4f7ccd1 100644
--- a/cmake/EthExecutableHelper.cmake
+++ b/cmake/EthExecutableHelper.cmake
@@ -43,6 +43,22 @@ macro(eth_add_executable EXECUTABLE)
endmacro()
+macro(eth_copy_dlls EXECUTABLE DLLS)
+ # dlls must be unsubstitud list variable (without ${}) in format
+ # optimized;path_to_dll.dll;debug;path_to_dlld.dll
+ list(GET ${DLLS} 1 DLL_RELEASE)
+ list(GET ${DLLS} 3 DLL_DEBUG)
+ add_custom_command(TARGET ${EXECUTABLE}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} ARGS
+ -DDLL_RELEASE="${DLL_RELEASE}"
+ -DDLL_DEBUG="${DLL_DEBUG}"
+ -DCONF="$"
+ -DDESTINATION="${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
+ -P "${ETH_SCRIPTS_DIR}/copydlls.cmake"
+ )
+endmacro()
+
#
# this function requires the following variables to be specified:
# ETH_DEPENDENCY_INSTALL_DIR
@@ -107,10 +123,7 @@ macro(eth_install_executable EXECUTABLE)
#copy additional dlls
foreach(dll ${ETH_INSTALL_EXECUTABLE_DLLS})
- add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS -E copy ${dll} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
- )
+ eth_copy_dlls(${EXECUTABLE} ${dll})
endforeach(dll)
install( TARGETS ${EXECUTABLE} RUNTIME
diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake
index ba6603784..e2f52fe79 100644
--- a/cmake/FindCURL.cmake
+++ b/cmake/FindCURL.cmake
@@ -30,6 +30,7 @@ set(CURL_LIBRARIES ${CURL_LIBRARY})
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+
find_library(
CURL_LIBRARY_DEBUG
NAMES curld libcurld
diff --git a/cmake/FindCpuid.cmake b/cmake/FindCpuid.cmake
new file mode 100644
index 000000000..8b590f44b
--- /dev/null
+++ b/cmake/FindCpuid.cmake
@@ -0,0 +1,33 @@
+# Find libcpuid
+#
+# Find the libcpuid includes and library
+#
+# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
+#
+# This module defines
+# CPUID_INCLUDE_DIRS, where to find header, etc.
+# CPUID_LIBRARIES, the libraries needed to use cpuid.
+# CPUID_FOUND, If false, do not try to use cpuid.
+
+# only look in default directories
+find_path(
+ CPUID_INCLUDE_DIR
+ NAMES libcpuid/libcpuid.h
+ DOC "libcpuid include dir"
+ )
+
+find_library(
+ CPUID_LIBRARY
+ NAMES cpuid
+ DOC "libcpuid library"
+ )
+
+set(CPUID_INCLUDE_DIRS ${CPUID_INCLUDE_DIR})
+set(CPUID_LIBRARIES ${CPUID_LIBRARY})
+
+# handle the QUIETLY and REQUIRED arguments and set CPUID_FOUND to TRUE
+# if all listed variables are TRUE, hide their existence from configuration view
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(cpuid DEFAULT_MSG CPUID_INCLUDE_DIR CPUID_LIBRARY)
+mark_as_advanced (CPUID_INCLUDE_DIR CPUID_LIBRARY)
+
diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake
index c5b9c87d8..1dbfc2046 100644
--- a/cmake/FindJsoncpp.cmake
+++ b/cmake/FindJsoncpp.cmake
@@ -30,6 +30,7 @@ set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+
find_library(
JSONCPP_LIBRARY_DEBUG
NAMES jsoncppd
diff --git a/cmake/FindLevelDB.cmake b/cmake/FindLevelDB.cmake
index b1a9a5815..1c3465665 100644
--- a/cmake/FindLevelDB.cmake
+++ b/cmake/FindLevelDB.cmake
@@ -29,6 +29,7 @@ set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY})
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+
find_library(
LEVELDB_LIBRARY_DEBUG
NAMES leveldbd
diff --git a/cmake/FindMHD.cmake b/cmake/FindMHD.cmake
old mode 100755
new mode 100644
index 5cb8a98d6..1e8ba03aa
--- a/cmake/FindMHD.cmake
+++ b/cmake/FindMHD.cmake
@@ -30,18 +30,20 @@ set(MHD_LIBRARIES ${MHD_LIBRARY})
# official MHD project actually uses _d suffix
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- #TODO: place dlls into CMAKE_CFG_INTDIR subfolders
- string(REPLACE ".lib" ".dll" MHD_DLL_RELEASE ${MHD_LIBRARY})
- string(REPLACE "/lib/" "/bin/" MHD_DLL_RELEASE ${MHD_DLL_RELEASE})
-
find_library(
MHD_LIBRARY_DEBUG
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d
DOC "mhd debug library"
)
- # always use release for now
- #string(REPLACE ".lib" ".dll" MHD_DLL_DEBUG ${MHD_LIBRARY_DEBUG})
- #set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
+
+ set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
+
+ # prepare dlls
+ string(REPLACE ".lib" ".dll" MHD_DLL ${MHD_LIBRARY})
+ string(REPLACE "/lib/" "/bin/" MHD_DLL ${MHD_DLL})
+ string(REPLACE ".lib" ".dll" MHD_DLL_DEBUG ${MHD_LIBRARY_DEBUG})
+ string(REPLACE "/lib/" "/bin/" MHD_DLL_DEBUG ${MHD_DLL_DEBUG})
+ set(MHD_DLLS optimized ${MHD_DLL} debug ${MHD_DLL_DEBUG})
endif()
diff --git a/cmake/FindOpenCL.cmake b/cmake/FindOpenCL.cmake
new file mode 100644
index 000000000..4d3ed842c
--- /dev/null
+++ b/cmake/FindOpenCL.cmake
@@ -0,0 +1,136 @@
+#.rst:
+# FindOpenCL
+# ----------
+#
+# Try to find OpenCL
+#
+# Once done this will define::
+#
+# OpenCL_FOUND - True if OpenCL was found
+# OpenCL_INCLUDE_DIRS - include directories for OpenCL
+# OpenCL_LIBRARIES - link against this library to use OpenCL
+# OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2)
+# OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation
+# OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation
+#
+# The module will also define two cache variables::
+#
+# OpenCL_INCLUDE_DIR - the OpenCL include directory
+# OpenCL_LIBRARY - the path to the OpenCL library
+#
+
+#=============================================================================
+# Copyright 2014 Matthaeus G. Chajdas
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+function(_FIND_OPENCL_VERSION)
+ include(CheckSymbolExists)
+ include(CMakePushCheckState)
+ set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY})
+
+ CMAKE_PUSH_CHECK_STATE()
+ foreach(VERSION "2_0" "1_2" "1_1" "1_0")
+ set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}")
+
+ if(APPLE)
+ CHECK_SYMBOL_EXISTS(
+ CL_VERSION_${VERSION}
+ "${OpenCL_INCLUDE_DIR}/OpenCL/cl.h"
+ OPENCL_VERSION_${VERSION})
+ else()
+ CHECK_SYMBOL_EXISTS(
+ CL_VERSION_${VERSION}
+ "${OpenCL_INCLUDE_DIR}/CL/cl.h"
+ OPENCL_VERSION_${VERSION})
+ endif()
+
+ if(OPENCL_VERSION_${VERSION})
+ string(REPLACE "_" "." VERSION "${VERSION}")
+ set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE)
+ string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}")
+ list(GET version_components 0 major_version)
+ list(GET version_components 1 minor_version)
+ set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE)
+ set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE)
+ break()
+ endif()
+ endforeach()
+ CMAKE_POP_CHECK_STATE()
+endfunction()
+
+find_path(OpenCL_INCLUDE_DIR
+ NAMES
+ CL/cl.h OpenCL/cl.h
+ PATHS
+ ENV "PROGRAMFILES(X86)"
+ ENV AMDAPPSDKROOT
+ ENV INTELOCLSDKROOT
+ ENV NVSDKCOMPUTE_ROOT
+ ENV CUDA_PATH
+ ENV ATISTREAMSDKROOT
+ PATH_SUFFIXES
+ include
+ OpenCL/common/inc
+ "AMD APP/include")
+
+_FIND_OPENCL_VERSION()
+
+if(WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ find_library(OpenCL_LIBRARY
+ NAMES OpenCL
+ PATHS
+ ENV "PROGRAMFILES(X86)"
+ ENV AMDAPPSDKROOT
+ ENV INTELOCLSDKROOT
+ ENV CUDA_PATH
+ ENV NVSDKCOMPUTE_ROOT
+ ENV ATISTREAMSDKROOT
+ PATH_SUFFIXES
+ "AMD APP/lib/x86"
+ lib/x86
+ lib/Win32
+ OpenCL/common/lib/Win32)
+ elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ find_library(OpenCL_LIBRARY
+ NAMES OpenCL
+ PATHS
+ ENV "PROGRAMFILES(X86)"
+ ENV AMDAPPSDKROOT
+ ENV INTELOCLSDKROOT
+ ENV CUDA_PATH
+ ENV NVSDKCOMPUTE_ROOT
+ ENV ATISTREAMSDKROOT
+ PATH_SUFFIXES
+ "AMD APP/lib/x86_64"
+ lib/x86_64
+ lib/x64
+ OpenCL/common/lib/x64)
+ endif()
+else()
+ find_library(OpenCL_LIBRARY
+ NAMES OpenCL)
+endif()
+
+set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
+set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR})
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(
+ OpenCL
+ FOUND_VAR OpenCL_FOUND
+ REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR
+ VERSION_VAR OpenCL_VERSION_STRING)
+
+mark_as_advanced(
+ OpenCL_INCLUDE_DIR
+ OpenCL_LIBRARY)
diff --git a/cmake/FindPackageHandleStandardArgs.cmake b/cmake/FindPackageHandleStandardArgs.cmake
new file mode 100644
index 000000000..6bcf1e788
--- /dev/null
+++ b/cmake/FindPackageHandleStandardArgs.cmake
@@ -0,0 +1,382 @@
+#.rst:
+# FindPackageHandleStandardArgs
+# -----------------------------
+#
+#
+#
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS( ... )
+#
+# This function is intended to be used in FindXXX.cmake modules files.
+# It handles the REQUIRED, QUIET and version-related arguments to
+# find_package(). It also sets the _FOUND variable. The
+# package is considered found if all variables ... listed contain
+# valid results, e.g. valid filepaths.
+#
+# There are two modes of this function. The first argument in both
+# modes is the name of the Find-module where it is called (in original
+# casing).
+#
+# The first simple mode looks like this:
+#
+# ::
+#
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS(
+# (DEFAULT_MSG|"Custom failure message") ... )
+#
+# If the variables to are all valid, then
+# _FOUND will be set to TRUE. If DEFAULT_MSG is given
+# as second argument, then the function will generate itself useful
+# success and error messages. You can also supply a custom error
+# message for the failure case. This is not recommended.
+#
+# The second mode is more powerful and also supports version checking:
+#
+# ::
+#
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME
+# [FOUND_VAR ]
+# [REQUIRED_VARS ...]
+# [VERSION_VAR ]
+# [HANDLE_COMPONENTS]
+# [CONFIG_MODE]
+# [FAIL_MESSAGE "Custom failure message"] )
+#
+# In this mode, the name of the result-variable can be set either to
+# either _FOUND or _FOUND using the
+# FOUND_VAR option. Other names for the result-variable are not
+# allowed. So for a Find-module named FindFooBar.cmake, the two
+# possible names are FooBar_FOUND and FOOBAR_FOUND. It is recommended
+# to use the original case version. If the FOUND_VAR option is not
+# used, the default is _FOUND.
+#
+# As in the simple mode, if through are all valid,
+# _FOUND will be set to TRUE. After REQUIRED_VARS the
+# variables which are required for this package are listed. Following
+# VERSION_VAR the name of the variable can be specified which holds the
+# version of the package which has been found. If this is done, this
+# version will be checked against the (potentially) specified required
+# version used in the find_package() call. The EXACT keyword is also
+# handled. The default messages include information about the required
+# version and the version which has been actually found, both if the
+# version is ok or not. If the package supports components, use the
+# HANDLE_COMPONENTS option to enable handling them. In this case,
+# find_package_handle_standard_args() will report which components have
+# been found and which are missing, and the _FOUND variable
+# will be set to FALSE if any of the required components (i.e. not the
+# ones listed after OPTIONAL_COMPONENTS) are missing. Use the option
+# CONFIG_MODE if your FindXXX.cmake module is a wrapper for a
+# find_package(... NO_MODULE) call. In this case VERSION_VAR will be
+# set to _VERSION and the macro will automatically check whether
+# the Config module was found. Via FAIL_MESSAGE a custom failure
+# message can be specified, if this is not used, the default message
+# will be displayed.
+#
+# Example for mode 1:
+#
+# ::
+#
+# find_package_handle_standard_args(LibXml2 DEFAULT_MSG
+# LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
+#
+#
+#
+# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
+# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to
+# TRUE. If it is not found and REQUIRED was used, it fails with
+# FATAL_ERROR, independent whether QUIET was used or not. If it is
+# found, success will be reported, including the content of . On
+# repeated Cmake runs, the same message won't be printed again.
+#
+# Example for mode 2:
+#
+# ::
+#
+# find_package_handle_standard_args(LibXslt
+# FOUND_VAR LibXslt_FOUND
+# REQUIRED_VARS LibXslt_LIBRARIES LibXslt_INCLUDE_DIRS
+# VERSION_VAR LibXslt_VERSION_STRING)
+#
+# In this case, LibXslt is considered to be found if the variable(s)
+# listed after REQUIRED_VAR are all valid, i.e. LibXslt_LIBRARIES and
+# LibXslt_INCLUDE_DIRS in this case. The result will then be stored in
+# LibXslt_FOUND . Also the version of LibXslt will be checked by using
+# the version contained in LibXslt_VERSION_STRING. Since no
+# FAIL_MESSAGE is given, the default messages will be printed.
+#
+# Another example for mode 2:
+#
+# ::
+#
+# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
+# find_package_handle_standard_args(Automoc4 CONFIG_MODE)
+#
+# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4
+# NO_MODULE) and adds an additional search directory for automoc4. Here
+# the result will be stored in AUTOMOC4_FOUND. The following
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
+# success/error message.
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
+
+# internal helper macro
+macro(_FPHSA_FAILURE_MESSAGE _msg)
+ if (${_NAME}_FIND_REQUIRED)
+ message(FATAL_ERROR "${_msg}")
+ else ()
+ if (NOT ${_NAME}_FIND_QUIETLY)
+ message(STATUS "${_msg}")
+ endif ()
+ endif ()
+endmacro()
+
+
+# internal helper macro to generate the failure message when used in CONFIG_MODE:
+macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
+ # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
+ if(${_NAME}_CONFIG)
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
+ else()
+ # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
+ # List them all in the error message:
+ if(${_NAME}_CONSIDERED_CONFIGS)
+ set(configsText "")
+ list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
+ math(EXPR configsCount "${configsCount} - 1")
+ foreach(currentConfigIndex RANGE ${configsCount})
+ list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
+ list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
+ set(configsText "${configsText} ${filename} (version ${version})\n")
+ endforeach()
+ if (${_NAME}_NOT_FOUND_MESSAGE)
+ set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+ endif()
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
+
+ else()
+ # Simple case: No Config-file was found at all:
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
+ endif()
+ endif()
+endmacro()
+
+
+function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
+
+# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
+# new extended or in the "old" mode:
+ set(options CONFIG_MODE HANDLE_COMPONENTS)
+ set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
+ set(multiValueArgs REQUIRED_VARS)
+ set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
+ list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
+
+ if(${INDEX} EQUAL -1)
+ set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
+ set(FPHSA_REQUIRED_VARS ${ARGN})
+ set(FPHSA_VERSION_VAR)
+ else()
+
+ CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
+
+ if(FPHSA_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ if(NOT FPHSA_FAIL_MESSAGE)
+ set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
+ endif()
+ endif()
+
+# now that we collected all arguments, process them
+
+ if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
+ set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
+ endif()
+
+ # In config-mode, we rely on the variable _CONFIG, which is set by find_package()
+ # when it successfully found the config-file, including version checking:
+ if(FPHSA_CONFIG_MODE)
+ list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
+ list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
+ set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
+ endif()
+
+ if(NOT FPHSA_REQUIRED_VARS)
+ message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
+ endif()
+
+ list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
+
+ string(TOUPPER ${_NAME} _NAME_UPPER)
+ string(TOLOWER ${_NAME} _NAME_LOWER)
+
+ if(FPHSA_FOUND_VAR)
+ if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
+ set(_FOUND_VAR ${FPHSA_FOUND_VAR})
+ else()
+ message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
+ endif()
+ else()
+ set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
+ endif()
+
+ # collect all variables which were not found, so they can be printed, so the
+ # user knows better what went wrong (#6375)
+ set(MISSING_VARS "")
+ set(DETAILS "")
+ # check if all passed variables are valid
+ unset(${_FOUND_VAR})
+ foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
+ if(NOT ${_CURRENT_VAR})
+ set(${_FOUND_VAR} FALSE)
+ set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
+ else()
+ set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
+ endif()
+ endforeach()
+ if(NOT "${${_FOUND_VAR}}" STREQUAL "FALSE")
+ set(${_FOUND_VAR} TRUE)
+ endif()
+
+ # component handling
+ unset(FOUND_COMPONENTS_MSG)
+ unset(MISSING_COMPONENTS_MSG)
+
+ if(FPHSA_HANDLE_COMPONENTS)
+ foreach(comp ${${_NAME}_FIND_COMPONENTS})
+ if(${_NAME}_${comp}_FOUND)
+
+ if(NOT DEFINED FOUND_COMPONENTS_MSG)
+ set(FOUND_COMPONENTS_MSG "found components: ")
+ endif()
+ set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
+
+ else()
+
+ if(NOT DEFINED MISSING_COMPONENTS_MSG)
+ set(MISSING_COMPONENTS_MSG "missing components: ")
+ endif()
+ set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
+
+ if(${_NAME}_FIND_REQUIRED_${comp})
+ set(${_FOUND_VAR} FALSE)
+ set(MISSING_VARS "${MISSING_VARS} ${comp}")
+ endif()
+
+ endif()
+ endforeach()
+ set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
+ set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
+ endif()
+
+ # version handling:
+ set(VERSION_MSG "")
+ set(VERSION_OK TRUE)
+ set(VERSION ${${FPHSA_VERSION_VAR}})
+
+ # check with DEFINED here as the requested or found version may be "0"
+ if (DEFINED ${_NAME}_FIND_VERSION)
+ if(DEFINED ${FPHSA_VERSION_VAR})
+
+ if(${_NAME}_FIND_VERSION_EXACT) # exact version required
+ # count the dots in the version string
+ string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
+ # add one dot because there is one dot more than there are components
+ string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
+ if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
+ # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
+ # is at most 4 here. Therefore a simple lookup table is used.
+ if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
+ set(_VERSION_REGEX "[^.]*")
+ elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
+ set(_VERSION_REGEX "[^.]*\\.[^.]*")
+ elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
+ set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
+ else ()
+ set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
+ endif ()
+ string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
+ unset(_VERSION_REGEX)
+ if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
+ set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+ set(VERSION_OK FALSE)
+ else ()
+ set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+ endif ()
+ unset(_VERSION_HEAD)
+ else ()
+ if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+ set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+ set(VERSION_OK FALSE)
+ else ()
+ set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+ endif ()
+ endif ()
+ unset(_VERSION_DOTS)
+
+ else() # minimum version specified:
+ if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
+ set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
+ set(VERSION_OK FALSE)
+ else ()
+ set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
+ endif ()
+ endif()
+
+ else()
+
+ # if the package was not found, but a version was given, add that to the output:
+ if(${_NAME}_FIND_VERSION_EXACT)
+ set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
+ else()
+ set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
+ endif()
+
+ endif()
+ else ()
+ if(VERSION)
+ set(VERSION_MSG "(found version \"${VERSION}\")")
+ endif()
+ endif ()
+
+ if(VERSION_OK)
+ set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
+ else()
+ set(${_FOUND_VAR} FALSE)
+ endif()
+
+
+ # print the result:
+ if (${_FOUND_VAR})
+ FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
+ else ()
+
+ if(FPHSA_CONFIG_MODE)
+ _FPHSA_HANDLE_FAILURE_CONFIG_MODE()
+ else()
+ if(NOT VERSION_OK)
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
+ else()
+ _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+ endif()
+ endif()
+
+ endif ()
+
+ set(${_FOUND_VAR} ${${_FOUND_VAR}} PARENT_SCOPE)
+
+endfunction()
diff --git a/cmake/FindPackageMessage.cmake b/cmake/FindPackageMessage.cmake
new file mode 100644
index 000000000..a0349d3db
--- /dev/null
+++ b/cmake/FindPackageMessage.cmake
@@ -0,0 +1,57 @@
+#.rst:
+# FindPackageMessage
+# ------------------
+#
+#
+#
+# FIND_PACKAGE_MESSAGE( "message for user" "find result details")
+#
+# This macro is intended to be used in FindXXX.cmake modules files. It
+# will print a message once for each unique find result. This is useful
+# for telling the user where a package was found. The first argument
+# specifies the name (XXX) of the package. The second argument
+# specifies the message to display. The third argument lists details
+# about the find result so that if they change the message will be
+# displayed again. The macro also obeys the QUIET argument to the
+# find_package command.
+#
+# Example:
+#
+# ::
+#
+# if(X11_FOUND)
+# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
+# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
+# else()
+# ...
+# endif()
+
+#=============================================================================
+# Copyright 2008-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+function(FIND_PACKAGE_MESSAGE pkg msg details)
+ # Avoid printing a message repeatedly for the same find result.
+ if(NOT ${pkg}_FIND_QUIETLY)
+ string(REPLACE "\n" "" details "${details}")
+ set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
+ if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
+ # The message has not yet been printed.
+ message(STATUS "${msg}")
+
+ # Save the find details in the cache to avoid printing the same
+ # message again.
+ set("${DETAILS_VAR}" "${details}"
+ CACHE INTERNAL "Details about finding ${pkg}")
+ endif()
+ endif()
+endfunction()
diff --git a/cmake/Findjson_rpc_cpp.cmake b/cmake/Findjson_rpc_cpp.cmake
index 9b64cda2b..0bdbe4d5c 100644
--- a/cmake/Findjson_rpc_cpp.cmake
+++ b/cmake/Findjson_rpc_cpp.cmake
@@ -52,6 +52,7 @@ set (JSON_RPC_CPP_CLIENT_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+
find_library(
JSON_RPC_CPP_COMMON_LIBRARY_DEBUG
NAMES jsonrpccpp-commond
diff --git a/cmake/scripts/copydlls.cmake b/cmake/scripts/copydlls.cmake
new file mode 100644
index 000000000..6d86b8e4e
--- /dev/null
+++ b/cmake/scripts/copydlls.cmake
@@ -0,0 +1,18 @@
+# this module expects
+# DLLS
+# CONF
+# DESTINATION
+
+# example usage:
+# cmake -DDLL_DEBUG=xd.dll -DDLL_RELEASE=x.dll -DCONFIGURATION=Release -DDESTINATION=dest -P scripts/copydlls.cmake
+
+# this script is created cause we do not know configuration in multiconfiguration generators at cmake configure phase ;)
+
+if ("${CONF}" STREQUAL "Release")
+ set(DLL ${DLL_RELEASE})
+else () # Debug
+ set(DLL ${DLL_DEBUG})
+endif()
+
+execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${DLL}" "${DESTINATION}")
+
diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt
index fbc6a8b24..75e0b9e04 100644
--- a/eth/CMakeLists.txt
+++ b/eth/CMakeLists.txt
@@ -22,6 +22,7 @@ if (READLINE_FOUND)
endif()
if (JSONRPC)
+ target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES})
target_link_libraries(${EXECUTABLE} web3jsonrpc)
endif()
@@ -29,7 +30,7 @@ target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethash)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
- add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
+ eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin )
diff --git a/eth/Farm.h b/eth/Farm.h
new file mode 100644
index 000000000..c061449e3
--- /dev/null
+++ b/eth/Farm.h
@@ -0,0 +1,38 @@
+/**
+ * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
+ */
+
+#ifndef JSONRPC_CPP_STUB_FARM_H_
+#define JSONRPC_CPP_STUB_FARM_H_
+
+#include
+
+class Farm : public jsonrpc::Client
+{
+ public:
+ Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
+
+ Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
+ {
+ Json::Value p;
+ p = Json::nullValue;
+ Json::Value result = this->CallMethod("eth_getWork",p);
+ if (result.isArray())
+ return result;
+ else
+ throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
+ }
+ bool eth_submitWork(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
+ {
+ Json::Value p;
+ p.append(param1);
+ p.append(param2);
+ Json::Value result = this->CallMethod("eth_submitWork",p);
+ if (result.isBool())
+ return result.asBool();
+ else
+ throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
+ }
+};
+
+#endif //JSONRPC_CPP_STUB_FARM_H_
diff --git a/eth/PhoneHome.h b/eth/PhoneHome.h
new file mode 100644
index 000000000..ae6091cc2
--- /dev/null
+++ b/eth/PhoneHome.h
@@ -0,0 +1,28 @@
+/**
+ * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
+ */
+
+#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_
+#define JSONRPC_CPP_STUB_PHONEHOME_H_
+
+#include
+
+class PhoneHome : public jsonrpc::Client
+{
+ public:
+ PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
+
+ int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException)
+ {
+ Json::Value p;
+ p.append(param1);
+ p.append(param2);
+ Json::Value result = this->CallMethod("report_benchmark",p);
+ if (result.isInt())
+ return result.asInt();
+ else
+ throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
+ }
+};
+
+#endif //JSONRPC_CPP_STUB_PHONEHOME_H_
diff --git a/eth/farm.json b/eth/farm.json
new file mode 100644
index 000000000..24f0c163e
--- /dev/null
+++ b/eth/farm.json
@@ -0,0 +1,4 @@
+[
+ { "name": "eth_getWork", "params": [], "order": [], "returns": []},
+ { "name": "eth_submitWork", "params": ["", ""], "order": [], "returns": true}
+]
diff --git a/eth/main.cpp b/eth/main.cpp
index c83332c20..98d98b2ab 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -32,20 +32,26 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
#include
-#if ETH_READLINE
+#if ETH_READLINE || !ETH_TRUE
#include
#include
#endif
-#if ETH_JSONRPC
+#if ETH_JSONRPC || !ETH_TRUE
#include
#include
+#include
#endif
-#include
#include "BuildInfo.h"
+#if ETH_JSONRPC || !ETH_TRUE
+#include "PhoneHome.h"
+#include "Farm.h"
+#endif
using namespace std;
using namespace dev;
using namespace dev::p2p;
@@ -88,7 +94,7 @@ void interactiveHelp()
<< " send Execute a given transaction with current secret." << endl
<< " contract Create a new contract with current secret." << endl
<< " peers List the peers that are connected" << endl
-#if ETH_FATDB
+#if ETH_FATDB || !ETH_TRUE
<< " listaccounts List the accounts on the network." << endl
<< " listcontracts List the contracts on the network." << endl
#endif
@@ -110,42 +116,57 @@ void help()
<< " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
<< " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (Default: 15)." << endl
- << " -c,--client-name Add a name to your client's version string (default: blank)." << endl
+ << " --client-name Add a name to your client's version string (default: blank)." << endl
+ << " -C,--cpu When mining, use the CPU." << endl
<< " -d,--db-path Load database from path (default: ~/.ethereum " << endl
<< " /Etherum or Library/Application Support/Ethereum)." << endl
+ << " --benchmark-warmup Set the duration of warmup for the benchmark tests (default: 3)." << endl
+ << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl
+ << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl
<< " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl
<< " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl
<< " -E,--export Export file as a concatenated series of blocks and exit." << endl
<< " --from Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only Equivalent to --export-from n --export-to n." << endl
- << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
+ << " -f,--force-mining Mine even when there are no transactions to mine (Default: off)" << endl
+#if ETH_JSONRPC || !ETH_TRUE
+ << " -F,--farm Put into mining farm mode with the work server at URL. Use with -G/--opencl." << endl
+ << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl
+#endif
+ << " -G,--opencl When mining use the GPU via OpenCL." << endl
<< " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
<< " -I,--import Import file as a concatenated series of blocks and exit." << endl
-#if ETH_JSONRPC
+#if ETH_JSONRPC || !ETH_TRUE
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
+#endif
+#if ETH_EVMJIT || !ETH_TRUE
+ << " -J,--jit Enable EVM JIT (default: off)." << endl
#endif
<< " -K,--kill First kill the blockchain." << endl
- << " --listen-ip Listen on the given port for incoming connections (default: 30303)." << endl
- << " -l,--listen Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
- << " -u,--public-ip Force public ip to given (default: auto)." << endl
+ << " --listen Listen on the given port for incoming connections (default: 30303)." << endl
+ << " --listen-ip (:) Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
+ << " --public-ip Force public ip to given (default: auto)." << endl
<< " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl
- << " -n,--upnp Use upnp for NAT (default: on)." << endl
+ << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl
<< " -o,--mode Start a full node or a peer node (Default: full)." << endl
- << " -p,--port Connect to remote port (default: 30303)." << endl
+ << " --opencl-device When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
+ << " --port Connect to remote port (default: 30303)." << endl
<< " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl
+#if ETH_JSONRPC || !ETH_TRUE
+ << " --phone-home When benchmarking, publish results (Default: on)" << endl
+#endif
<< " -R,--rebuild First rebuild the blockchain from the existing database." << endl
- << " -r,--remote Connect to remote host (default: none)." << endl
+ << " -r,--remote (:) Connect to remote host (default: none)." << endl
<< " -s,--secret Set the secret key for use with send command (default: auto)." << endl
- << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl
+ << " -S,--session-secret Set the secret key for use with send command, for this session only." << endl
+ << " --upnp Use upnp for NAT (default: on)." << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl
- << " -x,--peers Attempt to connect to given number of peers (Default: 5)." << endl
<< " -V,--version Show the version and exit." << endl
-#if ETH_EVMJIT
- << " --jit Use EVM JIT (default: off)." << endl
-#endif
+ << " -w,--check-pow Check PoW credentials for validity." << endl
+ << " -x,--peers Attempt to connect to given number of peers (Default: 5)." << endl
;
exit(0);
}
@@ -210,7 +231,7 @@ void doInitDAG(unsigned _n)
BlockInfo bi;
bi.number = _n;
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl;
- Ethasher::get()->full(bi);
+ Ethash::prep(bi);
exit(0);
}
@@ -219,7 +240,9 @@ enum class OperationMode
Node,
Import,
Export,
- DAGInit
+ DAGInit,
+ Benchmark,
+ Farm
};
enum class Format
@@ -229,6 +252,128 @@ enum class Format
Human
};
+enum class MinerType
+{
+ CPU,
+ GPU
+};
+
+void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5)
+{
+ BlockInfo genesis = CanonBlockChain::genesis();
+ genesis.difficulty = 1 << 18;
+ cdebug << genesis.boundary();
+
+ GenericFarm f;
+ f.onSolutionFound([&](ProofOfWork::Solution) { return false; });
+
+ string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : "";
+ cout << "Benchmarking on platform: " << platformInfo << endl;
+
+ cout << "Preparing DAG..." << endl;
+ Ethash::prep(genesis);
+
+ genesis.difficulty = u256(1) << 63;
+ genesis.noteDirty();
+ f.setWork(genesis);
+ if (_m == MinerType::CPU)
+ f.startCPU();
+ else if (_m == MinerType::GPU)
+ f.startGPU();
+
+ map results;
+ uint64_t mean = 0;
+ uint64_t innerMean = 0;
+ for (unsigned i = 0; i <= _trials; ++i)
+ {
+ if (!i)
+ cout << "Warming up..." << endl;
+ else
+ cout << "Trial " << i << "... " << flush;
+ this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration));
+
+ auto mp = f.miningProgress();
+ f.resetMiningProgress();
+ if (!i)
+ continue;
+ auto rate = mp.rate();
+
+ cout << rate << endl;
+ results[rate] = mp;
+ mean += rate;
+ if (i > 1 && i < 5)
+ innerMean += rate;
+ }
+ f.stop();
+ cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl;
+ cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl;
+
+ (void)_phoneHome;
+#if ETH_JSONRPC || !ETH_TRUE
+ if (_phoneHome)
+ {
+ cout << "Phoning home to find world ranking..." << endl;
+ jsonrpc::HttpClient client("http://192.168.33.39:3000/benchmark");
+ PhoneHome rpc(client);
+ try
+ {
+ unsigned ranking = rpc.report_benchmark(platformInfo, innerMean);
+ cout << "Ranked: " << ranking << " of all benchmarks." << endl;
+ }
+ catch (...)
+ {
+ cout << "Error phoning home. ET is sad." << endl;
+ }
+ }
+#endif
+ exit(0);
+}
+
+void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
+{
+ (void)_m;
+ (void)_remote;
+ (void)_recheckPeriod;
+#if ETH_JSONRPC || !ETH_TRUE
+ jsonrpc::HttpClient client(_remote);
+ Farm rpc(client);
+
+ GenericFarm f;
+
+ if (_m == MinerType::CPU)
+ f.startCPU();
+ else if (_m == MinerType::GPU)
+ f.startGPU();
+
+ ProofOfWork::WorkPackage current;
+ while (true)
+ {
+ bool completed = false;
+ ProofOfWork::Solution solution;
+ f.onSolutionFound([&](ProofOfWork::Solution sol)
+ {
+ solution = sol;
+ return completed = true;
+ });
+ for (unsigned i = 0; !completed; ++i)
+ {
+ Json::Value v = rpc.eth_getWork();
+ h256 hh(v[0].asString());
+ if (hh != current.headerHash)
+ {
+ current.headerHash = hh;
+ current.seedHash = h256(v[1].asString());
+ current.boundary = h256(v[2].asString());
+ f.setWork(current);
+ }
+ this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
+ }
+ rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(solution.mixHash));
+ }
+#endif
+ exit(0);
+}
+
int main(int argc, char** argv)
{
// Init defaults
@@ -238,6 +383,10 @@ int main(int argc, char** argv)
OperationMode mode = OperationMode::Node;
string dbPath;
+ /// Mining options
+ MinerType minerType = MinerType::CPU;
+ unsigned openclDevice = 0;
+
/// File name for import/export.
string filename;
@@ -271,11 +420,10 @@ int main(int argc, char** argv)
/// Mining params
unsigned mining = ~(unsigned)0;
- int miners = -1;
bool forceMining = false;
- bool turboMining = false;
- KeyPair us = KeyPair::create();
- Address coinbase = us.address();
+ KeyPair sigKey = KeyPair::create();
+ Secret sessionSecret;
+ Address coinbase = sigKey.address();
/// Structured logging params
bool structuredLogging = false;
@@ -286,12 +434,22 @@ int main(int argc, char** argv)
double etherPrice = 30.679;
double blockFees = 15.0;
+ /// Benchmarking params
+ bool phoneHome = true;
+ unsigned benchmarkWarmup = 3;
+ unsigned benchmarkTrial = 3;
+ unsigned benchmarkTrials = 5;
+
+ /// Farm params
+ string farmURL = "http://127.0.0.1:8080";
+ unsigned farmRecheckPeriod = 500;
+
string configFile = getDataDir() + "/config.rlp";
bytes b = contents(configFile);
if (b.size())
{
RLP config(b);
- us = KeyPair(config[0].toHash());
+ sigKey = KeyPair(config[0].toHash());
coinbase = config[1].toHash();
}
@@ -301,13 +459,25 @@ int main(int argc, char** argv)
if (arg == "--listen-ip" && i + 1 < argc)
listenIP = argv[++i];
else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
+ {
+ if (arg == "-l")
+ cerr << "-l is DEPRECATED. It will be removed for the Frontier. Use --listen-port instead." << endl;
listenPort = (short)atoi(argv[++i]);
+ }
else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
+ {
+ if (arg == "-u")
+ cerr << "-u is DEPRECATED. It will be removed for the Frontier. Use --public-ip instead." << endl;
publicIP = argv[++i];
+ }
else if ((arg == "-r" || arg == "--remote") && i + 1 < argc)
remoteHost = argv[++i];
else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
+ {
+ if (arg == "-p")
+ cerr << "-p is DEPRECATED. It will be removed for the Frontier. Use --port instead (or place directly as host:port)." << endl;
remotePort = (short)atoi(argv[++i]);
+ }
else if ((arg == "-I" || arg == "--import") && i + 1 < argc)
{
mode = OperationMode::Import;
@@ -318,6 +488,42 @@ int main(int argc, char** argv)
mode = OperationMode::Export;
filename = argv[++i];
}
+ else if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
+ {
+ mode = OperationMode::Farm;
+ farmURL = argv[++i];
+ }
+ else if (arg == "--farm-recheck" && i + 1 < argc)
+ try {
+ farmRecheckPeriod = stol(argv[++i]);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << argv[i] << endl;
+ return -1;
+ }
+ else if (arg == "--opencl-device" && i + 1 < argc)
+ try {
+ openclDevice = stol(argv[++i]);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << argv[i] << endl;
+ return -1;
+ }
+ else if (arg == "--phone-home" && i + 1 < argc)
+ {
+ string m = argv[++i];
+ if (isTrue(m))
+ phoneHome = true;
+ else if (isFalse(m))
+ phoneHome = false;
+ else
+ {
+ cerr << "Bad " << arg << " option: " << m << endl;
+ return -1;
+ }
+ }
else if (arg == "--format" && i + 1 < argc)
{
string m = argv[++i];
@@ -339,8 +545,10 @@ int main(int argc, char** argv)
exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i];
- else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
+ else if ((arg == "-n" || arg == "-u" || arg == "--upnp") && i + 1 < argc)
{
+ if (arg == "-n")
+ cerr << "-n is DEPRECATED. It will be removed for the Frontier. Use --upnp instead." << endl;
string m = argv[++i];
if (isTrue(m))
upnp = true;
@@ -352,18 +560,48 @@ int main(int argc, char** argv)
return -1;
}
}
+ else if (arg == "--benchmark-warmup" && i + 1 < argc)
+ try {
+ benchmarkWarmup = stol(argv[++i]);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << argv[i] << endl;
+ return -1;
+ }
+ else if (arg == "--benchmark-trial" && i + 1 < argc)
+ try {
+ benchmarkTrial = stol(argv[++i]);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << argv[i] << endl;
+ return -1;
+ }
+ else if (arg == "--benchmark-trials" && i + 1 < argc)
+ try {
+ benchmarkTrials = stol(argv[++i]);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << argv[i] << endl;
+ return -1;
+ }
else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill")
killChain = WithExisting::Kill;
else if (arg == "-B" || arg == "--rebuild")
killChain = WithExisting::Verify;
else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
+ {
+ if (arg == "-c")
+ cerr << "-c is DEPRECATED. It will be removed for the Frontier. Use --client-name instead." << endl;
clientName = argv[++i];
+ }
else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc)
- try
- {
+ try {
coinbase = h160(fromHex(argv[++i], WhenError::Throw));
}
- catch (BadHexCharacter& _e)
+ catch (BadHexCharacter&)
{
cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
return -1;
@@ -373,8 +611,14 @@ int main(int argc, char** argv)
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
+ else if (arg == "-C" || arg == "--cpu")
+ minerType = MinerType::CPU;
+ else if (arg == "-G" || arg == "--opencl")
+ minerType = MinerType::GPU;
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
- us = KeyPair(h256(fromHex(argv[++i])));
+ sigKey = KeyPair(h256(fromHex(argv[++i])));
+ else if ((arg == "-S" || arg == "--session-secret") && i + 1 < argc)
+ sessionSecret = h256(fromHex(argv[++i]));
else if (arg == "--structured-logging-format" && i + 1 < argc)
structuredLoggingFormat = string(argv[++i]);
else if (arg == "--structured-logging")
@@ -400,6 +644,45 @@ int main(int argc, char** argv)
return -1;
}
}
+ else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
+ {
+ string m;
+ try
+ {
+ BlockInfo bi;
+ m = boost::to_lower_copy(string(argv[++i]));
+ h256 powHash(m);
+ m = boost::to_lower_copy(string(argv[++i]));
+ h256 seedHash;
+ if (m.size() == 64 || m.size() == 66)
+ seedHash = h256(m);
+ else
+ seedHash = EthashAux::seedHash(stol(m));
+ m = boost::to_lower_copy(string(argv[++i]));
+ bi.difficulty = u256(m);
+ auto boundary = bi.boundary();
+ m = boost::to_lower_copy(string(argv[++i]));
+ bi.nonce = h64(m);
+ auto r = EthashAux::eval(seedHash, powHash, bi.nonce);
+ bool valid = r.value < boundary;
+ cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
+ cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
+ cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl;
+ cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl;
+ cout << " with seed as " << seedHash << endl;
+ if (valid)
+ cout << "(mixHash = " << r.mixHash << ")" << endl;
+ cout << "SHA3( light(seed) ) = " << sha3(bytesConstRef((byte const*)EthashAux::light(seedHash), EthashAux::params(seedHash).cache_size)) << endl;
+ exit(0);
+ }
+ catch (...)
+ {
+ cerr << "Bad " << arg << " option: " << m << endl;
+ return -1;
+ }
+ }
+ else if (arg == "-M" || arg == "--benchmark")
+ mode = OperationMode::Benchmark;
else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc)
{
try
@@ -466,8 +749,6 @@ int main(int argc, char** argv)
bootstrap = true;
else if (arg == "-f" || arg == "--force-mining")
forceMining = true;
- else if (arg == "-T" || arg == "--turbo-mining")
- turboMining = true;
else if (arg == "-i" || arg == "--interactive")
interactive = true;
#if ETH_JSONRPC
@@ -480,8 +761,6 @@ int main(int argc, char** argv)
g_logVerbosity = atoi(argv[++i]);
else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
peers = atoi(argv[++i]);
- else if ((arg == "-t" || arg == "--miners") && i + 1 < argc)
- miners = atoi(argv[++i]);
else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
{
string m = argv[++i];
@@ -495,15 +774,12 @@ int main(int argc, char** argv)
return -1;
}
}
- else if (arg == "--jit")
- {
#if ETH_EVMJIT
+ else if (arg == "-J" || arg == "--jit")
+ {
jit = true;
-#else
- cerr << "EVM JIT not enabled" << endl;
- return -1;
-#endif
}
+#endif
else if (arg == "-h" || arg == "--help")
help();
else if (arg == "-V" || arg == "--version")
@@ -517,15 +793,26 @@ int main(int argc, char** argv)
{
RLPStream config(2);
- config << us.secret() << coinbase;
+ config << sigKey.secret() << coinbase;
writeFile(configFile, config.out());
}
+ if (sessionSecret)
+ sigKey = KeyPair(sessionSecret);
+
+ ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
+
// Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process.
if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock))
doInitDAG(initDAG);
+ if (mode == OperationMode::Benchmark)
+ doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials);
+
+ if (mode == OperationMode::Farm)
+ doFarm(minerType, farmURL, farmRecheckPeriod);
+
if (!clientName.empty())
clientName += "/";
@@ -540,9 +827,7 @@ int main(int argc, char** argv)
killChain,
nodeMode == NodeMode::Full ? set{"eth", "shh"} : set(),
netPrefs,
- &nodesState,
- miners
- );
+ &nodesState);
if (mode == OperationMode::DAGInit)
doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0));
@@ -632,11 +917,10 @@ int main(int argc, char** argv)
{
c->setGasPricer(gasPricer);
c->setForceMining(forceMining);
- c->setTurboMining(turboMining);
c->setAddress(coinbase);
}
- cout << "Transaction Signer: " << us.address() << endl;
+ cout << "Transaction Signer: " << sigKey.address() << endl;
cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork();
@@ -651,8 +935,7 @@ int main(int argc, char** argv)
if (jsonrpc > -1)
{
jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
- jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({us})));
- jsonrpcServer->setIdentities({us});
+ jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({sigKey})));
jsonrpcServer->StartListening();
}
#endif
@@ -776,8 +1059,7 @@ int main(int argc, char** argv)
if (jsonrpc < 0)
jsonrpc = SensibleHttpPort;
jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
- jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({us})));
- jsonrpcServer->setIdentities({us});
+ jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({sigKey})));
jsonrpcServer->StartListening();
}
else if (cmd == "jsonstop")
@@ -789,12 +1071,11 @@ int main(int argc, char** argv)
#endif
else if (cmd == "address")
{
- cout << "Current address:" << endl
- << toHex(us.address().asArray()) << endl;
+ cout << "Current address:" << endl << sigKey.address() << endl;
}
else if (cmd == "secret")
{
- cout << "Secret Key: " << toHex(us.secret().asArray()) << endl;
+ cout << "Secret Key: " << sigKey.secret() << endl;
}
else if (c && cmd == "block")
{
@@ -809,7 +1090,7 @@ int main(int argc, char** argv)
}
else if (c && cmd == "balance")
{
- cout << "Current balance: " << formatBalance( c->balanceAt(us.address())) << " = " <balanceAt(us.address()) << " wei" << endl;
+ cout << "Current balance: " << formatBalance( c->balanceAt(sigKey.address())) << " = " <balanceAt(sigKey.address()) << " wei" << endl;
}
else if (c && cmd == "transact")
{
@@ -925,7 +1206,7 @@ int main(int argc, char** argv)
try
{
Address dest = h160(fromHex(hexAddr, WhenError::Throw));
- c->submitTransaction(us.secret(), amount, dest, bytes(), minGas);
+ c->submitTransaction(sigKey.secret(), amount, dest, bytes(), minGas);
}
catch (BadHexCharacter& _e)
{
@@ -994,7 +1275,7 @@ int main(int argc, char** argv)
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else
- c->submitTransaction(us.secret(), endowment, init, gas, gasPrice);
+ c->submitTransaction(sigKey.secret(), endowment, init, gas, gasPrice);
}
else
cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX";
@@ -1111,7 +1392,7 @@ int main(int argc, char** argv)
{
string hexSec;
iss >> hexSec;
- us = KeyPair(h256(fromHex(hexSec)));
+ sigKey = KeyPair(h256(fromHex(hexSec)));
}
else
cwarn << "Require parameter: setSecret HEXSECRETKEY";
@@ -1151,7 +1432,7 @@ int main(int argc, char** argv)
string path;
iss >> path;
RLPStream config(2);
- config << us.secret() << coinbase;
+ config << sigKey.secret() << coinbase;
writeFile(path, config.out());
}
else
@@ -1167,7 +1448,7 @@ int main(int argc, char** argv)
if (b.size())
{
RLP config(b);
- us = KeyPair(config[0].toHash());
+ sigKey = KeyPair(config[0].toHash());
coinbase = config[1].toHash();
}
else
diff --git a/eth/phonehome.json b/eth/phonehome.json
new file mode 100644
index 000000000..0bed56d72
--- /dev/null
+++ b/eth/phonehome.json
@@ -0,0 +1,3 @@
+[
+ { "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 }
+]
diff --git a/ethrpctest/CMakeLists.txt b/ethrpctest/CMakeLists.txt
index 5d3fef542..e28b08d70 100644
--- a/ethrpctest/CMakeLists.txt
+++ b/ethrpctest/CMakeLists.txt
@@ -28,7 +28,7 @@ target_link_libraries(${EXECUTABLE} testutils)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
- add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
+ eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin )
diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt
index 7e670cfaa..d2a0e9ead 100644
--- a/exp/CMakeLists.txt
+++ b/exp/CMakeLists.txt
@@ -23,10 +23,11 @@ endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} p2p)
+if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} OpenCL)
-
+endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin)
diff --git a/exp/main.cpp b/exp/main.cpp
index 48562f80e..20f287f43 100644
--- a/exp/main.cpp
+++ b/exp/main.cpp
@@ -25,6 +25,7 @@
#include "libethash-cl/cl.hpp"
#endif
#include
+#include
#include
#include
#include
@@ -34,11 +35,12 @@
#include
#include
#include
-#include
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -106,21 +108,144 @@ int main()
cnote << "State after transaction: " << s;
cnote << before.diff(s);
}
-#else
+#elif 0
int main()
{
-#if ETH_ETHASHCL
- EthashCL ecl;
+ GenericFarm f;
BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18;
- cdebug << (h256)u256((bigint(1) << 256) / genesis.difficulty);
- std::pair r;
- while (!r.first.completed)
- r = ecl.mine(genesis, 1000);
- cdebug << r.second.mixHash << r.second.nonce;
- EthashCL::assignResult(r.second, genesis);
- assert(EthashCPU::verify(genesis));
-#endif
+ cdebug << genesis.boundary();
+
+ auto mine = [](GenericFarm& f, BlockInfo const& g, unsigned timeout) {
+ BlockInfo bi = g;
+ bool completed = false;
+ f.onSolutionFound([&](ProofOfWork::Solution sol)
+ {
+ ProofOfWork::assignResult(sol, bi);
+ return completed = true;
+ });
+ f.setWork(bi);
+ for (unsigned i = 0; !completed && i < timeout * 10; ++i, cout << f.miningProgress() << "\r" << flush)
+ this_thread::sleep_for(chrono::milliseconds(100));
+ cout << endl << flush;
+ cdebug << bi.mixHash << bi.nonce << (Ethash::verify(bi) ? "GOOD" : "bad");
+ };
+
+ Ethash::prep(genesis);
+
+ genesis.difficulty = u256(1) << 40;
+ genesis.noteDirty();
+ f.startCPU();
+ mine(f, genesis, 10);
+
+ f.startGPU();
+
+ cdebug << "Good:";
+ genesis.difficulty = 1 << 18;
+ genesis.noteDirty();
+ mine(f, genesis, 30);
+
+ cdebug << "Bad:";
+ genesis.difficulty = (u256(1) << 40);
+ genesis.noteDirty();
+ mine(f, genesis, 30);
+
+ f.stop();
+
+ return 0;
+}
+#elif 0
+
+void mine(State& s, BlockChain const& _bc)
+{
+ s.commitToMine(_bc);
+ GenericFarm f;
+ bool completed = false;
+ f.onSolutionFound([&](ProofOfWork::Solution sol)
+ {
+ return completed = s.completeMine(sol);
+ });
+ f.setWork(s.info());
+ f.startCPU();
+ while (!completed)
+ this_thread::sleep_for(chrono::milliseconds(20));
+}
+#elif 0
+int main()
+{
+ cnote << "Testing State...";
+
+ KeyPair me = sha3("Gav Wood");
+ KeyPair myMiner = sha3("Gav's Miner");
+// KeyPair you = sha3("123");
+
+ Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()));
+
+ OverlayDB stateDB = State::openDB();
+ CanonBlockChain bc;
+ cout << bc;
+
+ State s(stateDB, BaseState::CanonGenesis, myMiner.address());
+ cout << s;
+
+ // Sync up - this won't do much until we use the last state.
+ s.sync(bc);
+
+ cout << s;
+
+ // Mine to get some ether!
+ mine(s, bc);
+
+ bc.attemptImport(s.blockData(), stateDB);
+
+ cout << bc;
+
+ s.sync(bc);
+
+ cout << s;
+
+ // Inject a transaction to transfer funds from miner to me.
+ Transaction t(1000, 10000, 30000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
+ assert(t.sender() == myMiner.address());
+ s.execute(bc.lastHashes(), t);
+
+ cout << s;
+
+ // Mine to get some ether and set in stone.
+ s.commitToMine(bc);
+ s.commitToMine(bc);
+ mine(s, bc);
+ bc.attemptImport(s.blockData(), stateDB);
+
+ cout << bc;
+
+ s.sync(bc);
+
+ cout << s;
+
+ return 0;
+}
+#else
+int main()
+{
+ string tempDir = boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count());
+
+ KeyPair myMiner = sha3("Gav's Miner");
+
+ p2p::Host net("Test");
+ cdebug << "Path:" << tempDir;
+ Client c(&net, tempDir);
+
+ c.setAddress(myMiner.address());
+
+ this_thread::sleep_for(chrono::milliseconds(1000));
+
+ c.startMining();
+
+ this_thread::sleep_for(chrono::milliseconds(6000));
+
+ c.stopMining();
+
return 0;
}
#endif
diff --git a/extdep/CMakeLists.txt b/extdep/CMakeLists.txt
index e9711754f..8ec381330 100644
--- a/extdep/CMakeLists.txt
+++ b/extdep/CMakeLists.txt
@@ -34,23 +34,14 @@ if (ETH_COMPILE)
# boost
include(compile/boost.cmake)
else()
- eth_download(jsoncpp)
- eth_download(microhttpd)
- eth_download(json-rpc-cpp
- VERSION 4.2
- OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh
- )
-
- if (APPLE)
- eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh)
- endif()
-
- eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh)
- eth_download(qt VERSION 5.4)
- eth_download(cryptopp)
- eth_download(boost)
- eth_download(curl)
-
+ eth_download(boost VERSION 1.55.0)
+ eth_download(cryptopp VERSION 5.6.2)
+ eth_download(curl VERSION 7.4.2)
+ eth_download(jsoncpp VERSION 1.6.2)
+ eth_download(json-rpc-cpp VERSION 0.5.0)
+ eth_download(leveldb VERSION 1.2)
+ eth_download(microhttpd VERSION 0.9.2)
+ eth_download(qt VERSION 5.4.1)
endif()
# will be re-eanbled later
diff --git a/extdep/getstuff.bat b/extdep/getstuff.bat
new file mode 100644
index 000000000..e083a97ce
--- /dev/null
+++ b/extdep/getstuff.bat
@@ -0,0 +1,32 @@
+REM get stuff!
+if not exist download mkdir download
+if not exist install mkdir install
+if not exist install\windows mkdir install\windows
+
+set eth_server=https://build.ethdev.com/builds/windows-precompiled
+
+call :download boost 1.55.0
+call :download cryptopp 5.6.2
+call :download curl 7.4.2
+call :download jsoncpp 1.6.2
+call :download json-rpc-cpp 0.5.0
+call :download leveldb 1.2
+call :download microhttpd 0.9.2
+call :download qt 5.4.1
+
+goto :EOF
+
+:download
+
+set eth_name=%1
+set eth_version=%2
+
+cd download
+
+if not exist %eth_name%-%eth_version%.tar.gz curl -o %eth_name%-%eth_version%.tar.gz %eth_server%/%eth_name%-%eth_version%.tar.gz
+if not exist %eth_name%-%eth_version% tar -zxvf %eth_name%-%eth_version%.tar.gz
+cmake -E copy_directory %eth_name%-%eth_version% ..\install\windows
+
+cd ..\download
+
+goto :EOF
diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp
index b6e8e7f93..7cdc433f3 100644
--- a/libdevcore/Common.cpp
+++ b/libdevcore/Common.cpp
@@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
-char const* Version = "0.9.7";
+char const* Version = "0.9.9";
}
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 38ccd71f0..93bad71a3 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -116,9 +116,9 @@ inline void toBigEndian(_T _val, _Out& o_out)
template
inline _T fromBigEndian(_In const& _bytes)
{
- _T ret = 0;
+ _T ret = (_T)0;
for (auto i: _bytes)
- ret = (ret << 8) | (byte)(typename std::make_unsigned::type)i;
+ ret = (_T)((ret << 8) | (byte)(typename std::make_unsigned::type)i);
return ret;
}
diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h
index f5c64b041..4229428ce 100644
--- a/libdevcore/Guards.h
+++ b/libdevcore/Guards.h
@@ -38,4 +38,75 @@ using UpgradableGuard = boost::upgrade_lock;
using UpgradeGuard = boost::upgrade_to_unique_lock;
using WriteGuard = boost::unique_lock;
+template
+struct GenericGuardBool: GuardType
+{
+ GenericGuardBool(MutexType& _m): GuardType(_m) {}
+ bool b = true;
+};
+template
+struct GenericUnguardBool
+{
+ GenericUnguardBool(MutexType& _m): m(_m) { m.unlock(); }
+ ~GenericUnguardBool() { m.lock(); }
+ bool b = true;
+ MutexType& m;
+};
+template
+struct GenericUnguardSharedBool
+{
+ GenericUnguardSharedBool(MutexType& _m): m(_m) { m.unlock_shared(); }
+ ~GenericUnguardSharedBool() { m.lock_shared(); }
+ bool b = true;
+ MutexType& m;
+};
+
+/** @brief Simple block guard.
+ * The expression/block following is guarded though the given mutex.
+ * Usage:
+ * @code
+ * Mutex m;
+ * unsigned d;
+ * ...
+ * ETH_GUARDED(m) d = 1;
+ * ...
+ * ETH_GUARDED(m) { for (auto d = 10; d > 0; --d) foo(d); d = 0; }
+ * @endcode
+ *
+ * There are several variants of this basic mechanism for different Mutex types and Guards.
+ *
+ * There is also the UNGUARD variant which allows an unguarded expression/block to exist within a
+ * guarded expression. eg:
+ *
+ * @code
+ * Mutex m;
+ * int d;
+ * ...
+ * ETH_GUARDED(m)
+ * {
+ * for (auto d = 50; d > 25; --d)
+ * foo(d);
+ * ETH_UNGUARDED(m)
+ * bar();
+ * for (; d > 0; --d)
+ * foo(d);
+ * }
+ * @endcode
+ */
+
+#define ETH_GUARDED(MUTEX) \
+ for (GenericGuardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_READ_GUARDED(MUTEX) \
+ for (GenericGuardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_WRITE_GUARDED(MUTEX) \
+ for (GenericGuardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_RECURSIVE_GUARDED(MUTEX) \
+ for (GenericGuardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_UNGUARDED(MUTEX) \
+ for (GenericUnguardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_READ_UNGUARDED(MUTEX) \
+ for (GenericUnguardSharedBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define ETH_WRITE_UNGUARDED(MUTEX) \
+ for (GenericUnguardBool __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+
}
diff --git a/libdevcore/Worker.cpp b/libdevcore/Worker.cpp
index 175323620..8c1fbb9c7 100644
--- a/libdevcore/Worker.cpp
+++ b/libdevcore/Worker.cpp
@@ -27,24 +27,28 @@
using namespace std;
using namespace dev;
-void Worker::startWorking()
+void Worker::startWorking(IfRunning _ir)
{
- cnote << "startWorking for thread" << m_name;
+// cnote << "startWorking for thread" << m_name;
Guard l(x_work);
- if (m_work)
- return;
+
+ if (m_work && m_work->joinable())
+ try {
+ if (_ir == IfRunning::Detach)
+ m_work->detach();
+ else if (_ir == IfRunning::Join)
+ m_work->join();
+ else
+ return;
+ } catch (...) {}
cnote << "Spawning" << m_name;
m_stop = false;
m_work.reset(new thread([&]()
{
setThreadName(m_name.c_str());
startedWorking();
- while (!m_stop)
- {
- if (m_idleWaitMs)
- this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
- doWork();
- }
+ workLoop();
+ m_work->detach();
cnote << "Finishing up worker thread";
doneWorking();
}));
@@ -52,14 +56,26 @@ void Worker::startWorking()
void Worker::stopWorking()
{
- cnote << "stopWorking for thread" << m_name;
+// cnote << "stopWorking for thread" << m_name;
Guard l(x_work);
- if (!m_work)
+ if (!m_work || !m_work->joinable())
return;
cnote << "Stopping" << m_name;
m_stop = true;
- m_work->join();
+ try {
+ m_work->join();
+ }
+ catch (...) {}
m_work.reset();
cnote << "Stopped" << m_name;
}
+void Worker::workLoop()
+{
+ while (!m_stop)
+ {
+ if (m_idleWaitMs)
+ this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
+ doWork();
+ }
+}
diff --git a/libdevcore/Worker.h b/libdevcore/Worker.h
index 40bc118aa..287ff6d6f 100644
--- a/libdevcore/Worker.h
+++ b/libdevcore/Worker.h
@@ -23,11 +23,19 @@
#include
#include
+#include
#include "Guards.h"
namespace dev
{
+enum class IfRunning
+{
+ Fail,
+ Join,
+ Detach
+};
+
class Worker
{
protected:
@@ -45,7 +53,7 @@ protected:
void setName(std::string _n) { if (!isWorking()) m_name = _n; }
/// Starts worker thread; causes startedWorking() to be called.
- void startWorking();
+ void startWorking(IfRunning _ir = IfRunning::Fail);
/// Stop worker thread; causes call to stopWorking().
void stopWorking();
@@ -57,11 +65,18 @@ protected:
virtual void startedWorking() {}
/// Called continuously following sleep for m_idleWaitMs.
- virtual void doWork() = 0;
+ virtual void doWork() {}
+
+ /// Overrides doWork(); should call shouldStop() often and exit when true.
+ virtual void workLoop();
+ bool shouldStop() const { return m_stop; }
/// Called when is to be stopped, just prior to thread being joined.
virtual void doneWorking() {}
+ /// Blocks caller into worker thread has finished.
+ void join() const { Guard l(x_work); try { if (m_work) m_work->join(); } catch (...) {} }
+
private:
std::string m_name;
unsigned m_idleWaitMs = 0;
diff --git a/libethash-cl/CMakeLists.txt b/libethash-cl/CMakeLists.txt
new file mode 100644
index 000000000..fdc2dad07
--- /dev/null
+++ b/libethash-cl/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(EXECUTABLE ethash-cl)
+
+include(bin2h.cmake)
+bin2h(SOURCE_FILE ethash_cl_miner_kernel.cl
+ VARIABLE_NAME ethash_cl_miner_kernel
+ HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/ethash_cl_miner_kernel.h)
+
+aux_source_directory(. SRC_LIST)
+file(GLOB HEADERS "*.h")
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${OpenCL_INCLUDE_DIRS})
+include_directories(..)
+add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
+TARGET_LINK_LIBRARIES(${EXECUTABLE} ${OpenCL_LIBRARIES} ethash)
+
+install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
+install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )
+
diff --git a/libethash-cl/bin2h.cmake b/libethash-cl/bin2h.cmake
new file mode 100644
index 000000000..90ca9cc5b
--- /dev/null
+++ b/libethash-cl/bin2h.cmake
@@ -0,0 +1,86 @@
+# https://gist.github.com/sivachandran/3a0de157dccef822a230
+include(CMakeParseArguments)
+
+# Function to wrap a given string into multiple lines at the given column position.
+# Parameters:
+# VARIABLE - The name of the CMake variable holding the string.
+# AT_COLUMN - The column position at which string will be wrapped.
+function(WRAP_STRING)
+ set(oneValueArgs VARIABLE AT_COLUMN)
+ cmake_parse_arguments(WRAP_STRING "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ string(LENGTH ${${WRAP_STRING_VARIABLE}} stringLength)
+ math(EXPR offset "0")
+
+ while(stringLength GREATER 0)
+
+ if(stringLength GREATER ${WRAP_STRING_AT_COLUMN})
+ math(EXPR length "${WRAP_STRING_AT_COLUMN}")
+ else()
+ math(EXPR length "${stringLength}")
+ endif()
+
+ string(SUBSTRING ${${WRAP_STRING_VARIABLE}} ${offset} ${length} line)
+ set(lines "${lines}\n${line}")
+
+ math(EXPR stringLength "${stringLength} - ${length}")
+ math(EXPR offset "${offset} + ${length}")
+ endwhile()
+
+ set(${WRAP_STRING_VARIABLE} "${lines}" PARENT_SCOPE)
+endfunction()
+
+# Function to embed contents of a file as byte array in C/C++ header file(.h). The header file
+# will contain a byte array and integer variable holding the size of the array.
+# Parameters
+# SOURCE_FILE - The path of source file whose contents will be embedded in the header file.
+# VARIABLE_NAME - The name of the variable for the byte array. The string "_SIZE" will be append
+# to this name and will be used a variable name for size variable.
+# HEADER_FILE - The path of header file.
+# APPEND - If specified appends to the header file instead of overwriting it
+# NULL_TERMINATE - If specified a null byte(zero) will be append to the byte array. This will be
+# useful if the source file is a text file and we want to use the file contents
+# as string. But the size variable holds size of the byte array without this
+# null byte.
+# Usage:
+# bin2h(SOURCE_FILE "Logo.png" HEADER_FILE "Logo.h" VARIABLE_NAME "LOGO_PNG")
+function(BIN2H)
+ set(options APPEND NULL_TERMINATE)
+ set(oneValueArgs SOURCE_FILE VARIABLE_NAME HEADER_FILE)
+ cmake_parse_arguments(BIN2H "${options}" "${oneValueArgs}" "" ${ARGN})
+
+ # reads source file contents as hex string
+ file(READ ${BIN2H_SOURCE_FILE} hexString HEX)
+ string(LENGTH ${hexString} hexStringLength)
+
+ # appends null byte if asked
+ if(BIN2H_NULL_TERMINATE)
+ set(hexString "${hexString}00")
+ endif()
+
+ # wraps the hex string into multiple lines at column 32(i.e. 16 bytes per line)
+ wrap_string(VARIABLE hexString AT_COLUMN 32)
+ math(EXPR arraySize "${hexStringLength} / 2")
+
+ # adds '0x' prefix and comma suffix before and after every byte respectively
+ string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " arrayValues ${hexString})
+ # removes trailing comma
+ string(REGEX REPLACE ", $" "" arrayValues ${arrayValues})
+
+ # converts the variable name into proper C identifier
+ IF (${CMAKE_VERSION} GREATER 2.8.10) # fix for legacy cmake
+ string(MAKE_C_IDENTIFIER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
+ ENDIF()
+ string(TOUPPER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
+
+ # declares byte array and the length variables
+ set(arrayDefinition "const unsigned char ${BIN2H_VARIABLE_NAME}[] = { ${arrayValues} };")
+ set(arraySizeDefinition "const size_t ${BIN2H_VARIABLE_NAME}_SIZE = ${arraySize};")
+
+ set(declarations "${arrayDefinition}\n\n${arraySizeDefinition}\n\n")
+ if(BIN2H_APPEND)
+ file(APPEND ${BIN2H_HEADER_FILE} "${declarations}")
+ else()
+ file(WRITE ${BIN2H_HEADER_FILE} "${declarations}")
+ endif()
+endfunction()
diff --git a/libethash-cl/cl.hpp b/libethash-cl/cl.hpp
new file mode 100644
index 000000000..a38498762
--- /dev/null
+++ b/libethash-cl/cl.hpp
@@ -0,0 +1,4014 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ ******************************************************************************/
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+/*! \file
+ *
+ * \brief C++ bindings for OpenCL 1.0 (rev 48) and OpenCL 1.1 (rev 33)
+ * \author Benedict R. Gaster and Laurent Morichetti
+ *
+ * Additions and fixes from Brian Cole, March 3rd 2010.
+ *
+ * \version 1.1
+ * \date June 2010
+ *
+ * Optional extension support
+ *
+ * cl
+ * cl_ext_device_fission
+ * #define USE_CL_DEVICE_FISSION
+ */
+
+/*! \mainpage
+ * \section intro Introduction
+ * For many large applications C++ is the language of choice and so it seems
+ * reasonable to define C++ bindings for OpenCL.
+ *
+ *
+ * The interface is contained with a single C++ header file \em cl.hpp and all
+ * definitions are contained within the namespace \em cl. There is no additional
+ * requirement to include \em cl.h and to use either the C++ or original C
+ * bindings it is enough to simply include \em cl.hpp.
+ *
+ * The bindings themselves are lightweight and correspond closely to the
+ * underlying C API. Using the C++ bindings introduces no additional execution
+ * overhead.
+ *
+ * For detail documentation on the bindings see:
+ *
+ * The OpenCL C++ Wrapper API 1.1 (revision 04)
+ * http://www.khronos.org/registry/cl/specs/opencl-cplusplus-1.1.pdf
+ *
+ * \section example Example
+ *
+ * The following example shows a general use case for the C++
+ * bindings, including support for the optional exception feature and
+ * also the supplied vector and string classes, see following sections for
+ * decriptions of these features.
+ *
+ * \code
+ * #define __CL_ENABLE_EXCEPTIONS
+ *
+ * #if defined(__APPLE__) || defined(__MACOSX)
+ * #include
+ * #else
+ * #include
+ * #endif
+ * #include
+ * #include
+ * #include
+ *
+ * const char * helloStr = "__kernel void "
+ * "hello(void) "
+ * "{ "
+ * " "
+ * "} ";
+ *
+ * int
+ * main(void)
+ * {
+ * cl_int err = CL_SUCCESS;
+ * try {
+ *
+ * std::vector platforms;
+ * cl::Platform::get(&platforms);
+ * if (platforms.size() == 0) {
+ * std::cout << "Platform size 0\n";
+ * return -1;
+ * }
+ *
+ * cl_context_properties properties[] =
+ * { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0};
+ * cl::Context context(CL_DEVICE_TYPE_CPU, properties);
+ *
+ * std::vector devices = context.getInfo();
+ *
+ * cl::Program::Sources source(1,
+ * std::make_pair(helloStr,strlen(helloStr)));
+ * cl::Program program_ = cl::Program(context, source);
+ * program_.build(devices);
+ *
+ * cl::Kernel kernel(program_, "hello", &err);
+ *
+ * cl::Event event;
+ * cl::CommandQueue queue(context, devices[0], 0, &err);
+ * queue.enqueueNDRangeKernel(
+ * kernel,
+ * cl::NullRange,
+ * cl::NDRange(4,4),
+ * cl::NullRange,
+ * NULL,
+ * &event);
+ *
+ * event.wait();
+ * }
+ * catch (cl::Error err) {
+ * std::cerr
+ * << "ERROR: "
+ * << err.what()
+ * << "("
+ * << err.err()
+ * << ")"
+ * << std::endl;
+ * }
+ *
+ * return EXIT_SUCCESS;
+ * }
+ *
+ * \endcode
+ *
+ */
+#ifndef CL_HPP_
+#define CL_HPP_
+
+#ifdef _WIN32
+#include
+#include
+#if defined(USE_DX_INTEROP)
+#include
+#endif
+#endif // _WIN32
+
+//
+#if defined(USE_CL_DEVICE_FISSION)
+#include
+#endif
+
+#if defined(__APPLE__) || defined(__MACOSX)
+#include
+#include
+#else
+#include
+#include
+#endif // !__APPLE__
+
+#if !defined(CL_CALLBACK)
+#define CL_CALLBACK
+#endif //CL_CALLBACK
+
+#include
+
+#if !defined(__NO_STD_VECTOR)
+#include
+#endif
+
+#if !defined(__NO_STD_STRING)
+#include
+#endif
+
+#if defined(linux) || defined(__APPLE__) || defined(__MACOSX)
+# include
+#endif // linux
+
+#include
+
+/*! \namespace cl
+ *
+ * \brief The OpenCL C++ bindings are defined within this namespace.
+ *
+ */
+namespace cl {
+
+#define __INIT_CL_EXT_FCN_PTR(name) \
+ if(!pfn_##name) { \
+ pfn_##name = (PFN_##name) \
+ clGetExtensionFunctionAddress(#name); \
+ if(!pfn_##name) { \
+ } \
+ }
+
+class Program;
+class Device;
+class Context;
+class CommandQueue;
+class Memory;
+
+#if defined(__CL_ENABLE_EXCEPTIONS)
+#include
+/*! \class Error
+ * \brief Exception class
+ */
+class Error : public std::exception
+{
+private:
+ cl_int err_;
+ const char * errStr_;
+public:
+ /*! Create a new CL error exception for a given error code
+ * and corresponding message.
+ */
+ Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr)
+ {}
+
+ ~Error() throw() {}
+
+ /*! \brief Get error string associated with exception
+ *
+ * \return A memory pointer to the error message string.
+ */
+ virtual const char * what() const throw ()
+ {
+ if (errStr_ == NULL) {
+ return "empty";
+ }
+ else {
+ return errStr_;
+ }
+ }
+
+ /*! \brief Get error code associated with exception
+ *
+ * \return The error code.
+ */
+ cl_int err(void) const { return err_; }
+};
+
+#define __ERR_STR(x) #x
+#else
+#define __ERR_STR(x) NULL
+#endif // __CL_ENABLE_EXCEPTIONS
+
+//! \cond DOXYGEN_DETAIL
+#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS)
+#define __GET_DEVICE_INFO_ERR __ERR_STR(clgetDeviceInfo)
+#define __GET_PLATFORM_INFO_ERR __ERR_STR(clGetPlatformInfo)
+#define __GET_DEVICE_IDS_ERR __ERR_STR(clGetDeviceIDs)
+#define __GET_PLATFORM_IDS_ERR __ERR_STR(clGetPlatformIDs)
+#define __GET_CONTEXT_INFO_ERR __ERR_STR(clGetContextInfo)
+#define __GET_EVENT_INFO_ERR __ERR_STR(clGetEventInfo)
+#define __GET_EVENT_PROFILE_INFO_ERR __ERR_STR(clGetEventProfileInfo)
+#define __GET_MEM_OBJECT_INFO_ERR __ERR_STR(clGetMemObjectInfo)
+#define __GET_IMAGE_INFO_ERR __ERR_STR(clGetImageInfo)
+#define __GET_SAMPLER_INFO_ERR __ERR_STR(clGetSamplerInfo)
+#define __GET_KERNEL_INFO_ERR __ERR_STR(clGetKernelInfo)
+#define __GET_KERNEL_WORK_GROUP_INFO_ERR __ERR_STR(clGetKernelWorkGroupInfo)
+#define __GET_PROGRAM_INFO_ERR __ERR_STR(clGetProgramInfo)
+#define __GET_PROGRAM_BUILD_INFO_ERR __ERR_STR(clGetProgramBuildInfo)
+#define __GET_COMMAND_QUEUE_INFO_ERR __ERR_STR(clGetCommandQueueInfo)
+
+#define __CREATE_CONTEXT_FROM_TYPE_ERR __ERR_STR(clCreateContextFromType)
+#define __GET_SUPPORTED_IMAGE_FORMATS_ERR __ERR_STR(clGetSupportedImageFormats)
+
+#define __CREATE_BUFFER_ERR __ERR_STR(clCreateBuffer)
+#define __CREATE_SUBBUFFER_ERR __ERR_STR(clCreateSubBuffer)
+#define __CREATE_GL_BUFFER_ERR __ERR_STR(clCreateFromGLBuffer)
+#define __GET_GL_OBJECT_INFO_ERR __ERR_STR(clGetGLObjectInfo)
+#define __CREATE_IMAGE2D_ERR __ERR_STR(clCreateImage2D)
+#define __CREATE_IMAGE3D_ERR __ERR_STR(clCreateImage3D)
+#define __CREATE_SAMPLER_ERR __ERR_STR(clCreateSampler)
+#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR __ERR_STR(clSetMemObjectDestructorCallback)
+
+#define __CREATE_USER_EVENT_ERR __ERR_STR(clCreateUserEvent)
+#define __SET_USER_EVENT_STATUS_ERR __ERR_STR(clSetUserEventStatus)
+#define __SET_EVENT_CALLBACK_ERR __ERR_STR(clSetEventCallback)
+#define __WAIT_FOR_EVENTS_ERR __ERR_STR(clWaitForEvents)
+
+#define __CREATE_KERNEL_ERR __ERR_STR(clCreateKernel)
+#define __SET_KERNEL_ARGS_ERR __ERR_STR(clSetKernelArg)
+#define __CREATE_PROGRAM_WITH_SOURCE_ERR __ERR_STR(clCreateProgramWithSource)
+#define __CREATE_PROGRAM_WITH_BINARY_ERR __ERR_STR(clCreateProgramWithBinary)
+#define __BUILD_PROGRAM_ERR __ERR_STR(clBuildProgram)
+#define __CREATE_KERNELS_IN_PROGRAM_ERR __ERR_STR(clCreateKernelsInProgram)
+
+#define __CREATE_COMMAND_QUEUE_ERR __ERR_STR(clCreateCommandQueue)
+#define __SET_COMMAND_QUEUE_PROPERTY_ERR __ERR_STR(clSetCommandQueueProperty)
+#define __ENQUEUE_READ_BUFFER_ERR __ERR_STR(clEnqueueReadBuffer)
+#define __ENQUEUE_READ_BUFFER_RECT_ERR __ERR_STR(clEnqueueReadBufferRect)
+#define __ENQUEUE_WRITE_BUFFER_ERR __ERR_STR(clEnqueueWriteBuffer)
+#define __ENQUEUE_WRITE_BUFFER_RECT_ERR __ERR_STR(clEnqueueWriteBufferRect)
+#define __ENQEUE_COPY_BUFFER_ERR __ERR_STR(clEnqueueCopyBuffer)
+#define __ENQEUE_COPY_BUFFER_RECT_ERR __ERR_STR(clEnqueueCopyBufferRect)
+#define __ENQUEUE_READ_IMAGE_ERR __ERR_STR(clEnqueueReadImage)
+#define __ENQUEUE_WRITE_IMAGE_ERR __ERR_STR(clEnqueueWriteImage)
+#define __ENQUEUE_COPY_IMAGE_ERR __ERR_STR(clEnqueueCopyImage)
+#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR __ERR_STR(clEnqueueCopyImageToBuffer)
+#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR __ERR_STR(clEnqueueCopyBufferToImage)
+#define __ENQUEUE_MAP_BUFFER_ERR __ERR_STR(clEnqueueMapBuffer)
+#define __ENQUEUE_MAP_IMAGE_ERR __ERR_STR(clEnqueueMapImage)
+#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR __ERR_STR(clEnqueueUnMapMemObject)
+#define __ENQUEUE_NDRANGE_KERNEL_ERR __ERR_STR(clEnqueueNDRangeKernel)
+#define __ENQUEUE_TASK_ERR __ERR_STR(clEnqueueTask)
+#define __ENQUEUE_NATIVE_KERNEL __ERR_STR(clEnqueueNativeKernel)
+#define __ENQUEUE_MARKER_ERR __ERR_STR(clEnqueueMarker)
+#define __ENQUEUE_WAIT_FOR_EVENTS_ERR __ERR_STR(clEnqueueWaitForEvents)
+#define __ENQUEUE_BARRIER_ERR __ERR_STR(clEnqueueBarrier)
+
+#define __ENQUEUE_ACQUIRE_GL_ERR __ERR_STR(clEnqueueAcquireGLObjects)
+#define __ENQUEUE_RELEASE_GL_ERR __ERR_STR(clEnqueueReleaseGLObjects)
+
+#define __UNLOAD_COMPILER_ERR __ERR_STR(clUnloadCompiler)
+
+#define __FLUSH_ERR __ERR_STR(clFlush)
+#define __FINISH_ERR __ERR_STR(clFinish)
+
+#define __CREATE_SUB_DEVICES __ERR_STR(clCreateSubDevicesEXT)
+#endif // __CL_USER_OVERRIDE_ERROR_STRINGS
+//! \endcond
+
+/*! \class string
+ * \brief Simple string class, that provides a limited subset of std::string
+ * functionality but avoids many of the issues that come with that class.
+ */
+class string
+{
+private:
+ ::size_t size_;
+ char * str_;
+public:
+ string(void) : size_(0), str_(NULL)
+ {
+ }
+
+ string(char * str, ::size_t size) :
+ size_(size),
+ str_(NULL)
+ {
+ str_ = new char[size_+1];
+ if (str_ != NULL) {
+ memcpy(str_, str, size_ * sizeof(char));
+ str_[size_] = '\0';
+ }
+ else {
+ size_ = 0;
+ }
+ }
+
+ string(char * str) :
+ str_(NULL)
+ {
+ size_= ::strlen(str);
+ str_ = new char[size_ + 1];
+ if (str_ != NULL) {
+ memcpy(str_, str, (size_ + 1) * sizeof(char));
+ }
+ else {
+ size_ = 0;
+ }
+ }
+
+ string& operator=(const string& rhs)
+ {
+ if (this == &rhs) {
+ return *this;
+ }
+
+ if (rhs.size_ == 0 || rhs.str_ == NULL) {
+ size_ = 0;
+ str_ = NULL;
+ }
+ else {
+ size_ = rhs.size_;
+ str_ = new char[size_ + 1];
+ if (str_ != NULL) {
+ memcpy(str_, rhs.str_, (size_ + 1) * sizeof(char));
+ }
+ else {
+ size_ = 0;
+ }
+ }
+
+ return *this;
+ }
+
+ string(const string& rhs)
+ {
+ *this = rhs;
+ }
+
+ ~string()
+ {
+ if (str_ != NULL) {
+ delete[] str_;
+ }
+ }
+
+ ::size_t size(void) const { return size_; }
+ ::size_t length(void) const { return size(); }
+
+ const char * c_str(void) const { return (str_) ? str_ : "";}
+};
+
+#if !defined(__USE_DEV_STRING) && !defined(__NO_STD_STRING)
+#include
+typedef std::string STRING_CLASS;
+#elif !defined(__USE_DEV_STRING)
+typedef cl::string STRING_CLASS;
+#endif
+
+#if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR)
+#include
+#define VECTOR_CLASS std::vector
+#elif !defined(__USE_DEV_VECTOR)
+#define VECTOR_CLASS cl::vector
+#endif
+
+#if !defined(__MAX_DEFAULT_VECTOR_SIZE)
+#define __MAX_DEFAULT_VECTOR_SIZE 10
+#endif
+
+/*! \class vector
+ * \brief Fixed sized vector implementation that mirroring
+ * std::vector functionality.
+ */
+template
+class vector
+{
+private:
+ T data_[N];
+ unsigned int size_;
+ bool empty_;
+public:
+ vector() :
+ size_(-1),
+ empty_(true)
+ {}
+
+ ~vector() {}
+
+ unsigned int size(void) const
+ {
+ return size_ + 1;
+ }
+
+ void clear()
+ {
+ size_ = -1;
+ empty_ = true;
+ }
+
+ void push_back (const T& x)
+ {
+ if (size() < N) {
+ size_++;
+ data_[size_] = x;
+ empty_ = false;
+ }
+ }
+
+ void pop_back(void)
+ {
+ if (!empty_) {
+ data_[size_].~T();
+ size_--;
+ if (size_ == -1) {
+ empty_ = true;
+ }
+ }
+ }
+
+ vector(const vector& vec) :
+ size_(vec.size_),
+ empty_(vec.empty_)
+ {
+ if (!empty_) {
+ memcpy(&data_[0], &vec.data_[0], size() * sizeof(T));
+ }
+ }
+
+ vector(unsigned int size, const T& val = T()) :
+ size_(-1),
+ empty_(true)
+ {
+ for (unsigned int i = 0; i < size; i++) {
+ push_back(val);
+ }
+ }
+
+ vector& operator=(const vector& rhs)
+ {
+ if (this == &rhs) {
+ return *this;
+ }
+
+ size_ = rhs.size_;
+ empty_ = rhs.empty_;
+
+ if (!empty_) {
+ memcpy(&data_[0], &rhs.data_[0], size() * sizeof(T));
+ }
+
+ return *this;
+ }
+
+ bool operator==(vector &vec)
+ {
+ if (empty_ && vec.empty_) {
+ return true;
+ }
+
+ if (size() != vec.size()) {
+ return false;
+ }
+
+ return memcmp(&data_[0], &vec.data_[0], size() * sizeof(T)) == 0 ? true : false;
+ }
+
+ operator T* () { return data_; }
+ operator const T* () const { return data_; }
+
+ bool empty (void) const
+ {
+ return empty_;
+ }
+
+ unsigned int max_size (void) const
+ {
+ return N;
+ }
+
+ unsigned int capacity () const
+ {
+ return sizeof(T) * N;
+ }
+
+ T& operator[](int index)
+ {
+ return data_[index];
+ }
+
+ T operator[](int index) const
+ {
+ return data_[index];
+ }
+
+ template
+ void assign(I start, I end)
+ {
+ clear();
+ while(start < end) {
+ push_back(*start);
+ start++;
+ }
+ }
+
+ /*! \class iterator
+ * \brief Iterator class for vectors
+ */
+ class iterator
+ {
+ private:
+ vector vec_;
+ int index_;
+ bool initialized_;
+ public:
+ iterator(void) :
+ index_(-1),
+ initialized_(false)
+ {
+ index_ = -1;
+ initialized_ = false;
+ }
+
+ ~iterator(void) {}
+
+ static iterator begin(vector &vec)
+ {
+ iterator i;
+
+ if (!vec.empty()) {
+ i.index_ = 0;
+ }
+
+ i.vec_ = vec;
+ i.initialized_ = true;
+ return i;
+ }
+
+ static iterator end(vector &vec)
+ {
+ iterator i;
+
+ if (!vec.empty()) {
+ i.index_ = vec.size();
+ }
+ i.vec_ = vec;
+ i.initialized_ = true;
+ return i;
+ }
+
+ bool operator==(iterator i)
+ {
+ return ((vec_ == i.vec_) &&
+ (index_ == i.index_) &&
+ (initialized_ == i.initialized_));
+ }
+
+ bool operator!=(iterator i)
+ {
+ return (!(*this==i));
+ }
+
+ void operator++()
+ {
+ index_++;
+ }
+
+ void operator++(int x)
+ {
+ index_ += x;
+ }
+
+ void operator--()
+ {
+ index_--;
+ }
+
+ void operator--(int x)
+ {
+ index_ -= x;
+ }
+
+ T operator *()
+ {
+ return vec_[index_];
+ }
+ };
+
+ iterator begin(void)
+ {
+ return iterator::begin(*this);
+ }
+
+ iterator end(void)
+ {
+ return iterator::end(*this);
+ }
+
+ T& front(void)
+ {
+ return data_[0];
+ }
+
+ T& back(void)
+ {
+ return data_[size_];
+ }
+
+ const T& front(void) const
+ {
+ return data_[0];
+ }
+
+ const T& back(void) const
+ {
+ return data_[size_];
+ }
+};
+
+/*!
+ * \brief size_t class used to interface between C++ and
+ * OpenCL C calls that require arrays of size_t values, who's
+ * size is known statically.
+ */
+template
+struct size_t : public cl::vector< ::size_t, N> { };
+
+namespace detail {
+
+// GetInfo help struct
+template
+struct GetInfoHelper
+{
+ static cl_int
+ get(Functor f, cl_uint name, T* param)
+ {
+ return f(name, sizeof(T), param, NULL);
+ }
+};
+
+// Specialized GetInfoHelper for VECTOR_CLASS params
+template
+struct GetInfoHelper >
+{
+ static cl_int get(Func f, cl_uint name, VECTOR_CLASS* param)
+ {
+ ::size_t required;
+ cl_int err = f(name, 0, NULL, &required);
+ if (err != CL_SUCCESS) {
+ return err;
+ }
+
+ T* value = (T*) alloca(required);
+ err = f(name, required, value, NULL);
+ if (err != CL_SUCCESS) {
+ return err;
+ }
+
+ param->assign(&value[0], &value[required/sizeof(T)]);
+ return CL_SUCCESS;
+ }
+};
+
+// Specialized for getInfo
+template
+struct GetInfoHelper >
+{
+ static cl_int
+ get(Func f, cl_uint name, VECTOR_CLASS* param)
+ {
+ cl_uint err = f(name, param->size() * sizeof(char *), &(*param)[0], NULL);
+ if (err != CL_SUCCESS) {
+ return err;
+ }
+
+ return CL_SUCCESS;
+ }
+};
+
+// Specialized GetInfoHelper for STRING_CLASS params
+template
+struct GetInfoHelper
+{
+ static cl_int get(Func f, cl_uint name, STRING_CLASS* param)
+ {
+ ::size_t required;
+ cl_int err = f(name, 0, NULL, &required);
+ if (err != CL_SUCCESS) {
+ return err;
+ }
+
+ char* value = (char*) alloca(required);
+ err = f(name, required, value, NULL);
+ if (err != CL_SUCCESS) {
+ return err;
+ }
+
+ *param = value;
+ return CL_SUCCESS;
+ }
+};
+
+#define __GET_INFO_HELPER_WITH_RETAIN(CPP_TYPE) \
+namespace detail { \
+template \
+struct GetInfoHelper \
+{ \
+ static cl_int get(Func f, cl_uint name, CPP_TYPE* param) \
+ { \
+ cl_uint err = f(name, sizeof(CPP_TYPE), param, NULL); \
+ if (err != CL_SUCCESS) { \
+ return err; \
+ } \
+ \
+ return ReferenceHandler::retain((*param)()); \
+ } \
+}; \
+}
+
+
+#define __PARAM_NAME_INFO_1_0(F) \
+ F(cl_platform_info, CL_PLATFORM_PROFILE, STRING_CLASS) \
+ F(cl_platform_info, CL_PLATFORM_VERSION, STRING_CLASS) \
+ F(cl_platform_info, CL_PLATFORM_NAME, STRING_CLASS) \
+ F(cl_platform_info, CL_PLATFORM_VENDOR, STRING_CLASS) \
+ F(cl_platform_info, CL_PLATFORM_EXTENSIONS, STRING_CLASS) \
+ \
+ F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \
+ F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, ::size_t) \
+ F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, VECTOR_CLASS< ::size_t>) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \
+ F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_bitfield) \
+ F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \
+ F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, ::size_t) \
+ F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, ::size_t) \
+ F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, ::size_t) \
+ F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, ::size_t) \
+ F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, ::size_t) \
+ F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, ::size_t) \
+ F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \
+ F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \
+ F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \
+ F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\
+ F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \
+ F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \
+ F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \
+ F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \
+ F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \
+ F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \
+ F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \
+ F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, ::size_t) \
+ F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \
+ F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \
+ F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \
+ F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \
+ F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties) \
+ F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \
+ F(cl_device_info, CL_DEVICE_NAME, STRING_CLASS) \
+ F(cl_device_info, CL_DEVICE_VENDOR, STRING_CLASS) \
+ F(cl_device_info, CL_DRIVER_VERSION, STRING_CLASS) \
+ F(cl_device_info, CL_DEVICE_PROFILE, STRING_CLASS) \
+ F(cl_device_info, CL_DEVICE_VERSION, STRING_CLASS) \
+ F(cl_device_info, CL_DEVICE_EXTENSIONS, STRING_CLASS) \
+ \
+ F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \
+ F(cl_context_info, CL_CONTEXT_DEVICES, VECTOR_CLASS) \
+ F(cl_context_info, CL_CONTEXT_PROPERTIES, VECTOR_CLASS) \
+ \
+ F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \
+ F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \
+ F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \
+ F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_uint) \
+ \
+ F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \
+ F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \
+ F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \
+ F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \
+ \
+ F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \
+ F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \
+ F(cl_mem_info, CL_MEM_SIZE, ::size_t) \
+ F(cl_mem_info, CL_MEM_HOST_PTR, void*) \
+ F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \
+ F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \
+ F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \
+ \
+ F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \
+ F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, ::size_t) \
+ F(cl_image_info, CL_IMAGE_ROW_PITCH, ::size_t) \
+ F(cl_image_info, CL_IMAGE_SLICE_PITCH, ::size_t) \
+ F(cl_image_info, CL_IMAGE_WIDTH, ::size_t) \
+ F(cl_image_info, CL_IMAGE_HEIGHT, ::size_t) \
+ F(cl_image_info, CL_IMAGE_DEPTH, ::size_t) \
+ \
+ F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \
+ F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \
+ F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_addressing_mode) \
+ F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_filter_mode) \
+ F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_bool) \
+ \
+ F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \
+ F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \
+ F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \
+ F(cl_program_info, CL_PROGRAM_DEVICES, VECTOR_CLASS) \
+ F(cl_program_info, CL_PROGRAM_SOURCE, STRING_CLASS) \
+ F(cl_program_info, CL_PROGRAM_BINARY_SIZES, VECTOR_CLASS< ::size_t>) \
+ F(cl_program_info, CL_PROGRAM_BINARIES, VECTOR_CLASS) \
+ \
+ F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \
+ F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, STRING_CLASS) \
+ F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, STRING_CLASS) \
+ \
+ F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, STRING_CLASS) \
+ F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \
+ F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \
+ F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \
+ F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \
+ \
+ F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, ::size_t) \
+ F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::size_t<3>) \
+ F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \
+ \
+ F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \
+ F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \
+ F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \
+ F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties)
+
+#if defined(CL_VERSION_1_1)
+#define __PARAM_NAME_INFO_1_1(F) \
+ F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\
+ F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \
+ F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \
+ F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \
+ F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \
+ F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool) \
+ \
+ F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \
+ F(cl_mem_info, CL_MEM_OFFSET, ::size_t) \
+ \
+ F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, ::size_t) \
+ F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \
+ \
+ F(cl_event_info, CL_EVENT_CONTEXT, cl::Context)
+#endif // CL_VERSION_1_1
+
+#if defined(USE_CL_DEVICE_FISSION)
+#define __PARAM_NAME_DEVICE_FISSION(F) \
+ F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \
+ F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, VECTOR_CLASS) \
+ F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, VECTOR_CLASS) \
+ F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \
+ F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, VECTOR_CLASS)
+#endif // USE_CL_DEVICE_FISSION
+
+template
+struct param_traits {};
+
+#define __DECLARE_PARAM_TRAITS(token, param_name, T) \
+struct token; \
+template<> \
+struct param_traits \
+{ \
+ enum { value = param_name }; \
+ typedef T param_type; \
+};
+
+__PARAM_NAME_INFO_1_0(__DECLARE_PARAM_TRAITS)
+#if defined(CL_VERSION_1_1)
+__PARAM_NAME_INFO_1_1(__DECLARE_PARAM_TRAITS)
+#endif // CL_VERSION_1_1
+
+#if defined(USE_CL_DEVICE_FISSION)
+__PARAM_NAME_DEVICE_FISSION(__DECLARE_PARAM_TRAITS);
+#endif // USE_CL_DEVICE_FISSION
+
+#undef __DECLARE_PARAM_TRAITS
+
+// Convenience functions
+
+template
+inline cl_int
+getInfo(Func f, cl_uint name, T* param)
+{
+ return GetInfoHelper::get(f, name, param);
+}
+
+template
+struct GetInfoFunctor0
+{
+ Func f_; const Arg0& arg0_;
+ cl_int operator ()(
+ cl_uint param, ::size_t size, void* value, ::size_t* size_ret)
+ { return f_(arg0_, param, size, value, size_ret); }
+};
+
+template
+struct GetInfoFunctor1
+{
+ Func f_; const Arg0& arg0_; const Arg1& arg1_;
+ cl_int operator ()(
+ cl_uint param, ::size_t size, void* value, ::size_t* size_ret)
+ { return f_(arg0_, arg1_, param, size, value, size_ret); }
+};
+
+template
+inline cl_int
+getInfo(Func f, const Arg0& arg0, cl_uint name, T* param)
+{
+ GetInfoFunctor0 f0 = { f, arg0 };
+ return GetInfoHelper, T>
+ ::get(f0, name, param);
+}
+
+template
+inline cl_int
+getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param)
+{
+ GetInfoFunctor1 f0 = { f, arg0, arg1 };
+ return GetInfoHelper, T>
+ ::get(f0, name, param);
+}
+
+template