Commit 7c67a86d authored by Dominik Charousset's avatar Dominik Charousset

Merge branch 'develop'

parents 14467ae0 99fcd2b1
...@@ -22,6 +22,9 @@ endif() ...@@ -22,6 +22,9 @@ endif()
if(NOT CAF_BUILD_STATIC) if(NOT CAF_BUILD_STATIC)
set(CAF_BUILD_STATIC no) set(CAF_BUILD_STATIC no)
endif() endif()
if(NOT CAF_NO_OPENCL)
set(CAF_NO_OPENCL no)
endif()
################################################################################ ################################################################################
...@@ -98,31 +101,83 @@ if(NOT WIN32 AND NOT NO_COMPILER_CHECK) ...@@ -98,31 +101,83 @@ if(NOT WIN32 AND NOT NO_COMPILER_CHECK)
"or is not supported") "or is not supported")
endif() endif()
endif() endif()
# set optional build flags
set(EXTRA_FLAGS "")
# add "-Werror" flag if --pedantic-build is used
if(CXX_WARNINGS_AS_ERROS)
set(EXTRA_FLAGS "-Werror")
endif()
# enable a ton of warnings if --more-clang-warnings is used
if(MORE_WARNINGS)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(WFLAGS "-Weverything -Wno-c++98-compat -Wno-padded "
"-Wno-documentation-unknown-command -Wno-exit-time-destructors "
"-Wno-global-constructors -Wno-missing-prototypes "
"-Wno-c++98-compat-pedantic -Wno-unused-member-function "
"-Wno-unused-const-variable -Wno-switch-enum "
"-Wno-missing-noreturn -Wno-covered-switch-default")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(WFLAGS "-Waddress -Wall -Warray-bounds "
"-Wattributes -Wbuiltin-macro-redefined -Wcast-align "
"-Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment "
"-Wconversion -Wconversion-null -Wcoverage-mismatch "
"-Wcpp -Wdelete-non-virtual-dtor -Wdeprecated "
"-Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion "
"-Wempty-body -Wendif-labels -Wenum-compare -Wextra "
"-Wfloat-equal -Wformat -Wfree-nonheap-object "
"-Wignored-qualifiers -Winit-self "
"-Winline -Wint-to-pointer-cast -Winvalid-memory-model "
"-Winvalid-offsetof -Wlogical-op -Wmain -Wmaybe-uninitialized "
"-Wmissing-braces -Wmissing-field-initializers -Wmultichar "
"-Wnarrowing -Wnoexcept -Wnon-template-friend "
"-Wnon-virtual-dtor -Wnonnull -Woverflow "
"-Woverlength-strings -Wparentheses "
"-Wpmf-conversions -Wpointer-arith -Wreorder "
"-Wreturn-type -Wsequence-point -Wshadow "
"-Wsign-compare -Wswitch -Wtype-limits -Wundef "
"-Wuninitialized -Wunused -Wvla -Wwrite-strings")
endif()
# convert CMake list to a single string, erasing the ";" separators
string(REPLACE ";" "" WFLAGS_STR ${WFLAGS})
set(EXTRA_FLAGS "${EXTRA_FLAGS} ${WFLAGS_STR}")
endif()
# add -stdlib=libc++ when using Clang
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
message(STATUS "NOTE: Automatically added -stdlib=libc++ flag, "
"you can override this by defining CMAKE_CXX_FLAGS "
"(see 'configure --help')")
set(EXTRA_FLAGS "${EXTRA_FLAGS} -stdlib=libc++")
endif()
# enable address sanitizer if requested by the user
if(ENABLE_ADDRESS_SANITIZER)
# check whether address sanitizer is available
set(CXXFLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
try_run(ProgramResult
CompilationSucceeded
"${CMAKE_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/get_compiler_version.cpp")
if(NOT CompilationSucceeded)
message(WARNING "Address Sanitizer is not available on selected compiler")
else()
message(STATUS "Enable Address Sanitizer")
set(EXTRA_FLAGS "${EXTRA_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
endif()
# restore CXX flags
set(CMAKE_CXX_FLAGS "${CXXFLAGS_BACKUP}")
endif(ENABLE_ADDRESS_SANITIZER)
# -pthread is ignored on MacOSX but required on other platforms
if(NOT APPLE AND NOT WIN32)
set(EXTRA_FLAGS "${EXTRA_FLAGS} -pthread")
endif()
# check if the user provided CXXFLAGS, set defaults otherwise # check if the user provided CXXFLAGS, set defaults otherwise
if(CMAKE_CXX_FLAGS) if(CMAKE_CXX_FLAGS)
set(CXXFLAGS_PROVIDED true)
set(CMAKE_CXX_FLAGS_DEBUG "") set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_MINSIZEREL "") set(CMAKE_CXX_FLAGS_MINSIZEREL "")
set(CMAKE_CXX_FLAGS_RELEASE "") set(CMAKE_CXX_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
else() else()
set(CXXFLAGS_PROVIDED false) set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic -fPIC ${EXTRA_FLAGS}")
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
message(STATUS "NOTE: Automatically added -stdlib=libc++ flag, "
"you can override this by defining CMAKE_CXX_FLAGS "
"(see 'configure --help')")
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -fPIC")
if(MORE_CLANG_WARNINGS)
set(CMAKE_CXX_FLAGS "-pedantic -Weverything -Wno-c++98-compat "
"-Wno-padded -Wno-documentation-unknown-command "
"-Wno-exit-time-destructors -Wno-global-constructors "
"-Wno-missing-prototypes -Wno-c++98-compat-pedantic "
"-Wno-unused-member-function "
"-Wno-unused-const-variable")
endif()
else()
set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic -fPIC")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
...@@ -132,16 +187,6 @@ endif() ...@@ -132,16 +187,6 @@ endif()
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo) set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif() endif()
# enable clang's address sanitizer if requested by the user
if(ENABLE_ADDRESS_SANITIZER)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
message(STATUS "Enable address sanitizer")
endif(ENABLE_ADDRESS_SANITIZER)
# -pthread is ignored on MacOSX, enable it for all other platforms
if(NOT APPLE AND NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
# extra setup steps needed on MinGW # extra setup steps needed on MinGW
if(MINGW) if(MINGW)
add_definitions(-D_WIN32_WINNT=0x0600) add_definitions(-D_WIN32_WINNT=0x0600)
...@@ -184,7 +229,7 @@ install(DIRECTORY libcaf_core/cppa/ ...@@ -184,7 +229,7 @@ install(DIRECTORY libcaf_core/cppa/
install(DIRECTORY libcaf_io/caf/ DESTINATION include/caf install(DIRECTORY libcaf_io/caf/ DESTINATION include/caf
FILES_MATCHING PATTERN "*.hpp") FILES_MATCHING PATTERN "*.hpp")
# install includes from opencl # install includes from opencl
if(EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/caf") if(EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/CMakeLists.txt")
install(DIRECTORY libcaf_opencl/caf/ DESTINATION include/caf install(DIRECTORY libcaf_opencl/caf/ DESTINATION include/caf
FILES_MATCHING PATTERN "*.hpp") FILES_MATCHING PATTERN "*.hpp")
endif() endif()
...@@ -208,7 +253,7 @@ set(LIBCAF_INCLUDE_DIRS ...@@ -208,7 +253,7 @@ set(LIBCAF_INCLUDE_DIRS
"${CMAKE_SOURCE_DIR}/libcaf_core" "${CMAKE_SOURCE_DIR}/libcaf_core"
"${CMAKE_SOURCE_DIR}/libcaf_io") "${CMAKE_SOURCE_DIR}/libcaf_io")
# path to caf opencl headers # path to caf opencl headers
if(EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/caf") if(EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/CMakeLists.txt")
set(LIBCAF_INCLUDE_DIRS set(LIBCAF_INCLUDE_DIRS
"${CMAKE_SOURCE_DIR}/libcaf_opencl/" "${LIBCAF_INCLUDE_DIRS}") "${CMAKE_SOURCE_DIR}/libcaf_opencl/" "${LIBCAF_INCLUDE_DIRS}")
endif() endif()
...@@ -230,7 +275,7 @@ add_subdirectory(libcaf_io) ...@@ -230,7 +275,7 @@ add_subdirectory(libcaf_io)
# set io lib for sub directories # set io lib for sub directories
set(LIBCAF_IO_LIBRARY libcaf_io) set(LIBCAF_IO_LIBRARY libcaf_io)
# set opencl lib for sub directories if not told otherwise # set opencl lib for sub directories if not told otherwise
if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/caf") if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/CMakeLists.txt")
message(STATUS "Enter subdirectory libcaf_opencl") message(STATUS "Enter subdirectory libcaf_opencl")
find_package(OPENCL REQUIRED) find_package(OPENCL REQUIRED)
add_subdirectory(libcaf_opencl) add_subdirectory(libcaf_opencl)
...@@ -253,7 +298,7 @@ if(NOT CAF_NO_UNIT_TESTS) ...@@ -253,7 +298,7 @@ if(NOT CAF_NO_UNIT_TESTS)
message(STATUS "Enter subdirectory unit_testing") message(STATUS "Enter subdirectory unit_testing")
add_subdirectory(unit_testing) add_subdirectory(unit_testing)
add_dependencies(all_unit_tests libcaf_io) add_dependencies(all_unit_tests libcaf_io)
if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/caf") if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/CMakeLists.txt")
add_subdirectory(libcaf_opencl/unit_testing) add_subdirectory(libcaf_opencl/unit_testing)
endif() endif()
endif() endif()
...@@ -262,13 +307,13 @@ if(NOT CAF_NO_EXAMPLES) ...@@ -262,13 +307,13 @@ if(NOT CAF_NO_EXAMPLES)
message(STATUS "Enter subdirectory examples") message(STATUS "Enter subdirectory examples")
add_subdirectory(examples) add_subdirectory(examples)
add_dependencies(all_examples libcaf_io) add_dependencies(all_examples libcaf_io)
if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/caf") if(NOT CAF_NO_OPENCL AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_opencl/CMakeLists.txt")
add_subdirectory(libcaf_opencl/examples) add_subdirectory(libcaf_opencl/examples)
add_dependencies(opencl_examples libcaf_opencl) add_dependencies(opencl_examples libcaf_opencl)
endif() endif()
endif() endif()
# build RIAC if not being told otherwise # build RIAC if not being told otherwise
if(NOT CAF_NO_RIAC AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_riac/caf/") if(NOT CAF_NO_RIAC AND EXISTS "${CMAKE_SOURCE_DIR}/libcaf_riac/CMakeLists.txt")
message(STATUS "Enter subdirectory probe") message(STATUS "Enter subdirectory probe")
add_subdirectory(libcaf_riac) add_subdirectory(libcaf_riac)
if(CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC) if(CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
...@@ -288,7 +333,7 @@ else() ...@@ -288,7 +333,7 @@ else()
set(CAF_HAS_RIAC no) set(CAF_HAS_RIAC no)
endif() endif()
# build nexus if not being told otherwise # build nexus if not being told otherwise
if(NOT CAF_NO_NEXUS AND EXISTS "${CMAKE_SOURCE_DIR}/nexus/caf/") if(NOT CAF_NO_NEXUS AND EXISTS "${CMAKE_SOURCE_DIR}/nexus/CMakeLists.txt")
if(NOT CAF_HAS_RIAC) if(NOT CAF_HAS_RIAC)
message(WARNING "cannot build nexus without RIAC submodule") message(WARNING "cannot build nexus without RIAC submodule")
set(CAF_NO_NEXUS yes) set(CAF_NO_NEXUS yes)
...@@ -307,7 +352,7 @@ else() ...@@ -307,7 +352,7 @@ else()
set(CAF_NO_NEXUS yes) set(CAF_NO_NEXUS yes)
endif() endif()
# build cash if not being told otherwise # build cash if not being told otherwise
if(NOT CAF_NO_CASH AND EXISTS "${CMAKE_SOURCE_DIR}/cash/caf/") if(NOT CAF_NO_CASH AND EXISTS "${CMAKE_SOURCE_DIR}/cash/CMakeLists.txt")
if(NOT CAF_HAS_RIAC) if(NOT CAF_HAS_RIAC)
message(WARNING "cannot build cash without RIAC submodule") message(WARNING "cannot build cash without RIAC submodule")
set(CAF_NO_CASH yes) set(CAF_NO_CASH yes)
...@@ -326,7 +371,7 @@ else() ...@@ -326,7 +371,7 @@ else()
set(CAF_NO_CASH yes) set(CAF_NO_CASH yes)
endif() endif()
# build benchmarks if not being told otherwise # build benchmarks if not being told otherwise
if(NOT CAF_NO_BENCHMARKS AND EXISTS "${CMAKE_SOURCE_DIR}/benchmarks/caf/") if(NOT CAF_NO_BENCHMARKS AND EXISTS "${CMAKE_SOURCE_DIR}/benchmarks/CMakeLists.txt")
message(STATUS "Enter subdirectory benchmarks") message(STATUS "Enter subdirectory benchmarks")
add_subdirectory(benchmarks) add_subdirectory(benchmarks)
add_dependencies(all_benchmarks libcaf_io) add_dependencies(all_benchmarks libcaf_io)
...@@ -363,6 +408,12 @@ if(DOXYGEN_FOUND) ...@@ -363,6 +408,12 @@ if(DOXYGEN_FOUND)
endif(DOXYGEN_FOUND) endif(DOXYGEN_FOUND)
################################################################################
# Add additional project files to GUI #
################################################################################
add_custom_target(gui_dummy SOURCES configure)
################################################################################ ################################################################################
# print summary # # print summary #
################################################################################ ################################################################################
......
Subproject commit ed985aed8bbd0f3eb6c149beff01a5a32276433f Subproject commit 725fb2bee0e24fe8dce73d1c3896f72f7be2424b
Subproject commit 8d709e6da3796161680c726802ea6152e88eaf08 Subproject commit 429df03e9483483b9fe78a6676b67c5407b5ac11
...@@ -19,6 +19,8 @@ if [ -d "$sourcedir/benchmarks/caf" ] ; then ...@@ -19,6 +19,8 @@ if [ -d "$sourcedir/benchmarks/caf" ] ; then
benchmark_suite_options="\ benchmark_suite_options="\
Benchmark Suite Options: Benchmark Suite Options:
--with-javac=FILE path to Java compiler
--with-java=FILE path to Java Runtime
--with-scalac=FILE path to Scala compiler --with-scalac=FILE path to Scala compiler
--with-erlc=FILE path to Erlang compiler --with-erlc=FILE path to Erlang compiler
--with-charmc=FILE path to Charm++ compiler --with-charmc=FILE path to Charm++ compiler
...@@ -43,8 +45,9 @@ Usage: $0 [OPTION]... [VAR=VALUE]... ...@@ -43,8 +45,9 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--dual-build build using both gcc and clang --dual-build build using both gcc and clang
--build-static build as static and shared library --build-static build as static and shared library
--build-static-only build as static library only --build-static-only build as static library only
--more-clang-warnings enables most of Clang's warning flags --more-warnings enables most warnings
--no-compiler-check disable compiler version check --no-compiler-check disable compiler version check
--warnings-as-errors enables -Werror
Installation Directories: Installation Directories:
--prefix=PREFIX installation directory [/usr/local] --prefix=PREFIX installation directory [/usr/local]
...@@ -73,8 +76,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]... ...@@ -73,8 +76,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
- INFO - INFO
- DEBUG - DEBUG
- TRACE - TRACE
(implicitly sets --enable-debug) --with-address-sanitizer build with address sanitizer if available
--enable-address-sanitizer build with Clang's address sanitizer
Influential Environment Variables (only on first invocation): Influential Environment Variables (only on first invocation):
CXX C++ compiler command CXX C++ compiler command
...@@ -88,7 +90,16 @@ $benchmark_suite_options" ...@@ -88,7 +90,16 @@ $benchmark_suite_options"
# $3 is the cache entry variable value # $3 is the cache entry variable value
append_cache_entry () append_cache_entry ()
{ {
CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3" case "$3" in
*\ * )
# string contains whitespace
CMakeCacheEntries="$CMakeCacheEntries -D \"$1:$2=$3\""
;;
*)
# string contains whitespace
CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3"
;;
esac
} }
# Creates a build directory via CMake. # Creates a build directory via CMake.
...@@ -99,6 +110,7 @@ append_cache_entry () ...@@ -99,6 +110,7 @@ append_cache_entry ()
# $5 is the CMake generator. # $5 is the CMake generator.
configure () configure ()
{ {
CMakeCacheEntries=$CMakeDefaultCache CMakeCacheEntries=$CMakeDefaultCache
if [ -n "$1" ]; then if [ -n "$1" ]; then
...@@ -135,23 +147,23 @@ configure () ...@@ -135,23 +147,23 @@ configure ()
append_cache_entry LIBRARY_OUTPUT_PATH PATH "$absolute_builddir/lib" append_cache_entry LIBRARY_OUTPUT_PATH PATH "$absolute_builddir/lib"
fi fi
if [ -d $workdir ]; then if [ -d "$workdir" ]; then
# If a build directory exists, check if it has a CMake cache. # If a build directory exists, check if it has a CMake cache.
if [ -f $workdir/CMakeCache.txt ]; then if [ -f "$workdir/CMakeCache.txt" ]; then
# If the CMake cache exists, delete it so that this configuration # If the CMake cache exists, delete it so that this configuration
# is not tainted by a previous one. # is not tainted by a previous one.
rm -f $workdir/CMakeCache.txt rm -f "$workdir/CMakeCache.txt"
fi fi
else else
mkdir -p $workdir mkdir -p "$workdir"
fi fi
cd $workdir cd "$workdir"
if [ -n "$5" ]; then if [ -n "$5" ]; then
cmake -G "$5" $CMakeCacheEntries $sourcedir cmake -G "$5" $CMakeCacheEntries "$sourcedir"
else else
cmake $CMakeCacheEntries $sourcedir cmake $CMakeCacheEntries "$sourcedir"
fi fi
echo "# This is the command used to configure this build" > config.status echo "# This is the command used to configure this build" > config.status
...@@ -204,6 +216,10 @@ while [ $# -ne 0 ]; do ...@@ -204,6 +216,10 @@ while [ $# -ne 0 ]; do
append_cache_entry CAF_ENABLE_RUNTIME_CHECKS BOOL yes append_cache_entry CAF_ENABLE_RUNTIME_CHECKS BOOL yes
;; ;;
--enable-address-sanitizer) --enable-address-sanitizer)
echo "*** warning: --enable-address-sanitizer is deprecated, please use --with-address-sanitizer instead"
append_cache_entry ENABLE_ADDRESS_SANITIZER BOOL yes
;;
--with-address-sanitizer)
append_cache_entry ENABLE_ADDRESS_SANITIZER BOOL yes append_cache_entry ENABLE_ADDRESS_SANITIZER BOOL yes
;; ;;
--no-memory-management) --no-memory-management)
...@@ -216,12 +232,15 @@ while [ $# -ne 0 ]; do ...@@ -216,12 +232,15 @@ while [ $# -ne 0 ]; do
--standalone-build) --standalone-build)
echo "*** WARNING: --standalone-build is deprecated" echo "*** WARNING: --standalone-build is deprecated"
;; ;;
--more-clang-warnings) --more-warnings)
append_cache_entry MORE_CLANG_WARNINGS BOOL yes append_cache_entry MORE_WARNINGS BOOL yes
;; ;;
--no-compiler-check) --no-compiler-check)
append_cache_entry NO_COMPILER_CHECK BOOL yes append_cache_entry NO_COMPILER_CHECK BOOL yes
;; ;;
--warnings-as-errors)
append_cache_entry CXX_WARNINGS_AS_ERROS BOOL yes
;;
--with-log-level=*) --with-log-level=*)
level=`echo "$optarg" | tr '[:lower:]' '[:upper:]'` level=`echo "$optarg" | tr '[:lower:]' '[:upper:]'`
case $level in case $level in
...@@ -256,40 +275,46 @@ while [ $# -ne 0 ]; do ...@@ -256,40 +275,46 @@ while [ $# -ne 0 ]; do
append_cache_entry CMAKE_BUILD_TYPE STRING $optarg append_cache_entry CMAKE_BUILD_TYPE STRING $optarg
;; ;;
--build-dir=*) --build-dir=*)
builddir=$optarg builddir="$optarg"
;; ;;
--bin-dir=*) --bin-dir=*)
bindir=$optarg bindir="$optarg"
;; ;;
--lib-dir=*) --lib-dir=*)
libdir=$optarg libdir="$optarg"
;; ;;
--dual-build) --dual-build)
dualbuild=1 dualbuild=1
;; ;;
--no-examples) --no-examples)
append_cache_entry CAF_NO_EXAMPLES STRING yes append_cache_entry CAF_NO_EXAMPLES BOOL yes
;; ;;
--no-qt-examples) --no-qt-examples)
append_cache_entry CAF_NO_QT_EXAMPLES STRING yes append_cache_entry CAF_NO_QT_EXAMPLES BOOL yes
;; ;;
--no-protobuf-examples) --no-protobuf-examples)
append_cache_entry CAF_NO_PROTOBUF_EXAMPLES STRING yes append_cache_entry CAF_NO_PROTOBUF_EXAMPLES BOOL yes
;; ;;
--no-curl-examples) --no-curl-examples)
append_cache_entry CAF_NO_CURL_EXAMPLES STRING yes append_cache_entry CAF_NO_CURL_EXAMPLES BOOL yes
;; ;;
--no-unit-tests) --no-unit-tests)
append_cache_entry CAF_NO_UNIT_TESTS STRING yes append_cache_entry CAF_NO_UNIT_TESTS BOOL yes
;; ;;
--no-opencl) --no-opencl)
append_cache_entry CAF_NO_OPENCL STRING yes append_cache_entry CAF_NO_OPENCL BOOL yes
;; ;;
--build-static) --build-static)
append_cache_entry CAF_BUILD_STATIC STRING yes append_cache_entry CAF_BUILD_STATIC BOOL yes
;; ;;
--build-static-only) --build-static-only)
append_cache_entry CAF_BUILD_STATIC_ONLY STRING yes append_cache_entry CAF_BUILD_STATIC_ONLY BOOL yes
;;
--with-javac=*)
append_cache_entry CAF_JAVA_COMPILER FILEPATH "$optarg"
;;
--with-java=*)
append_cache_entry CAF_JAVA_BIN FILEPATH "$optarg"
;; ;;
--with-scalac=*) --with-scalac=*)
append_cache_entry CAF_SCALA_COMPILER FILEPATH "$optarg" append_cache_entry CAF_SCALA_COMPILER FILEPATH "$optarg"
......
...@@ -107,6 +107,7 @@ if(NOT CAF_NO_CURL_EXAMPLES) ...@@ -107,6 +107,7 @@ if(NOT CAF_NO_CURL_EXAMPLES)
find_package(CURL) find_package(CURL)
if(CURL_FOUND) if(CURL_FOUND)
add_executable(curl_fuse curl/curl_fuse.cpp) add_executable(curl_fuse curl/curl_fuse.cpp)
include_directories(${CURL_INCLUDE_DIRS})
target_link_libraries(curl_fuse ${CMAKE_DL_LIBS} ${LIBCAF_LIBRARIES} ${PTHREAD_LIBRARIES} ${CURL_LIBRARY}) target_link_libraries(curl_fuse ${CMAKE_DL_LIBS} ${LIBCAF_LIBRARIES} ${PTHREAD_LIBRARIES} ${CURL_LIBRARY})
add_dependencies(curl_fuse all_examples) add_dependencies(curl_fuse all_examples)
endif(CURL_FOUND) endif(CURL_FOUND)
......
...@@ -67,12 +67,25 @@ void write_int(broker* self, connection_handle hdl, T value) { ...@@ -67,12 +67,25 @@ void write_int(broker* self, connection_handle hdl, T value) {
self->flush(hdl); self->flush(hdl);
} }
void write_int(broker* self, connection_handle hdl, uint64_t value) {
// write two uint32 values instead (htonl does not work for 64bit integers)
write_int(self, hdl, static_cast<uint32_t>(value));
write_int(self, hdl, static_cast<uint32_t>(value >> sizeof(uint32_t)));
}
// utility function for reading an ingeger from incoming data // utility function for reading an ingeger from incoming data
template <class T> template <class T>
T read_int(const void* data) { void read_int(const void* data, T& storage) {
T value; memcpy(&storage, data, sizeof(T));
memcpy(&value, data, sizeof(T)); storage = static_cast<T>(ntohl(storage));
return static_cast<T>(ntohl(value)); }
void read_int(const void* data, uint64_t& storage) {
uint32_t first;
uint32_t second;
read_int(data, first);
read_int(reinterpret_cast<const char*>(data) + sizeof(uint32_t), second);
storage = first | (static_cast<uint64_t>(second) << sizeof(uint32_t));
} }
// implemenation of our broker // implemenation of our broker
...@@ -115,12 +128,14 @@ behavior broker_impl(broker* self, connection_handle hdl, const actor& buddy) { ...@@ -115,12 +128,14 @@ behavior broker_impl(broker* self, connection_handle hdl, const actor& buddy) {
}, },
[=](const new_data_msg& msg) { [=](const new_data_msg& msg) {
// read the atom value as uint64_t from buffer // read the atom value as uint64_t from buffer
auto atm_val = read_int<uint64_t>(msg.buf.data()); uint64_t atm_val;
read_int(msg.buf.data(), atm_val);
// cast to original type // cast to original type
auto atm = static_cast<atom_value>(atm_val); auto atm = static_cast<atom_value>(atm_val);
// read integer value from buffer, jumping to the correct // read integer value from buffer, jumping to the correct
// position via offset_data(...) // position via offset_data(...)
auto ival = read_int<int32_t>(msg.buf.data() + sizeof(uint64_t)); int32_t ival;
read_int(msg.buf.data() + sizeof(uint64_t), ival);
// show some output // show some output
aout(self) << "received {" << to_string(atm) << ", " << ival << "}" aout(self) << "received {" << to_string(atm) << ", " << ival << "}"
<< endl; << endl;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
// C++ includes // C++ includes
#include <string> #include <string>
#include <vector> #include <vector>
#include <random>
#include <iostream> #include <iostream>
// libcurl // libcurl
...@@ -46,7 +47,7 @@ ...@@ -46,7 +47,7 @@
// libcaf // libcaf
#include "caf/all.hpp" #include "caf/all.hpp"
// disable some clang warnings here caused by CURL and srand(time(nullptr)) // disable some clang warnings here caused by CURL
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic ignored "-Wshorten-64-to-32" # pragma clang diagnostic ignored "-Wshorten-64-to-32"
# pragma clang diagnostic ignored "-Wdisabled-macro-expansion" # pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
...@@ -101,6 +102,8 @@ class base_actor : public event_based_actor { ...@@ -101,6 +102,8 @@ class base_actor : public event_based_actor {
// nop // nop
} }
~base_actor();
inline actor_ostream& print() { inline actor_ostream& print() {
return m_out << m_color << m_name << " (id = " << id() << "): "; return m_out << m_color << m_name << " (id = " << id() << "): ";
} }
...@@ -117,6 +120,10 @@ class base_actor : public event_based_actor { ...@@ -117,6 +120,10 @@ class base_actor : public event_based_actor {
actor_ostream m_out; actor_ostream m_out;
}; };
base_actor::~base_actor() {
// avoid weak-vtables warning
}
// encapsulates an HTTP request // encapsulates an HTTP request
class client_job : public base_actor { class client_job : public base_actor {
public: public:
...@@ -125,6 +132,8 @@ class client_job : public base_actor { ...@@ -125,6 +132,8 @@ class client_job : public base_actor {
// nop // nop
} }
~client_job();
protected: protected:
behavior make_behavior() override { behavior make_behavior() override {
print() << "init" << color::reset_endl; print() << "init" << color::reset_endl;
...@@ -149,15 +158,24 @@ class client_job : public base_actor { ...@@ -149,15 +158,24 @@ class client_job : public base_actor {
} }
}; };
client_job::~client_job() {
// avoid weak-vtables warning
}
// spawns HTTP requests // spawns HTTP requests
class client : public base_actor { class client : public base_actor {
public: public:
client(const actor& parent) client(const actor& parent)
: base_actor(parent, "client", color::green), m_count(0) { : base_actor(parent, "client", color::green),
m_count(0),
m_re(m_rd()),
m_dist(min_req_interval, max_req_interval) {
// nop // nop
} }
~client();
protected: protected:
behavior make_behavior() override { behavior make_behavior() override {
using std::chrono::milliseconds; using std::chrono::milliseconds;
...@@ -175,7 +193,7 @@ class client : public base_actor { ...@@ -175,7 +193,7 @@ class client : public base_actor {
// and should thus be spawned in a separate thread // and should thus be spawned in a separate thread
spawn<client_job, detached+linked>(m_parent); spawn<client_job, detached+linked>(m_parent);
// compute random delay until next job is launched // compute random delay until next job is launched
auto delay = (rand() + min_req_interval) % max_req_interval; auto delay = m_dist(m_re);
delayed_send(this, milliseconds(delay), atom("next")); delayed_send(this, milliseconds(delay), atom("next"));
} }
); );
...@@ -183,17 +201,25 @@ class client : public base_actor { ...@@ -183,17 +201,25 @@ class client : public base_actor {
private: private:
size_t m_count; size_t m_count;
std::random_device m_rd;
std::default_random_engine m_re;
std::uniform_int_distribution<int> m_dist;
}; };
client::~client() {
// avoid weak-vtables warning
}
// manages a CURL session // manages a CURL session
class curl_worker : public base_actor { class curl_worker : public base_actor {
public: public:
curl_worker(const actor& parent) curl_worker(const actor& parent)
: base_actor(parent, "curl_worker", color::yellow) { : base_actor(parent, "curl_worker", color::yellow) {
// nop // nop
} }
~curl_worker();
protected: protected:
behavior make_behavior() override { behavior make_behavior() override {
print() << "init" << color::reset_endl; print() << "init" << color::reset_endl;
...@@ -203,7 +229,7 @@ class curl_worker : public base_actor { ...@@ -203,7 +229,7 @@ class curl_worker : public base_actor {
return ( return (
on(atom("read"), arg_match) on(atom("read"), arg_match)
>> [=](const std::string& fname, uint64_t offset, uint64_t range) >> [=](const std::string& fname, uint64_t offset, uint64_t range)
-> cow_tuple<atom_value, buffer_type> { -> message {
print() << "read" << color::reset_endl; print() << "read" << color::reset_endl;
for (;;) { for (;;) {
m_buf.clear(); m_buf.clear();
...@@ -241,7 +267,7 @@ class curl_worker : public base_actor { ...@@ -241,7 +267,7 @@ class curl_worker : public base_actor {
<< color::reset_endl; << color::reset_endl;
// tell parent that this worker is done // tell parent that this worker is done
send(m_parent, atom("finished")); send(m_parent, atom("finished"));
return make_cow_tuple(atom("reply"), m_buf); return make_message(atom("reply"), m_buf);
case 404: // file does not exist case 404: // file does not exist
print() << "http error: download failed with " print() << "http error: download failed with "
<< "'HTTP RETURN CODE': 404 (file does " << "'HTTP RETURN CODE': 404 (file does "
...@@ -275,6 +301,11 @@ class curl_worker : public base_actor { ...@@ -275,6 +301,11 @@ class curl_worker : public base_actor {
buffer_type m_buf; buffer_type m_buf;
}; };
curl_worker::~curl_worker() {
// avoid weak-vtables warning
}
// manages {num_curl_workers} workers with a round-robin protocol // manages {num_curl_workers} workers with a round-robin protocol
class curl_master : public base_actor { class curl_master : public base_actor {
public: public:
...@@ -282,6 +313,8 @@ class curl_master : public base_actor { ...@@ -282,6 +313,8 @@ class curl_master : public base_actor {
// nop // nop
} }
~curl_master();
protected: protected:
behavior make_behavior() override { behavior make_behavior() override {
print() << "init" << color::reset_endl; print() << "init" << color::reset_endl;
...@@ -337,12 +370,17 @@ class curl_master : public base_actor { ...@@ -337,12 +370,17 @@ class curl_master : public base_actor {
std::vector<actor> m_busy_worker; std::vector<actor> m_busy_worker;
}; };
curl_master::~curl_master() {
// avoid weak-vtables warning
}
// signal handling for ctrl+c // signal handling for ctrl+c
namespace {
std::atomic<bool> shutdown_flag{false}; std::atomic<bool> shutdown_flag{false};
} // namespace <anonymous>
int main() { int main() {
// random number setup // random number setup
srand(time(nullptr));
// install signal handler // install signal handler
struct sigaction act; struct sigaction act;
act.sa_handler = [](int) { shutdown_flag = true; }; act.sa_handler = [](int) { shutdown_flag = true; };
......
...@@ -80,9 +80,10 @@ void tester(event_based_actor* self, const calculator_type& testee) { ...@@ -80,9 +80,10 @@ void tester(event_based_actor* self, const calculator_type& testee) {
int main() { int main() {
// announce custom message types // announce custom message types
announce<shutdown_request>(); announce<shutdown_request>("shutdown_request");
announce<plus_request>(&plus_request::a, &plus_request::b); announce<plus_request>("plus_request", &plus_request::a, &plus_request::b);
announce<minus_request>(&minus_request::a, &minus_request::b); announce<minus_request>("minus_request", &minus_request::a,
&minus_request::b);
// test function-based impl // test function-based impl
spawn(tester, spawn_typed(typed_calculator)); spawn(tester, spawn_typed(typed_calculator));
await_all_actors_done(); await_all_actors_done();
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
* - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n bob * * - ./build/bin/group_chat -g remote:chatroom@localhost:4242 -n bob *
\ ******************************************************************************/ \ ******************************************************************************/
#include <cstdlib>
#include <string> #include <string>
#include <cstdlib>
#include <iostream> #include <iostream>
#include "caf/all.hpp" #include "caf/all.hpp"
...@@ -20,9 +20,9 @@ using namespace caf; ...@@ -20,9 +20,9 @@ using namespace caf;
optional<uint16_t> to_port(const string& arg) { optional<uint16_t> to_port(const string& arg) {
char* last = nullptr; char* last = nullptr;
auto res = strtol(arg.c_str(), &last, 10); auto res = strtoul(arg.c_str(), &last, 10);
if (last == (arg.c_str() + arg.size()) && res > 1024) { if (last == (arg.c_str() + arg.size()) && res <= 65536) {
return res; return static_cast<uint16_t>(res);
} }
return none; return none;
} }
......
...@@ -77,11 +77,11 @@ int main(int, char**) { ...@@ -77,11 +77,11 @@ int main(int, char**) {
// announces foo to the libcaf type system; // announces foo to the libcaf type system;
// the function expects member pointers to all elements of foo // the function expects member pointers to all elements of foo
announce<foo>(&foo::a, &foo::b); announce<foo>("foo", &foo::a, &foo::b);
// announce foo2 to the libcaf type system, // announce foo2 to the libcaf type system,
// note that recursive containers are managed automatically by libcaf // note that recursive containers are managed automatically by libcaf
announce<foo2>(&foo2::a, &foo2::b); announce<foo2>("foo2", &foo2::a, &foo2::b);
foo2 vd; foo2 vd;
vd.a = 5; vd.a = 5;
...@@ -98,17 +98,11 @@ int main(int, char**) { ...@@ -98,17 +98,11 @@ int main(int, char**) {
assert(vd == vd2); assert(vd == vd2);
// announce std::pair<int, int> to the type system; // announce std::pair<int, int> to the type system
// NOTE: foo_pair is NOT distinguishable from foo_pair2! announce<foo_pair>("foo_pair", &foo_pair::first, &foo_pair::second);
auto uti = announce<foo_pair>(&foo_pair::first, &foo_pair::second);
// since foo_pair and foo_pair2 are not distinguishable since typedefs
// do not 'create' an own type, this announce fails, since
// std::pair<int, int> is already announced
assert(announce<foo_pair2>(&foo_pair2::first, &foo_pair2::second) == uti);
// libcaf returns the same uniform_type_info // libcaf returns the same uniform_type_info
// instance for foo_pair and foo_pair2 // instance for the type aliases foo_pair and foo_pair2
assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>()); assert(uniform_typeid<foo_pair>() == uniform_typeid<foo_pair2>());
// spawn a testee that receives two messages // spawn a testee that receives two messages
...@@ -124,4 +118,3 @@ int main(int, char**) { ...@@ -124,4 +118,3 @@ int main(int, char**) {
shutdown(); shutdown();
return 0; return 0;
} }
...@@ -54,8 +54,8 @@ void testee(event_based_actor* self) { ...@@ -54,8 +54,8 @@ void testee(event_based_actor* self) {
int main(int, char**) { int main(int, char**) {
// if a class uses getter and setter member functions, // if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs. // we pass those to the announce function as { getter, setter } pairs.
announce<foo>(make_pair(&foo::a, &foo::set_a), announce<foo>("foo", make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)); make_pair(&foo::b, &foo::set_b));
{ {
scoped_actor self; scoped_actor self;
auto t = spawn(testee); auto t = spawn(testee);
......
...@@ -68,14 +68,15 @@ int main(int, char**) { ...@@ -68,14 +68,15 @@ int main(int, char**) {
foo_setter s2 = &foo::b; foo_setter s2 = &foo::b;
// equal to example 3 // equal to example 3
announce<foo>(make_pair(g1, s1), make_pair(g2, s2)); announce<foo>("foo", make_pair(g1, s1), make_pair(g2, s2));
// alternative syntax that uses casts instead of variables // alternative syntax that uses casts instead of variables
// (returns false since foo is already announced) // (returns false since foo is already announced)
announce<foo>(make_pair(static_cast<foo_getter>(&foo::a), announce<foo>("foo",
static_cast<foo_setter>(&foo::a)), make_pair(static_cast<foo_getter>(&foo::a),
make_pair(static_cast<foo_getter>(&foo::b), static_cast<foo_setter>(&foo::a)),
static_cast<foo_setter>(&foo::b))); make_pair(static_cast<foo_getter>(&foo::b),
static_cast<foo_setter>(&foo::b)));
// spawn a new testee and send it a foo // spawn a new testee and send it a foo
{ {
......
...@@ -108,23 +108,20 @@ int main(int, char**) { ...@@ -108,23 +108,20 @@ int main(int, char**) {
// it takes a pointer to the non-trivial member as first argument // it takes a pointer to the non-trivial member as first argument
// followed by all "sub-members" either as member pointer or // followed by all "sub-members" either as member pointer or
// { getter, setter } pair // { getter, setter } pair
announce<bar>(compound_member(&bar::f, auto meta_bar_f = [] {
make_pair(&foo::a, &foo::set_a), return compound_member(&bar::f,
make_pair(&foo::b, &foo::set_b)), make_pair(&foo::a, &foo::set_a),
&bar::i); make_pair(&foo::b, &foo::set_b));
};
// with meta_bar_f, we can now announce bar
announce<bar>("bar", meta_bar_f(), &bar::i);
// baz has non-trivial data members with getter/setter pair // baz has non-trivial data members with getter/setter pair
// and getter returning a mutable reference // and getter returning a mutable reference
announce<baz>(compound_member(make_pair(&baz::f, &baz::set_f), announce<baz>("baz", compound_member(make_pair(&baz::f, &baz::set_f),
make_pair(&foo::a, &foo::set_a), make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)), make_pair(&foo::b, &foo::set_b)),
// compound member that has a compound member // compound member that has a compound member
compound_member(&baz::b, compound_member(&baz::b, meta_bar_f(), &bar::i));
compound_member(&bar::f,
make_pair(&foo::a, &foo::set_a),
make_pair(&foo::b, &foo::set_b)),
&bar::i));
// spawn a testee that receives two messages // spawn a testee that receives two messages
auto t = spawn(testee, 2); auto t = spawn(testee, 2);
{ {
......
...@@ -86,9 +86,12 @@ bool operator==(const tree& lhs, const tree& rhs) { ...@@ -86,9 +86,12 @@ bool operator==(const tree& lhs, const tree& rhs) {
// - does have a copy constructor // - does have a copy constructor
// - does provide operator== // - does provide operator==
class tree_type_info : public detail::abstract_uniform_type_info<tree> { class tree_type_info : public detail::abstract_uniform_type_info<tree> {
public:
tree_type_info() : detail::abstract_uniform_type_info<tree>("tree") {
// nop
}
protected: protected:
void serialize(const void* ptr, serializer* sink) const { void serialize(const void* ptr, serializer* sink) const {
// ptr is guaranteed to be a pointer of type tree // ptr is guaranteed to be a pointer of type tree
auto tree_ptr = reinterpret_cast<const tree*>(ptr); auto tree_ptr = reinterpret_cast<const tree*>(ptr);
...@@ -105,7 +108,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> { ...@@ -105,7 +108,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> {
} }
private: private:
void serialize_node(const tree_node& node, serializer* sink) const { void serialize_node(const tree_node& node, serializer* sink) const {
// value, ... children ... // value, ... children ...
sink->write_value(node.value); sink->write_value(node.value);
...@@ -127,7 +129,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> { ...@@ -127,7 +129,6 @@ class tree_type_info : public detail::abstract_uniform_type_info<tree> {
} }
source->end_sequence(); source->end_sequence();
} }
}; };
using tree_vector = std::vector<tree>; using tree_vector = std::vector<tree>;
...@@ -171,7 +172,7 @@ void testee(event_based_actor* self, size_t remaining) { ...@@ -171,7 +172,7 @@ void testee(event_based_actor* self, size_t remaining) {
int main() { int main() {
// the tree_type_info is owned by libcaf after this function call // the tree_type_info is owned by libcaf after this function call
announce(typeid(tree), std::unique_ptr<uniform_type_info>{new tree_type_info}); announce(typeid(tree), std::unique_ptr<uniform_type_info>{new tree_type_info});
announce<tree_vector>(); announce<tree_vector>("tree_vector");
tree t0; // create a tree and fill it with some data tree t0; // create a tree and fill it with some data
......
...@@ -38,13 +38,13 @@ set (LIBCAF_CORE_SRCS ...@@ -38,13 +38,13 @@ set (LIBCAF_CORE_SRCS
src/continue_helper.cpp src/continue_helper.cpp
src/decorated_tuple.cpp src/decorated_tuple.cpp
src/default_attachable.cpp src/default_attachable.cpp
src/demangle.cpp
src/deserializer.cpp src/deserializer.cpp
src/duration.cpp src/duration.cpp
src/event_based_actor.cpp src/event_based_actor.cpp
src/exception.cpp src/exception.cpp
src/execution_unit.cpp src/execution_unit.cpp
src/exit_reason.cpp src/exit_reason.cpp
src/forwarding_actor_proxy.cpp
src/get_mac_addresses.cpp src/get_mac_addresses.cpp
src/get_root_uuid.cpp src/get_root_uuid.cpp
src/group.cpp src/group.cpp
...@@ -59,9 +59,11 @@ set (LIBCAF_CORE_SRCS ...@@ -59,9 +59,11 @@ set (LIBCAF_CORE_SRCS
src/message_builder.cpp src/message_builder.cpp
src/message_data.cpp src/message_data.cpp
src/message_handler.cpp src/message_handler.cpp
src/message_iterator.cpp
src/node_id.cpp src/node_id.cpp
src/ref_counted.cpp src/ref_counted.cpp
src/response_promise.cpp src/response_promise.cpp
src/replies_to.cpp
src/resumable.cpp src/resumable.cpp
src/ripemd_160.cpp src/ripemd_160.cpp
src/scoped_actor.cpp src/scoped_actor.cpp
...@@ -73,7 +75,7 @@ set (LIBCAF_CORE_SRCS ...@@ -73,7 +75,7 @@ set (LIBCAF_CORE_SRCS
src/string_algorithms.cpp src/string_algorithms.cpp
src/string_serialization.cpp src/string_serialization.cpp
src/sync_request_bouncer.cpp src/sync_request_bouncer.cpp
src/to_uniform_name.cpp src/try_match.cpp
src/uniform_type_info.cpp src/uniform_type_info.cpp
src/uniform_type_info_map.cpp) src/uniform_type_info_map.cpp)
......
...@@ -78,16 +78,12 @@ class abstract_actor : public abstract_channel { ...@@ -78,16 +78,12 @@ class abstract_actor : public abstract_channel {
/** /**
* Attaches `ptr` to this actor. The actor will call `ptr->detach(...)` on * Attaches `ptr` to this actor. The actor will call `ptr->detach(...)` on
* exit, or immediately if it already finished execution. * exit, or immediately if it already finished execution.
* @returns `true` if `ptr` was successfully attached to the actor,
* otherwise (actor already exited) `false`.
*/ */
void attach(attachable_ptr ptr); void attach(attachable_ptr ptr);
/** /**
* Convenience function that attaches the functor `f` to this actor. The * Convenience function that attaches the functor `f` to this actor. The
* actor executes `f()` on exit or immediatley if it is not running. * actor executes `f()` on exit or immediatley if it is not running.
* @returns `true` if `f` was successfully attached to the actor,
* otherwise (actor already exited) `false`.
*/ */
template <class F> template <class F>
void attach_functor(F f) { void attach_functor(F f) {
......
...@@ -149,10 +149,10 @@ class actor : detail::comparable<actor>, ...@@ -149,10 +149,10 @@ class actor : detail::comparable<actor>,
actor_id id() const; actor_id id() const;
private:
void swap(actor& other); void swap(actor& other);
private:
inline abstract_actor* get() const { inline abstract_actor* get() const {
return m_ptr.get(); return m_ptr.get();
} }
......
...@@ -38,8 +38,8 @@ class actor_proxy; ...@@ -38,8 +38,8 @@ class actor_proxy;
using actor_proxy_ptr = intrusive_ptr<actor_proxy>; using actor_proxy_ptr = intrusive_ptr<actor_proxy>;
/** /**
* Represents a remote actor. * Represents an actor running on a remote machine,
* @extends abstract_actor * or different hardware, or in a separate process.
*/ */
class actor_proxy : public abstract_actor { class actor_proxy : public abstract_actor {
public: public:
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "caf/match.hpp" #include "caf/match.hpp"
#include "caf/spawn.hpp" #include "caf/spawn.hpp"
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/either.hpp"
#include "caf/extend.hpp" #include "caf/extend.hpp"
#include "caf/channel.hpp" #include "caf/channel.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
......
...@@ -79,8 +79,8 @@ namespace caf { ...@@ -79,8 +79,8 @@ namespace caf {
*/ */
/** /**
* Adds a new mapping to the type system. Returns `false` if a mapping * Adds a new mapping to the type system. Returns `utype.get()` on
* for `tinfo` already exists, otherwise `true`. * success, otherwise a pointer to the previously installed singleton.
* @warning `announce` is **not** thead-safe! * @warning `announce` is **not** thead-safe!
*/ */
const uniform_type_info* announce(const std::type_info& tinfo, const uniform_type_info* announce(const std::type_info& tinfo,
...@@ -95,7 +95,7 @@ const uniform_type_info* announce(const std::type_info& tinfo, ...@@ -95,7 +95,7 @@ const uniform_type_info* announce(const std::type_info& tinfo,
template <class C, class Parent, class... Ts> template <class C, class Parent, class... Ts>
std::pair<C Parent::*, detail::abstract_uniform_type_info<C>*> std::pair<C Parent::*, detail::abstract_uniform_type_info<C>*>
compound_member(C Parent::*c_ptr, const Ts&... args) { compound_member(C Parent::*c_ptr, const Ts&... args) {
return {c_ptr, new detail::default_uniform_type_info<C>(args...)}; return {c_ptr, new detail::default_uniform_type_info<C>("???", args...)};
} }
// deals with getter returning a mutable reference // deals with getter returning a mutable reference
...@@ -108,7 +108,7 @@ compound_member(C Parent::*c_ptr, const Ts&... args) { ...@@ -108,7 +108,7 @@ compound_member(C Parent::*c_ptr, const Ts&... args) {
template <class C, class Parent, class... Ts> template <class C, class Parent, class... Ts>
std::pair<C& (Parent::*)(), detail::abstract_uniform_type_info<C>*> std::pair<C& (Parent::*)(), detail::abstract_uniform_type_info<C>*>
compound_member(C& (Parent::*getter)(), const Ts&... args) { compound_member(C& (Parent::*getter)(), const Ts&... args) {
return {getter, new detail::default_uniform_type_info<C>(args...)}; return {getter, new detail::default_uniform_type_info<C>("???", args...)};
} }
// deals with getter/setter pair // deals with getter/setter pair
...@@ -126,16 +126,17 @@ compound_member(const std::pair<GRes (Parent::*)() const, ...@@ -126,16 +126,17 @@ compound_member(const std::pair<GRes (Parent::*)() const,
SRes (Parent::*)(SArg)>& gspair, SRes (Parent::*)(SArg)>& gspair,
const Ts&... args) { const Ts&... args) {
using mtype = typename std::decay<GRes>::type; using mtype = typename std::decay<GRes>::type;
return {gspair, new detail::default_uniform_type_info<mtype>(args...)}; return {gspair, new detail::default_uniform_type_info<mtype>("???", args...)};
} }
/** /**
* Adds a new type mapping for `C` to the type system. * Adds a new type mapping for `C` to the type system
* using `tname` as its uniform name.
* @warning `announce` is **not** thead-safe! * @warning `announce` is **not** thead-safe!
*/ */
template <class C, class... Ts> template <class C, class... Ts>
inline const uniform_type_info* announce(const Ts&... args) { inline const uniform_type_info* announce(std::string tname, const Ts&... args) {
auto ptr = new detail::default_uniform_type_info<C>(args...); auto ptr = new detail::default_uniform_type_info<C>(std::move(tname), args...);
return announce(typeid(C), uniform_type_info_ptr{ptr}); return announce(typeid(C), uniform_type_info_ptr{ptr});
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define CAF_ATOM_HPP #define CAF_ATOM_HPP
#include <string> #include <string>
#include <type_traits>
#include "caf/detail/atom_val.hpp" #include "caf/detail/atom_val.hpp"
...@@ -46,6 +47,9 @@ constexpr atom_value atom(char const (&str)[Size]) { ...@@ -46,6 +47,9 @@ constexpr atom_value atom(char const (&str)[Size]) {
return static_cast<atom_value>(detail::atom_val(str, 0xF)); return static_cast<atom_value>(detail::atom_val(str, 0xF));
} }
template <atom_value Value>
using atom_constant = std::integral_constant<atom_value, Value>;
} // namespace caf } // namespace caf
#endif // CAF_ATOM_HPP #endif // CAF_ATOM_HPP
...@@ -44,11 +44,6 @@ class behavior { ...@@ -44,11 +44,6 @@ class behavior {
public: public:
friend class message_handler; friend class message_handler;
/**
* The type of continuations that can be used to extend an existing behavior.
*/
using continuation_fun = std::function<optional<message>(message&)>;
behavior() = default; behavior() = default;
behavior(behavior&&) = default; behavior(behavior&&) = default;
behavior(const behavior&) = default; behavior(const behavior&) = default;
...@@ -115,12 +110,6 @@ class behavior { ...@@ -115,12 +110,6 @@ class behavior {
return (m_impl) ? m_impl->invoke(std::forward<T>(arg)) : none; return (m_impl) ? m_impl->invoke(std::forward<T>(arg)) : none;
} }
/**
* Adds a continuation to this behavior that is executed
* whenever this behavior was successfully applied to a message.
*/
behavior add_continuation(continuation_fun fun);
/** /**
* Checks whether this behavior is not empty. * Checks whether this behavior is not empty.
*/ */
......
...@@ -51,6 +51,8 @@ class blocking_actor ...@@ -51,6 +51,8 @@ class blocking_actor
blocking_actor(); blocking_actor();
~blocking_actor();
/************************************************************************** /**************************************************************************
* utility stuff and receive() member function family * * utility stuff and receive() member function family *
**************************************************************************/ **************************************************************************/
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* whereas each number is a two-digit decimal number without * whereas each number is a two-digit decimal number without
* leading zeros (e.g. 900 is version 0.9.0). * leading zeros (e.g. 900 is version 0.9.0).
*/ */
#define CAF_VERSION 1102 #define CAF_VERSION 1200
#define CAF_MAJOR_VERSION (CAF_VERSION / 10000) #define CAF_MAJOR_VERSION (CAF_VERSION / 10000)
#define CAF_MINOR_VERSION ((CAF_VERSION / 100) % 100) #define CAF_MINOR_VERSION ((CAF_VERSION / 100) % 100)
...@@ -61,7 +61,18 @@ ...@@ -61,7 +61,18 @@
_Pragma("clang diagnostic ignored \"-Wconversion\"") \ _Pragma("clang diagnostic ignored \"-Wconversion\"") \
_Pragma("clang diagnostic ignored \"-Wcast-align\"") \ _Pragma("clang diagnostic ignored \"-Wcast-align\"") \
_Pragma("clang diagnostic ignored \"-Wundef\"") \ _Pragma("clang diagnostic ignored \"-Wundef\"") \
_Pragma("clang diagnostic ignored \"-Wnested-anon-types\"") _Pragma("clang diagnostic ignored \"-Wnested-anon-types\"") \
_Pragma("clang diagnostic ignored \"-Wdeprecated\"") \
_Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \
_Pragma("clang diagnostic ignored \"-Wdocumentation\"") \
_Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
_Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"") \
_Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
_Pragma("clang diagnostic ignored \"-Wshorten-64-to-32\"") \
_Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \
_Pragma("clang diagnostic ignored \"-Wundef\"") \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"")
# define CAF_POP_WARNINGS \ # define CAF_POP_WARNINGS \
_Pragma("clang diagnostic pop") _Pragma("clang diagnostic pop")
# define CAF_ANNOTATE_FALLTHROUGH [[clang::fallthrough]] # define CAF_ANNOTATE_FALLTHROUGH [[clang::fallthrough]]
...@@ -104,44 +115,32 @@ ...@@ -104,44 +115,32 @@
# error Platform and/or compiler not supportet # error Platform and/or compiler not supportet
#endif #endif
#include <memory>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
// import backtrace and backtrace_symbols_fd into caf::detail // import backtrace and backtrace_symbols_fd into caf::detail
#ifdef CAF_WINDOWS #ifndef CAF_ENABLE_RUNTIME_CHECKS
#include "caf/detail/execinfo_windows.hpp" # define CAF_REQUIRE(unused) static_cast<void>(0)
#else #elif defined(CAF_WINDOWS) || defined(CAF_BSD)
#include <execinfo.h> # define CAF_REQUIRE(stmt) \
namespace caf { if (static_cast<bool>(stmt) == false) { \
namespace detail { printf("%s:%u: requirement failed '%s'\n", __FILE__, __LINE__, #stmt); \
using ::backtrace; abort(); \
using ::backtrace_symbols_fd; } static_cast<void>(0)
} // namespace detail #else // defined(CAF_LINUX) || defined(CAF_MACOS)
} // namespace caf # include <execinfo.h>
# define CAF_REQUIRE(stmt) \
#endif if (static_cast<bool>(stmt) == false) { \
printf("%s:%u: requirement failed '%s'\n", __FILE__, __LINE__, #stmt); \
#ifdef CAF_ENABLE_RUNTIME_CHECKS void* array[10]; \
# define CAF_REQUIRE__(stmt, file, line) \ auto caf_bt_size = ::backtrace(array, 10); \
printf("%s:%u: requirement failed '%s'\n", file, line, stmt); { \ ::backtrace_symbols_fd(array, caf_bt_size, 2); \
void* array[10]; \ abort(); \
auto caf_bt_size = ::caf::detail::backtrace(array, 10); \
::caf::detail::backtrace_symbols_fd(array, caf_bt_size, 2); \
} abort()
# define CAF_REQUIRE(stmt) \
if (static_cast<bool>(stmt) == false) { \
CAF_REQUIRE__(#stmt, __FILE__, __LINE__); \
} static_cast<void>(0)
#else
# define CAF_REQUIRE(unused) static_cast<void>(0)
#endif
#define CAF_CRITICAL__(error, file, line) { \
printf("%s:%u: critical error: '%s'\n", file, line, error); \
exit(7); \
} static_cast<void>(0) } static_cast<void>(0)
#endif
#define CAF_CRITICAL(error) CAF_CRITICAL__(error, __FILE__, __LINE__) #define CAF_CRITICAL(error) \
printf("%s:%u: critical error: '%s'\n", __FILE__, __LINE__, error); \
abort()
#endif // CAF_CONFIG_HPP #endif // CAF_CONFIG_HPP
...@@ -38,35 +38,17 @@ class local_actor; ...@@ -38,35 +38,17 @@ class local_actor;
class continue_helper { class continue_helper {
public: public:
using message_id_wrapper_tag = int; using message_id_wrapper_tag = int;
using getter = std::function<optional<behavior&> (message_id msg_id)>; continue_helper(message_id mid);
continue_helper(message_id mid, getter get_sync_handler);
/**
* Adds the continuation `fun` to the synchronous message handler
* that is invoked if the response handler successfully returned.
*/
template <class F>
continue_helper& continue_with(F fun) {
return continue_with(behavior::continuation_fun{
message_handler{on(any_vals, arg_match) >> fun}});
}
/**
* Adds the continuation `fun` to the synchronous message handler
* that is invoked if the response handler successfully returned.
*/
continue_helper& continue_with(behavior::continuation_fun fun);
/** /**
* Returns the ID of the expected response message. * Returns the ID of the expected response message.
*/ */
message_id get_message_id() const { return m_mid; } message_id get_message_id() const {
return m_mid;
}
private: private:
message_id m_mid; message_id m_mid;
getter m_getter;
//local_actor* m_self;
}; };
} // namespace caf } // namespace caf
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/to_uniform_name.hpp"
#include "caf/detail/uniform_type_info_map.hpp" #include "caf/detail/uniform_type_info_map.hpp"
namespace caf { namespace caf {
...@@ -61,13 +60,8 @@ class abstract_uniform_type_info : public uniform_type_info { ...@@ -61,13 +60,8 @@ class abstract_uniform_type_info : public uniform_type_info {
protected: protected:
abstract_uniform_type_info() { abstract_uniform_type_info(std::string tname) {
auto uname = detail::to_uniform_name<T>(); m_name = detail::mapped_name_by_decorated_name(std::move(tname));
auto cname = detail::mapped_name_by_decorated_name(uname.c_str());
if (cname == uname.c_str())
m_name = std::move(uname);
else
m_name = cname;
} }
static inline const T& deref(const void* ptr) { static inline const T& deref(const void* ptr) {
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef CAF_DETAIL_APPLY_ARGS_HPP #ifndef CAF_DETAIL_APPLY_ARGS_HPP
#define CAF_DETAIL_APPLY_ARGS_HPP #define CAF_DETAIL_APPLY_ARGS_HPP
#include <utility>
#include "caf/detail/int_list.hpp" #include "caf/detail/int_list.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "caf/intrusive_ptr.hpp" #include "caf/intrusive_ptr.hpp"
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/either.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
#include "caf/duration.hpp" #include "caf/duration.hpp"
#include "caf/ref_counted.hpp" #include "caf/ref_counted.hpp"
...@@ -39,10 +40,6 @@ ...@@ -39,10 +40,6 @@
#include "caf/detail/apply_args.hpp" #include "caf/detail/apply_args.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
// <backward_compatibility version="0.9">
#include "cppa/cow_tuple.hpp"
// </backward_compatibility>
namespace caf { namespace caf {
class message_handler; class message_handler;
...@@ -72,7 +69,8 @@ struct optional_message_visitor_enable_tpl { ...@@ -72,7 +69,8 @@ struct optional_message_visitor_enable_tpl {
skip_message_t, skip_message_t,
optional<skip_message_t> optional<skip_message_t>
>::value >::value
&& !is_message_id_wrapper<T>::value; && !is_message_id_wrapper<T>::value
&& !std::is_convertible<T, message>::value;
}; };
struct optional_message_visitor : static_visitor<bhvr_invoke_result> { struct optional_message_visitor : static_visitor<bhvr_invoke_result> {
...@@ -95,15 +93,19 @@ struct optional_message_visitor : static_visitor<bhvr_invoke_result> { ...@@ -95,15 +93,19 @@ struct optional_message_visitor : static_visitor<bhvr_invoke_result> {
} }
template <class T, class... Ts> template <class T, class... Ts>
typename std::enable_if<optional_message_visitor_enable_tpl<T>::value, typename std::enable_if<
bhvr_invoke_result>::type optional_message_visitor_enable_tpl<T>::value,
bhvr_invoke_result
>::type
operator()(T& v, Ts&... vs) const { operator()(T& v, Ts&... vs) const {
return make_message(std::move(v), std::move(vs)...); return make_message(std::move(v), std::move(vs)...);
} }
template <class T> template <class T>
typename std::enable_if<is_message_id_wrapper<T>::value, typename std::enable_if<
bhvr_invoke_result>::type is_message_id_wrapper<T>::value,
bhvr_invoke_result
>::type
operator()(T& value) const { operator()(T& value) const {
return make_message(atom("MESSAGE_ID"), return make_message(atom("MESSAGE_ID"),
value.get_message_id().integer_value()); value.get_message_id().integer_value());
...@@ -113,17 +115,24 @@ struct optional_message_visitor : static_visitor<bhvr_invoke_result> { ...@@ -113,17 +115,24 @@ struct optional_message_visitor : static_visitor<bhvr_invoke_result> {
return std::move(value); return std::move(value);
} }
template <class L, class R>
bhvr_invoke_result operator()(either_or_t<L, R>& value) const {
return std::move(value.value);
}
template <class... Ts> template <class... Ts>
bhvr_invoke_result operator()(std::tuple<Ts...>& value) const { bhvr_invoke_result operator()(std::tuple<Ts...>& value) const {
return detail::apply_args(*this, detail::get_indices(value), value); return detail::apply_args(*this, detail::get_indices(value), value);
} }
// <backward_compatibility version="0.9"> template <class T>
template <class... Ts> typename std::enable_if<
bhvr_invoke_result operator()(cow_tuple<Ts...>& value) const { std::is_convertible<T, message>::value,
return static_cast<message>(std::move(value)); bhvr_invoke_result
>::type
operator()(const T& value) const {
return static_cast<message>(value);
} }
// </backward_compatibility>
}; };
......
...@@ -27,9 +27,9 @@ namespace detail { ...@@ -27,9 +27,9 @@ namespace detail {
* Barton–Nackman trick implementation. * Barton–Nackman trick implementation.
* `Subclass` must provide a compare member function that compares * `Subclass` must provide a compare member function that compares
* to instances of `T` and returns an integer x with: * to instances of `T` and returns an integer x with:
* - `x < 0</tt> if <tt>*this < other * - `x < 0` if `*this < other`
* - `x > 0</tt> if <tt>*this > other * - `x > 0` if `*this > other`
* - `x == 0</tt> if <tt>*this == other * - `x == 0` if `*this == other`
*/ */
template <class Subclass, class T = Subclass> template <class Subclass, class T = Subclass>
class comparable { class comparable {
......
...@@ -17,43 +17,56 @@ ...@@ -17,43 +17,56 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
/******************************************************************************\ #ifndef CAF_DETAIL_CTM_HPP
* Based on work by the mingw-w64 project; * #define CAF_DETAIL_CTM_HPP
* original header: *
* * #include "caf/replies_to.hpp"
* Copyright (c) 2012 mingw-w64 project *
* * #include "caf/detail/type_list.hpp"
* Contributing author: Kai Tietz * #include "caf/detail/typed_actor_util.hpp"
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is 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 Software. *
* *
* THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
\ ******************************************************************************/
#ifndef CAF_DETAIL_EXECINFO_WINDOWS_HPP
#define CAF_DETAIL_EXECINFO_WINDOWS_HPP
namespace caf { namespace caf {
namespace detail { namespace detail {
int backtrace(void** buffer, int size); // CTM: Compile-Time Match
void backtrace_symbols_fd(void* const* buffer, int size, int fd);
// left hand side is the MPI we are comparing to, this is *not* commutative
template <class A, class B>
struct ctm_cmp : std::false_type { };
template <class T>
struct ctm_cmp<T, T> : std::true_type { };
template <class In, class Out>
struct ctm_cmp<typed_mpi<In, Out, empty_type_list>,
typed_mpi<In, type_list<typed_continue_helper<Out>>, empty_type_list>>
: std::true_type { };
template <class In, class L, class R>
struct ctm_cmp<typed_mpi<In, L, R>,
typed_mpi<In, type_list<skip_message_t>, empty_type_list>>
: std::true_type { };
template <class A, class B>
struct ctm : std::false_type { };
template <>
struct ctm<empty_type_list, empty_type_list> : std::true_type { };
template <class A, class... As, class... Bs>
struct ctm<type_list<A, As...>, type_list<Bs...>>
: std::conditional<
sizeof...(As) + 1 != sizeof...(Bs),
std::false_type,
ctm<type_list<As...>,
typename tl_filter_not<
type_list<Bs...>,
tbind<ctm_cmp, A>::template type
>::type
>
>::type { };
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_EXECINFO_WINDOWS_HPP #endif // CAF_DETAIL_CTM_HPP
...@@ -248,16 +248,22 @@ template <class T, class AccessPolicy, ...@@ -248,16 +248,22 @@ template <class T, class AccessPolicy,
bool IsEmptyType = std::is_class<T>::value&& std::is_empty<T>::value> bool IsEmptyType = std::is_class<T>::value&& std::is_empty<T>::value>
class member_tinfo : public detail::abstract_uniform_type_info<T> { class member_tinfo : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
member_tinfo(AccessPolicy apol, SerializePolicy spol) member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) { : super("--member--"),
m_apol(std::move(apol)), m_spol(std::move(spol)) {
// nop // nop
} }
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) { member_tinfo(AccessPolicy apol)
: super("--member--"),
m_apol(std::move(apol)) {
// nop // nop
} }
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void* vptr, serializer* s) const override { void serialize(const void* vptr, serializer* s) const override {
m_spol(m_apol(vptr), s); m_spol(m_apol(vptr), s);
...@@ -289,15 +295,19 @@ template <class T, class A, class S> ...@@ -289,15 +295,19 @@ template <class T, class A, class S>
class member_tinfo<T, A, S, false, true> class member_tinfo<T, A, S, false, true>
: public detail::abstract_uniform_type_info<T> { : public detail::abstract_uniform_type_info<T> {
public: public:
member_tinfo(const A&, const S&) { using super = detail::abstract_uniform_type_info<T>;
member_tinfo(const A&, const S&) : super("--member--") {
// nop // nop
} }
member_tinfo(const A&) { member_tinfo(const A&) : super("--member--") {
// nop // nop
} }
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void*, serializer*) const override { void serialize(const void*, serializer*) const override {
// nop // nop
...@@ -312,14 +322,24 @@ template <class T, class AccessPolicy, class SerializePolicy> ...@@ -312,14 +322,24 @@ template <class T, class AccessPolicy, class SerializePolicy>
class member_tinfo<T, AccessPolicy, SerializePolicy, true, false> class member_tinfo<T, AccessPolicy, SerializePolicy, true, false>
: public detail::abstract_uniform_type_info<T> { : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
using value_type = typename std::underlying_type<T>::type; using value_type = typename std::underlying_type<T>::type;
member_tinfo(AccessPolicy apol, SerializePolicy spol) member_tinfo(AccessPolicy apol, SerializePolicy spol)
: m_apol(std::move(apol)), m_spol(std::move(spol)) {} : super("--member--"),
m_apol(std::move(apol)), m_spol(std::move(spol)) {
// nop
}
member_tinfo(AccessPolicy apol) : m_apol(std::move(apol)) {} member_tinfo(AccessPolicy apol)
: super("--member--"),
m_apol(std::move(apol)) {
// nop
}
member_tinfo() = default; member_tinfo() : super("--member--") {
// nop
}
void serialize(const void* p, serializer* s) const override { void serialize(const void* p, serializer* s) const override {
auto val = m_apol(p); auto val = m_apol(p);
...@@ -453,12 +473,15 @@ uniform_type_info_ptr new_member_tinfo(GRes (C::*getter)() const, ...@@ -453,12 +473,15 @@ uniform_type_info_ptr new_member_tinfo(GRes (C::*getter)() const,
template <class T> template <class T>
class default_uniform_type_info : public detail::abstract_uniform_type_info<T> { class default_uniform_type_info : public detail::abstract_uniform_type_info<T> {
public: public:
using super = detail::abstract_uniform_type_info<T>;
template <class... Ts> template <class... Ts>
default_uniform_type_info(Ts&&... args) { default_uniform_type_info(std::string tname, Ts&&... args)
: super(std::move(tname)) {
push_back(std::forward<Ts>(args)...); push_back(std::forward<Ts>(args)...);
} }
default_uniform_type_info() { default_uniform_type_info(std::string tname) : super(std::move(tname)) {
using result_type = member_tinfo<T, fake_access_policy<T>>; using result_type = member_tinfo<T, fake_access_policy<T>>;
m_members.push_back(uniform_type_info_ptr(new result_type)); m_members.push_back(uniform_type_info_ptr(new result_type));
} }
...@@ -552,9 +575,10 @@ template <class... Rs> ...@@ -552,9 +575,10 @@ template <class... Rs>
class default_uniform_type_info<typed_actor<Rs...>> : class default_uniform_type_info<typed_actor<Rs...>> :
public detail::abstract_uniform_type_info<typed_actor<Rs...>> { public detail::abstract_uniform_type_info<typed_actor<Rs...>> {
public: public:
using super = detail::abstract_uniform_type_info<typed_actor<Rs...>>;
using handle_type = typed_actor<Rs...>; using handle_type = typed_actor<Rs...>;
default_uniform_type_info() { default_uniform_type_info(std::string tname) : super(std::move(tname)) {
sub_uti = uniform_typeid<actor>(); sub_uti = uniform_typeid<actor>();
} }
......
...@@ -166,7 +166,7 @@ class double_ended_queue { ...@@ -166,7 +166,7 @@ class double_ended_queue {
{ // lifetime scope of guard { // lifetime scope of guard
lock_guard guard(m_head_lock); lock_guard guard(m_head_lock);
first.reset(m_head.load()); first.reset(m_head.load());
node* next = m_head.load()->next; node* next = first->next;
if (next == nullptr) { if (next == nullptr) {
// queue is empty // queue is empty
first.release(); first.release();
......
...@@ -68,7 +68,9 @@ typename ieee_754_trait<T>::packed_type pack754(T f) { ...@@ -68,7 +68,9 @@ typename ieee_754_trait<T>::packed_type pack754(T f) {
typedef ieee_754_trait<T> trait; // using trait = ... fails on GCC 4.7 typedef ieee_754_trait<T> trait; // using trait = ... fails on GCC 4.7
using result_type = typename trait::packed_type; using result_type = typename trait::packed_type;
// filter special type // filter special type
if (fabs(f) <= trait::zero) return 0; // only true if f equals +0 or -0 if (std::fabs(f) <= trait::zero) {
return 0; // only true if f equals +0 or -0
}
auto significandbits = trait::bits - trait::expbits - 1; // -1 for sign bit auto significandbits = trait::bits - trait::expbits - 1; // -1 for sign bit
// check sign and begin normalization // check sign and begin normalization
result_type sign; result_type sign;
...@@ -92,14 +94,14 @@ typename ieee_754_trait<T>::packed_type pack754(T f) { ...@@ -92,14 +94,14 @@ typename ieee_754_trait<T>::packed_type pack754(T f) {
} }
fnorm = fnorm - static_cast<T>(1); fnorm = fnorm - static_cast<T>(1);
// calculate 2^significandbits // calculate 2^significandbits
auto pownum = static_cast<result_type>(1) << significandbits; auto pownum = static_cast<T>(result_type{1} << significandbits);
// calculate the binary form (non-float) of the significand data // calculate the binary form (non-float) of the significand data
auto significand = static_cast<result_type>(fnorm * (pownum + trait::p5)); auto significand = static_cast<result_type>(fnorm * (pownum + trait::p5));
// get the biased exponent // get the biased exponent
auto exp = shift + ((1 << (trait::expbits - 1)) - 1); // shift + bias auto exp = shift + ((1 << (trait::expbits - 1)) - 1); // shift + bias
// return the final answer // return the final answer
return (sign << (trait::bits - 1)) | return (sign << (trait::bits - 1))
(exp << (trait::bits - trait::expbits - 1)) | significand; | (exp << (trait::bits - trait::expbits - 1)) | significand;
} }
template <class T> template <class T>
...@@ -109,11 +111,10 @@ typename ieee_754_trait<T>::float_type unpack754(T i) { ...@@ -109,11 +111,10 @@ typename ieee_754_trait<T>::float_type unpack754(T i) {
using result_type = typename trait::float_type; using result_type = typename trait::float_type;
if (i == 0) return trait::zero; if (i == 0) return trait::zero;
auto significandbits = trait::bits - trait::expbits - 1; // -1 for sign bit auto significandbits = trait::bits - trait::expbits - 1; // -1 for sign bit
// pull the significand // pull the significand: mask, convert back to float + add the one back on
result_type result = auto result = static_cast<result_type>(i & ((T{1} << significandbits) - 1));
(i & ((static_cast<T>(1) << significandbits) - 1)); // mask result /= static_cast<result_type>(T{1} << significandbits);
result /= (static_cast<T>(1) << significandbits); // convert back to float result += static_cast<result_type>(1);
result += static_cast<result_type>(1); // add the one back on
// deal with the exponent // deal with the exponent
auto si = static_cast<signed_type>(i); auto si = static_cast<signed_type>(i);
auto bias = (1 << (trait::expbits - 1)) - 1; auto bias = (1 << (trait::expbits - 1)) - 1;
......
...@@ -82,24 +82,24 @@ class lifted_fun_invoker { ...@@ -82,24 +82,24 @@ class lifted_fun_invoker {
using arg_types = typename get_callable_trait<F>::arg_types; using arg_types = typename get_callable_trait<F>::arg_types;
static constexpr size_t args = tl_size<arg_types>::value; static constexpr size_t num_args = tl_size<arg_types>::value;
public: public:
lifted_fun_invoker(F& fun) : f(fun) {} lifted_fun_invoker(F& fun) : f(fun) {}
template <class... Ts> template <class... Ts>
typename std::enable_if<sizeof...(Ts) == args, R>::type typename std::enable_if<sizeof...(Ts) == num_args, R>::type
operator()(Ts&... args) const { operator()(Ts&... vs) const {
if (has_none(args...)) return none; if (has_none(vs...)) return none;
return f(unopt(args)...); return f(unopt(vs)...);
} }
template <class T, class... Ts> template <class T, class... Ts>
typename std::enable_if<(sizeof...(Ts) + 1 > args), R>::type typename std::enable_if<(sizeof...(Ts) + 1 > num_args), R>::type
operator()(T& arg, Ts&... args) const { operator()(T& v, Ts&... vs) const {
if (has_none(arg)) return none; if (has_none(v)) return none;
return (*this)(args...); return (*this)(vs...);
} }
private: private:
...@@ -113,25 +113,25 @@ class lifted_fun_invoker<bool, F> { ...@@ -113,25 +113,25 @@ class lifted_fun_invoker<bool, F> {
using arg_types = typename get_callable_trait<F>::arg_types; using arg_types = typename get_callable_trait<F>::arg_types;
static constexpr size_t args = tl_size<arg_types>::value; static constexpr size_t num_args = tl_size<arg_types>::value;
public: public:
lifted_fun_invoker(F& fun) : f(fun) {} lifted_fun_invoker(F& fun) : f(fun) {}
template <class... Ts> template <class... Ts>
typename std::enable_if<sizeof...(Ts) == args, bool>::type typename std::enable_if<sizeof...(Ts) == num_args, bool>::type
operator()(Ts&&... args) const { operator()(Ts&&... vs) const {
if (has_none(args...)) return false; if (has_none(vs...)) return false;
f(unopt(args)...); f(unopt(vs)...);
return true; return true;
} }
template <class T, class... Ts> template <class T, class... Ts>
typename std::enable_if<(sizeof...(Ts) + 1 > args), bool>::type typename std::enable_if<(sizeof...(Ts) + 1 > num_args), bool>::type
operator()(T&& arg, Ts&&... args) const { operator()(T&& arg, Ts&&... vs) const {
if (has_none(arg)) return false; if (has_none(arg)) return false;
return (*this)(args...); return (*this)(vs...);
} }
private: private:
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "caf/to_string.hpp" #include "caf/to_string.hpp"
#include "caf/abstract_actor.hpp" #include "caf/abstract_actor.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/singletons.hpp" #include "caf/detail/singletons.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
...@@ -184,7 +183,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -184,7 +183,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
caf::detail::singletons::get_logger()->set_aid(aid_arg) caf::detail::singletons::get_logger()->set_aid(aid_arg)
#endif #endif
#define CAF_CLASS_NAME caf::detail::demangle(typeid(decltype(*this))).c_str() #define CAF_CLASS_NAME typeid(*this).name()
#define CAF_PRINT0(lvlname, classname, funname, msg) \ #define CAF_PRINT0(lvlname, classname, funname, msg) \
CAF_LOG_IMPL(lvlname, classname, funname, msg) CAF_LOG_IMPL(lvlname, classname, funname, msg)
...@@ -201,7 +200,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -201,7 +200,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
#define CAF_PRINT_IF1(stmt, lvlname, classname, funname, msg) \ #define CAF_PRINT_IF1(stmt, lvlname, classname, funname, msg) \
CAF_PRINT_IF0(stmt, lvlname, classname, funname, msg) CAF_PRINT_IF0(stmt, lvlname, classname, funname, msg)
#if CAF_LOG_LEVEL < CAF_TRACE #if !defined(CAF_LOG_LEVEL) || CAF_LOG_LEVEL < CAF_TRACE
#define CAF_PRINT4(arg0, arg1, arg2, arg3) #define CAF_PRINT4(arg0, arg1, arg2, arg3)
#else #else
#define CAF_PRINT4(lvlname, classname, funname, msg) \ #define CAF_PRINT4(lvlname, classname, funname, msg) \
...@@ -211,7 +210,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -211,7 +210,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
} }
#endif #endif
#if CAF_LOG_LEVEL < CAF_DEBUG #if !defined(CAF_LOG_LEVEL) || CAF_LOG_LEVEL < CAF_DEBUG
#define CAF_PRINT3(arg0, arg1, arg2, arg3) #define CAF_PRINT3(arg0, arg1, arg2, arg3)
#define CAF_PRINT_IF3(arg0, arg1, arg2, arg3, arg4) #define CAF_PRINT_IF3(arg0, arg1, arg2, arg3, arg4)
#else #else
...@@ -221,7 +220,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; } ...@@ -221,7 +220,7 @@ inline caf::actor_id caf_set_aid_dummy() { return 0; }
CAF_PRINT_IF0(stmt, lvlname, classname, funname, msg) CAF_PRINT_IF0(stmt, lvlname, classname, funname, msg)
#endif #endif
#if CAF_LOG_LEVEL < CAF_INFO #if !defined(CAF_LOG_LEVEL) || CAF_LOG_LEVEL < CAF_INFO
#define CAF_PRINT2(arg0, arg1, arg2, arg3) #define CAF_PRINT2(arg0, arg1, arg2, arg3)
#define CAF_PRINT_IF2(arg0, arg1, arg2, arg3, arg4) #define CAF_PRINT_IF2(arg0, arg1, arg2, arg3, arg4)
#else #else
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "caf/uniform_type_info.hpp" #include "caf/uniform_type_info.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/message_iterator.hpp" #include "caf/detail/message_iterator.hpp"
namespace caf { namespace caf {
...@@ -74,7 +73,7 @@ class message_data : public ref_counted { ...@@ -74,7 +73,7 @@ class message_data : public ref_counted {
bool equals(const message_data& other) const; bool equals(const message_data& other) const;
using const_iterator = message_iterator<message_data>; using const_iterator = message_iterator;
inline const_iterator begin() const { inline const_iterator begin() const {
return {this}; return {this};
...@@ -133,37 +132,6 @@ class message_data : public ref_counted { ...@@ -133,37 +132,6 @@ class message_data : public ref_counted {
}; };
struct full_eq_type {
constexpr full_eq_type() {}
template <class Tuple>
inline bool operator()(const message_iterator<Tuple>& lhs,
const message_iterator<Tuple>& rhs) const {
return lhs.type() == rhs.type() &&
lhs.type()->equals(lhs.value(), rhs.value());
}
};
struct types_only_eq_type {
constexpr types_only_eq_type() {}
template <class Tuple>
inline bool operator()(const message_iterator<Tuple>& lhs,
const uniform_type_info* rhs) const {
return lhs.type() == rhs;
}
template <class Tuple>
inline bool operator()(const uniform_type_info* lhs,
const message_iterator<Tuple>& rhs) const {
return lhs == rhs.type();
}
};
namespace {
constexpr full_eq_type full_eq;
constexpr types_only_eq_type types_only_eq;
} // namespace <anonymous>
std::string get_tuple_type_names(const detail::message_data&); std::string get_tuple_type_names(const detail::message_data&);
} // namespace detail } // namespace detail
......
...@@ -17,53 +17,41 @@ ...@@ -17,53 +17,41 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_TUPLE_ITERATOR_HPP #ifndef CAF_DETAIL_MESSAGE_ITERATOR_HPP
#define CAF_DETAIL_TUPLE_ITERATOR_HPP #define CAF_DETAIL_MESSAGE_ITERATOR_HPP
#include <cstddef> #include <cstddef>
#include "caf/config.hpp" #include "caf/fwd.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
template <class Tuple> class message_data;
class message_iterator {
size_t m_pos;
const Tuple* m_tuple;
class message_iterator {
public: public:
using pointer = message_data*;
using const_pointer = const message_data*;
inline message_iterator(const Tuple* tup, size_t pos = 0) message_iterator(const_pointer data, size_t pos = 0);
: m_pos(pos), m_tuple(tup) {}
message_iterator(const message_iterator&) = default; message_iterator(const message_iterator&) = default;
message_iterator& operator=(const message_iterator&) = default; message_iterator& operator=(const message_iterator&) = default;
inline bool operator==(const message_iterator& other) const {
CAF_REQUIRE(other.m_tuple == other.m_tuple);
return other.m_pos == m_pos;
}
inline bool operator!=(const message_iterator& other) const {
return !(*this == other);
}
inline message_iterator& operator++() { inline message_iterator& operator++() {
++m_pos; ++m_pos;
return *this; return *this;
} }
inline message_iterator& operator--() { inline message_iterator& operator--() {
CAF_REQUIRE(m_pos > 0);
--m_pos; --m_pos;
return *this; return *this;
} }
inline message_iterator operator+(size_t offset) { inline message_iterator operator+(size_t offset) {
return {m_tuple, m_pos + offset}; return {m_data, m_pos + offset};
} }
inline message_iterator& operator+=(size_t offset) { inline message_iterator& operator+=(size_t offset) {
...@@ -72,29 +60,46 @@ class message_iterator { ...@@ -72,29 +60,46 @@ class message_iterator {
} }
inline message_iterator operator-(size_t offset) { inline message_iterator operator-(size_t offset) {
CAF_REQUIRE(m_pos >= offset); return {m_data, m_pos - offset};
return {m_tuple, m_pos - offset};
} }
inline message_iterator& operator-=(size_t offset) { inline message_iterator& operator-=(size_t offset) {
CAF_REQUIRE(m_pos >= offset);
m_pos -= offset; m_pos -= offset;
return *this; return *this;
} }
inline size_t position() const { return m_pos; } inline size_t position() const {
return m_pos;
inline const void* value() const { return m_tuple->at(m_pos); } }
inline const uniform_type_info* type() const { inline const_pointer data() const {
return m_tuple->type_at(m_pos); return m_data;
} }
inline message_iterator& operator*() { return *this; } const void* value() const;
const uniform_type_info* type() const;
inline message_iterator& operator*() {
return *this;
}
private:
size_t m_pos;
const message_data* m_data;
}; };
inline bool operator==(const message_iterator& lhs,
const message_iterator& rhs) {
return lhs.data() == rhs.data() && lhs.position() == rhs.position();
}
inline bool operator!=(const message_iterator& lhs,
const message_iterator& rhs) {
return !(lhs == rhs);
}
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_TUPLE_ITERATOR_HPP #endif // CAF_DETAIL_MESSAGE_ITERATOR_HPP
...@@ -64,10 +64,10 @@ class proper_actor_base : public Policies::resume_policy::template ...@@ -64,10 +64,10 @@ class proper_actor_base : public Policies::resume_policy::template
scheduling_policy().enqueue(dptr(), sender, mid, msg, eu); scheduling_policy().enqueue(dptr(), sender, mid, msg, eu);
} }
inline void launch(bool hide, execution_unit* host) { inline void launch(bool hide, bool lazy, execution_unit* eu) {
CAF_LOG_TRACE(""); CAF_LOG_TRACE("");
this->is_registered(!hide); this->is_registered(!hide);
this->scheduling_policy().launch(this, host); this->scheduling_policy().launch(this, eu, lazy);
} }
template <class F> template <class F>
...@@ -255,17 +255,17 @@ class proper_actor<Base, Policies, true> ...@@ -255,17 +255,17 @@ class proper_actor<Base, Policies, true>
} }
restore_cache(); restore_cache();
} }
bool has_timeout = false; bool timeout_valid = false;
uint32_t timeout_id; uint32_t timeout_id;
// request timeout if needed // request timeout if needed
if (bhvr.timeout().valid()) { if (bhvr.timeout().valid()) {
has_timeout = true; timeout_valid = true;
timeout_id = this->request_timeout(bhvr.timeout()); timeout_id = this->request_timeout(bhvr.timeout());
} }
// workaround for GCC 4.7 bug (const this when capturing refs) // workaround for GCC 4.7 bug (const this when capturing refs)
auto& pending_timeouts = m_pending_timeouts; auto& pending_timeouts = m_pending_timeouts;
auto guard = detail::make_scope_guard([&] { auto guard = detail::make_scope_guard([&] {
if (has_timeout) { if (timeout_valid) {
auto e = pending_timeouts.end(); auto e = pending_timeouts.end();
auto i = std::find(pending_timeouts.begin(), e, timeout_id); auto i = std::find(pending_timeouts.begin(), e, timeout_id);
if (i != e) { if (i != e) {
......
...@@ -47,15 +47,17 @@ template <size_t N, class... Ts> ...@@ -47,15 +47,17 @@ template <size_t N, class... Ts>
const typename detail::type_at<N, Ts...>::type& const typename detail::type_at<N, Ts...>::type&
get(const detail::pseudo_tuple<Ts...>& tv) { get(const detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
return *reinterpret_cast<const typename detail::type_at<N, Ts...>::type*>( auto vp = tv.at(N);
tv.at(N)); CAF_REQUIRE(vp != nullptr);
return *reinterpret_cast<const typename detail::type_at<N, Ts...>::type*>(vp);
} }
template <size_t N, class... Ts> template <size_t N, class... Ts>
typename detail::type_at<N, Ts...>::type& get(detail::pseudo_tuple<Ts...>& tv) { typename detail::type_at<N, Ts...>::type& get(detail::pseudo_tuple<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
return *reinterpret_cast<typename detail::type_at<N, Ts...>::type*>( auto vp = tv.mutable_at(N);
tv.mutable_at(N)); CAF_REQUIRE(vp != nullptr);
return *reinterpret_cast<typename detail::type_at<N, Ts...>::type*>(vp);
} }
} // namespace detail } // namespace detail
......
...@@ -17,19 +17,13 @@ ...@@ -17,19 +17,13 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_SPLIT_HPP #ifndef CAF_DETAIL_SAFE_EQUAL_HPP
#define CAF_DETAIL_SPLIT_HPP #define CAF_DETAIL_SAFE_EQUAL_HPP
#include <cmath> // fabs #include <cmath> // fabs
#include <string>
#include <vector>
#include <limits> #include <limits>
#include <sstream>
#include <algorithm>
#include <type_traits> #include <type_traits>
#include "caf/detail/type_traits.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
...@@ -39,18 +33,18 @@ namespace detail { ...@@ -39,18 +33,18 @@ namespace detail {
* performs an epsilon comparison. * performs an epsilon comparison.
*/ */
template <class T, typename U> template <class T, typename U>
typename std::enable_if< !std::is_floating_point<T>::value typename std::enable_if<
&& !std::is_floating_point<U>::value, !std::is_floating_point<T>::value && !std::is_floating_point<U>::value,
bool bool
>::type >::type
safe_equal(const T& lhs, const U& rhs) { safe_equal(const T& lhs, const U& rhs) {
return lhs == rhs; return lhs == rhs;
} }
template <class T, typename U> template <class T, typename U>
typename std::enable_if< std::is_floating_point<T>::value typename std::enable_if<
|| std::is_floating_point<U>::value, std::is_floating_point<T>::value || std::is_floating_point<U>::value,
bool bool
>::type >::type
safe_equal(const T& lhs, const U& rhs) { safe_equal(const T& lhs, const U& rhs) {
using res_type = decltype(lhs - rhs); using res_type = decltype(lhs - rhs);
...@@ -60,4 +54,4 @@ safe_equal(const T& lhs, const U& rhs) { ...@@ -60,4 +54,4 @@ safe_equal(const T& lhs, const U& rhs) {
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_SPLIT_HPP #endif // CAF_DETAIL_SAFE_EQUAL_HPP
...@@ -336,7 +336,7 @@ class single_reader_queue { ...@@ -336,7 +336,7 @@ class single_reader_queue {
pointer reader_blocked_dummy() { pointer reader_blocked_dummy() {
// we are not going to dereference this pointer either // we are not going to dereference this pointer either
return reinterpret_cast<pointer>(reinterpret_cast<intptr_t>(this) return reinterpret_cast<pointer>(reinterpret_cast<intptr_t>(this)
+ sizeof(void*)); + static_cast<intptr_t>(sizeof(void*)));
} }
bool is_dummy(pointer ptr) { bool is_dummy(pointer ptr) {
......
...@@ -20,7 +20,9 @@ ...@@ -20,7 +20,9 @@
#ifndef CAF_DETAIL_MATCHES_HPP #ifndef CAF_DETAIL_MATCHES_HPP
#define CAF_DETAIL_MATCHES_HPP #define CAF_DETAIL_MATCHES_HPP
#include <array>
#include <numeric> #include <numeric>
#include <typeinfo>
#include "caf/message.hpp" #include "caf/message.hpp"
#include "caf/wildcard_position.hpp" #include "caf/wildcard_position.hpp"
...@@ -31,80 +33,75 @@ ...@@ -31,80 +33,75 @@
namespace caf { namespace caf {
namespace detail { namespace detail {
template <class Pattern, class FilteredPattern> bool match_element(const std::type_info* type, const message_iterator& iter,
struct matcher; void** storage);
template <class... Ts, class... Us> template <class T>
struct matcher<type_list<Ts...>, type_list<Us...>> { bool match_integral_constant_element(const std::type_info* type,
template <class TupleIter, class PatternIter, class Push, class Commit, const message_iterator& iter,
class Rollback> void** storage) {
bool operator()(TupleIter tbegin, TupleIter tend, PatternIter pbegin, auto value = T::value;
PatternIter pend, Push& push, Commit& commit, auto uti = iter.type();
Rollback& rollback) const { if (!uti->equal_to(*type) || !uti->equals(iter.value(), &value)) {
while (!(pbegin == pend && tbegin == tend)) { return false;
if (pbegin == pend) { }
// reached end of pattern while some values remain unmatched if (storage) {
return false; // This assignment implicitly casts `T*` to `integral_constant<T, V>*`.
} // This type violation could theoretically cause undefined behavior.
if (*pbegin == nullptr) { // nullptr == wildcard (anything) // However, `T::value` does have an address that is guaranteed to be valid
// perform submatching // throughout the runtime of the program and the integral constant
++pbegin; // objects does not have any members. Hence, this is nonetheless safe.
// always true at the end of the pattern auto ptr = reinterpret_cast<const void*>(&T::value);
if (pbegin == pend) { // Again, this const cast is always safe because we will never derefence
return true; // this pointer since `integral_constant<T, V>` has no members.
} *storage = const_cast<void*>(ptr);
// safe current mapping as fallback }
commit(); return true;
// iterate over tuple values until we found a match }
for (; tbegin != tend; ++tbegin) {
if ((*this)(tbegin, tend, pbegin, pend, push, commit, rollback)) { struct meta_element {
return true; const std::type_info* type;
} bool (*fun)(const std::type_info*, const message_iterator&, void**);
// restore mapping to fallback (delete invalid mappings) };
rollback();
} template <class T>
return false; // no submatch found struct meta_element_factory {
} static meta_element create() {
// compare types return {&typeid(T), match_element};
if (tbegin.type() != *pbegin) {
// type mismatch
return false;
}
// next iteration
push(tbegin);
++tbegin;
++pbegin;
}
return true; // pbegin == pend && tbegin == tend
} }
};
bool operator()(const message& tup, pseudo_tuple<Us...>* out) const { template <class T, T V>
auto& tarr = static_types_array<Ts...>::arr; struct meta_element_factory<std::integral_constant<T, V>> {
if (sizeof...(Us) == 0) { static meta_element create() {
// this pattern only has wildcards and thus always matches return {&typeid(T),
return true; match_integral_constant_element<std::integral_constant<T, V>>};
}
if (tup.size() < sizeof...(Us)) {
return false;
}
if (out) {
size_t pos = 0;
size_t fallback_pos = 0;
auto fpush = [&](const typename message::const_iterator& iter) {
(*out)[pos++] = const_cast<void*>(iter.value());
};
auto fcommit = [&] { fallback_pos = pos; };
auto frollback = [&] { pos = fallback_pos; };
return (*this)(tup.begin(), tup.end(), tarr.begin(), tarr.end(), fpush,
fcommit, frollback);
}
auto no_push = [](const typename message::const_iterator&) { };
auto nop = [] { };
return (*this)(tup.begin(), tup.end(), tarr.begin(), tarr.end(), no_push,
nop, nop);
} }
}; };
template <>
struct meta_element_factory<anything> {
static meta_element create() {
return {nullptr, nullptr};
}
};
template <class TypeList>
struct meta_elements;
template <class... Ts>
struct meta_elements<type_list<Ts...>> {
std::array<meta_element, sizeof...(Ts)> arr;
meta_elements() : arr{{meta_element_factory<Ts>::create()...}} {
// nop
}
};
bool try_match(const message& msg,
const meta_element* pattern_begin,
size_t pattern_size,
void** out = nullptr);
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
......
...@@ -207,8 +207,8 @@ class is_forward_iterator { ...@@ -207,8 +207,8 @@ class is_forward_iterator {
}; };
/** /**
* Checks wheter `T` has `begin()</tt> and <tt>end() member * Checks wheter `T` has `begin()` and `end()` member
* functions returning forward iterators. * functions returning forward iterators.
*/ */
template <class T> template <class T>
class is_iterable { class is_iterable {
...@@ -256,6 +256,23 @@ struct is_mutable_ref { ...@@ -256,6 +256,23 @@ struct is_mutable_ref {
&& !std::is_const<T>::value; && !std::is_const<T>::value;
}; };
/**
* Checks whether `T::static_type_name()` exists.
*/
template <class T>
class has_static_type_name {
private:
template <class U,
class = typename std::enable_if<
!std::is_member_pointer<decltype(&U::is_baz)>::value
>::type>
static std::true_type sfinae_fun(int);
template <class>
static std::false_type sfinae_fun(...);
public:
static constexpr bool value = decltype(sfinae_fun<T>(0))::value;
};
/** /**
* Returns either `T` or `T::type` if `T` is an option. * Returns either `T` or `T::type` if `T` is an option.
*/ */
...@@ -464,6 +481,16 @@ struct is_optional<optional<T>> : std::true_type { ...@@ -464,6 +481,16 @@ struct is_optional<optional<T>> : std::true_type {
// no members // no members
}; };
template <class T>
struct is_integral_constant : std::false_type {
// no members
};
template <class T, T V>
struct is_integral_constant<std::integral_constant<T, V>> : std::true_type {
// no members
};
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <tuple> #include <tuple>
#include "caf/replies_to.hpp" #include "caf/replies_to.hpp"
#include "caf/system_messages.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
...@@ -36,26 +37,56 @@ class typed_continue_helper; ...@@ -36,26 +37,56 @@ class typed_continue_helper;
namespace caf { namespace caf {
namespace detail { namespace detail {
template <class R, typename T> template <class T>
struct deduce_signature_helper; struct unwrap_std_tuple {
using type = type_list<T>;
};
template <class... Ts>
struct unwrap_std_tuple<std::tuple<Ts...>> {
using type = type_list<Ts...>;
};
template <class R, class... Ts> template <class T>
struct deduce_signature_helper<R, type_list<Ts...>> { struct deduce_lhs_result {
using type = typename replies_to<Ts...>::template with<R>; using type = typename unwrap_std_tuple<T>::type;
};
template <class L, class R>
struct deduce_lhs_result<either_or_t<L, R>> {
using type = L;
}; };
template <class... Rs, class... Ts> template <class T>
struct deduce_signature_helper<std::tuple<Rs...>, type_list<Ts...>> { struct deduce_rhs_result {
using type = typename replies_to<Ts...>::template with<Rs...>; using type = type_list<>;
};
template <class L, class R>
struct deduce_rhs_result<either_or_t<L, R>> {
using type = R;
}; };
template <class T> template <class T>
struct deduce_signature { struct is_hidden_msg_handler : std::false_type { };
using result_ = typename implicit_conversions<typename T::result_type>::type;
template <>
struct is_hidden_msg_handler<typed_mpi<type_list<exit_msg>,
type_list<void>,
empty_type_list>> : std::true_type { };
template <>
struct is_hidden_msg_handler<typed_mpi<type_list<down_msg>,
type_list<void>,
empty_type_list>> : std::true_type { };
template <class T>
struct deduce_mpi {
using result = typename implicit_conversions<typename T::result_type>::type;
using arg_t = typename tl_map<typename T::arg_types, std::decay>::type; using arg_t = typename tl_map<typename T::arg_types, std::decay>::type;
using type = typename deduce_signature_helper<result_, arg_t>::type; using type = typed_mpi<arg_t,
typename deduce_lhs_result<result>::type,
typename deduce_rhs_result<result>::type>;
}; };
template <class Arguments> template <class Arguments>
...@@ -67,20 +98,50 @@ struct input_is { ...@@ -67,20 +98,50 @@ struct input_is {
}; };
}; };
template <class OutputList, typename F> template <class OutputPair, class... Fs>
inline void assert_types() { struct type_checker;
using arg_types =
typename tl_map< template <class OutputList, class F1>
typename get_callable_trait<F>::arg_types, struct type_checker<OutputList, F1> {
std::decay static void check() {
>::type; using arg_types =
static constexpr size_t fun_args = tl_size<arg_types>::value; typename tl_map<
static_assert(fun_args <= tl_size<OutputList>::value, typename get_callable_trait<F1>::arg_types,
"functor takes too much arguments"); std::decay
using recv_types = typename tl_right<OutputList, fun_args>::type; >::type;
static_assert(std::is_same<arg_types, recv_types>::value, static constexpr size_t args = tl_size<arg_types>::value;
"wrong functor signature"); static_assert(args <= tl_size<OutputList>::value,
} "functor takes too much arguments");
using rtypes = typename tl_right<OutputList, args>::type;
static_assert(std::is_same<arg_types, rtypes>::value,
"wrong functor signature");
}
};
template <class Opt1, class Opt2, class F1>
struct type_checker<type_pair<Opt1, Opt2>, F1> {
static void check() {
type_checker<Opt1, F1>::check();
}
};
template <class OutputPair, class F1>
struct type_checker<OutputPair, F1, none_t> : type_checker<OutputPair, F1> { };
template <class Opt1, class Opt2, class F1, class F2>
struct type_checker<type_pair<Opt1, Opt2>, F1, F2> {
static void check() {
type_checker<Opt1, F1>::check();
type_checker<Opt2, F2>::check();
}
};
template <class A, class B, template <class, class> class Predicate>
struct static_asserter {
static void verify_match() {
static_assert(Predicate<A, B>::value, "exact match needed");
}
};
template <class T> template <class T>
struct lifted_result_type { struct lifted_result_type {
...@@ -93,27 +154,50 @@ struct lifted_result_type<std::tuple<Ts...>> { ...@@ -93,27 +154,50 @@ struct lifted_result_type<std::tuple<Ts...>> {
}; };
template <class T> template <class T>
struct deduce_output_type_step2 { struct deduce_lifted_output_type {
using type = T; using type = T;
}; };
template <class R> template <class R>
struct deduce_output_type_step2<type_list<typed_continue_helper<R>>> { struct deduce_lifted_output_type<type_list<typed_continue_helper<R>>> {
using type = typename lifted_result_type<R>::type; using type = typename lifted_result_type<R>::type;
}; };
template <class Signatures, typename InputTypes> template <class Signatures, typename InputTypes>
struct deduce_output_type { struct deduce_output_type {
static constexpr int input_pos = tl_find_if< static_assert(tl_find<
Signatures, InputTypes,
input_is<InputTypes>::template eval atom_value
>::value; >::value == -1,
static_assert(input_pos >= 0, "typed actor does not support given input"); "atom(...) notation is not sufficient for static type "
"checking, please use atom_constant instead in this context");
static constexpr int input_pos =
tl_find_if<
Signatures,
input_is<InputTypes>::template eval
>::value;
static_assert(input_pos != -1, "typed actor does not support given input");
using signature = typename tl_at<Signatures, input_pos>::type; using signature = typename tl_at<Signatures, input_pos>::type;
using type = using type = detail::type_pair<typename signature::output_opt1_types,
typename deduce_output_type_step2< typename signature::output_opt2_types>;
typename signature::output_types };
>::type;
template <class... Ts>
struct common_result_type;
template <class T>
struct common_result_type<T> {
using type = T;
};
template <class T, class... Us>
struct common_result_type<T, T, Us...> {
using type = typename common_result_type<T, Us...>::type;
};
template <class T1, class T2, class... Us>
struct common_result_type<T1, T2, Us...> {
using type = void;
}; };
} // namespace detail } // namespace detail
......
...@@ -23,15 +23,11 @@ ...@@ -23,15 +23,11 @@
#include <atomic> #include <atomic>
#include <typeinfo> #include <typeinfo>
#include "caf/uniform_typeid.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
// forward declarations
namespace caf {
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
} // namespace caf
namespace caf { namespace caf {
namespace detail { namespace detail {
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_EITHER_HPP
#define CAF_EITHER_HPP
#include <tuple>
#include <string>
#include <type_traits>
#include "caf/message.hpp"
#include "caf/replies_to.hpp"
#include "caf/type_name_access.hpp"
#include "caf/illegal_message_element.hpp"
#include "caf/detail/type_list.hpp"
namespace caf {
/** @cond PRIVATE */
std::string either_or_else_type_name(size_t lefts_size,
const std::string* lefts,
size_t rights_size,
const std::string* rights);
template <class L, class R>
struct either_or_t;
template <class... Ls, class... Rs>
struct either_or_t<detail::type_list<Ls...>,
detail::type_list<Rs...>> : illegal_message_element {
static_assert(!std::is_same<detail::type_list<Ls...>,
detail::type_list<Rs...>>::value,
"template parameter packs must differ");
either_or_t(Ls... ls) : value(make_message(std::move(ls)...)) {
// nop
}
either_or_t(Rs... rs) : value(make_message(std::move(rs)...)) {
// nop
}
using opt1_type = std::tuple<Ls...>;
using opt2_type = std::tuple<Rs...>;
message value;
static std::string static_type_name() {
std::string lefts[] = {type_name_access<Ls>::get()...};
std::string rights[] = {type_name_access<Rs>::get()...};
return either_or_else_type_name(sizeof...(Ls), lefts,
sizeof...(Rs), rights);
}
};
/** @endcond */
template <class... Ts>
struct either {
template <class... Us>
using or_else = either_or_t<detail::type_list<Ts...>,
detail::type_list<Us...>>;
};
} // namespace caf
#endif // CAF_EITHER_HPP
...@@ -17,50 +17,24 @@ ...@@ -17,50 +17,24 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_IO_REMOTE_ACTOR_PROXY_HPP #ifndef CAF_FORWARDING_ACTOR_PROXY_HPP
#define CAF_IO_REMOTE_ACTOR_PROXY_HPP #define CAF_FORWARDING_ACTOR_PROXY_HPP
#include "caf/extend.hpp" #include "caf/actor.hpp"
#include "caf/actor_proxy.hpp" #include "caf/actor_proxy.hpp"
#include "caf/mixin/memory_cached.hpp" #include "caf/detail/shared_spinlock.hpp"
#include "caf/detail/single_reader_queue.hpp"
namespace caf {
namespace detail {
class memory;
} // namespace detail
} // namespace caf
namespace caf { namespace caf {
namespace io {
class middleman; /**
* Implements a simple proxy forwarding all operations to a manager.
class sync_request_info : public extend<memory_managed>:: */
with<mixin::memory_cached> { class forwarding_actor_proxy : public actor_proxy {
friend class detail::memory;
public: public:
using pointer = sync_request_info*; forwarding_actor_proxy(actor_id mid, node_id pinfo, actor parent);
~sync_request_info();
pointer next; // intrusive next pointer ~forwarding_actor_proxy();
actor_addr sender; // points to the sender of the message
message_id mid; // sync message ID
private:
sync_request_info(actor_addr sptr, message_id id);
};
class remote_actor_proxy : public actor_proxy {
using super = actor_proxy;
public:
remote_actor_proxy(actor_id mid, node_id pinfo,
actor parent);
void enqueue(const actor_addr&, message_id, void enqueue(const actor_addr&, message_id,
message, execution_unit*) override; message, execution_unit*) override;
...@@ -73,17 +47,17 @@ class remote_actor_proxy : public actor_proxy { ...@@ -73,17 +47,17 @@ class remote_actor_proxy : public actor_proxy {
void kill_proxy(uint32_t reason) override; void kill_proxy(uint32_t reason) override;
protected: actor manager() const;
~remote_actor_proxy();
void manager(actor new_manager);
private: private:
void forward_msg(const actor_addr& sender, message_id mid, message msg); void forward_msg(const actor_addr& sender, message_id mid, message msg);
actor m_parent;
};
using remote_actor_proxy_ptr = intrusive_ptr<remote_actor_proxy>; mutable detail::shared_spinlock m_manager_mtx;
actor m_manager;
};
} // namespace io
} // namespace caf } // namespace caf
#endif // CAF_IO_REMOTE_ACTOR_PROXY_HPP #endif // CAF_FORWARDING_ACTOR_PROXY_HPP
...@@ -47,11 +47,13 @@ class blocking_actor; ...@@ -47,11 +47,13 @@ class blocking_actor;
class message_handler; class message_handler;
class uniform_type_info; class uniform_type_info;
class event_based_actor; class event_based_actor;
class forwarding_actor_proxy;
// structs // structs
struct anything; struct anything;
struct invalid_actor_t; struct invalid_actor_t;
struct invalid_actor_addr_t; struct invalid_actor_addr_t;
struct illegal_message_element;
// enums // enums
enum class atom_value : uint64_t; enum class atom_value : uint64_t;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_ILLEGAL_MESSAGE_ELEMENT_HPP
#define CAF_ILLEGAL_MESSAGE_ELEMENT_HPP
#include <type_traits>
namespace caf {
/**
* Marker class identifying classes in CAF that are not allowed
* to be used as message element.
*/
struct illegal_message_element {
// no members (marker class)
};
template <class T>
struct is_illegal_message_element
: std::is_base_of<illegal_message_element, T> { };
} // namespace caf
#endif // CAF_ILLEGAL_MESSAGE_ELEMENT_HPP
...@@ -504,8 +504,8 @@ class local_actor : public extend<abstract_actor>::with<mixin::memory_cached> { ...@@ -504,8 +504,8 @@ class local_actor : public extend<abstract_actor>::with<mixin::memory_cached> {
// returns 0 if last_dequeued() is an asynchronous or sync request message, // returns 0 if last_dequeued() is an asynchronous or sync request message,
// a response id generated from the request id otherwise // a response id generated from the request id otherwise
inline message_id get_response_id() { inline message_id get_response_id() {
auto id = m_current_node->mid; auto mid = m_current_node->mid;
return (id.is_request()) ? id.response_id() : message_id(); return (mid.is_request()) ? mid.response_id() : message_id();
} }
void reply_message(message&& what); void reply_message(message&& what);
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/left_or_right.hpp" #include "caf/detail/left_or_right.hpp"
#include "caf/detail/matcher.hpp" #include "caf/detail/try_match.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/lifted_fun.hpp" #include "caf/detail/lifted_fun.hpp"
#include "caf/detail/pseudo_tuple.hpp" #include "caf/detail/pseudo_tuple.hpp"
...@@ -227,10 +227,9 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) { ...@@ -227,10 +227,9 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
} }
auto& f = get<N>(fs); auto& f = get<N>(fs);
using ft = typename std::decay<decltype(f)>::type; using ft = typename std::decay<decltype(f)>::type;
detail::matcher<typename ft::pattern, typename ft::filtered_pattern> match; meta_elements<typename ft::pattern> ms;
typename ft::intermediate_tuple targs; typename ft::intermediate_tuple targs;
if (match(msg, &targs)) { if (try_match(msg, ms.arr.data(), ms.arr.size(), targs.data)) {
//if (policy::prepare_invoke(targs, type_token, is_dynamic, ptr, tup)) {
auto is = detail::get_indices(targs); auto is = detail::get_indices(targs);
auto res = detail::apply_args(f, is, deduce_const(msg, targs)); auto res = detail::apply_args(f, is, deduce_const(msg, targs));
if (unroll_expr_result_valid(res)) { if (unroll_expr_result_valid(res)) {
...@@ -240,19 +239,21 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) { ...@@ -240,19 +239,21 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
return none; return none;
} }
template <class PPFPs, class Tuple> template <class PPFPs>
uint64_t calc_bitmask(PPFPs&, minus1l, const std::type_info&, const Tuple&) { uint64_t calc_bitmask(PPFPs&, minus1l, const std::type_info&, const message&) {
return 0x00; return 0x00;
} }
template <class Case, long N, class Tuple> template <class Case, long N>
uint64_t calc_bitmask(Case& fs, long_constant<N>, uint64_t calc_bitmask(Case& fs, long_constant<N>,
const std::type_info& tinf, const Tuple& tup) { const std::type_info& tinf, const message& msg) {
auto& f = get<N>(fs); auto& f = get<N>(fs);
using ft = typename std::decay<decltype(f)>::type; using ft = typename std::decay<decltype(f)>::type;
detail::matcher<typename ft::pattern, typename ft::filtered_pattern> match; meta_elements<typename ft::pattern> ms;
uint64_t result = match(tup, nullptr) ? (0x01 << N) : 0x00; uint64_t result = try_match(msg, ms.arr.data(), ms.arr.size(), nullptr)
return result | calc_bitmask(fs, long_constant<N - 1l>(), tinf, tup); ? (0x01 << N)
: 0x00;
return result | calc_bitmask(fs, long_constant<N - 1l>(), tinf, msg);
} }
template <bool IsManipulator, typename T0, typename T1> template <bool IsManipulator, typename T0, typename T1>
......
...@@ -181,16 +181,12 @@ class message { ...@@ -181,16 +181,12 @@ class message {
/** /**
* Returns an iterator to the beginning. * Returns an iterator to the beginning.
*/ */
inline const_iterator begin() const { const_iterator begin() const;
return m_vals->begin();
}
/** /**
* Returns an iterator to the end. * Returns an iterator to the end.
*/ */
inline const_iterator end() const { const_iterator end() const;
return m_vals->end();
}
/** /**
* Returns a copy-on-write pointer to the internal data. * Returns a copy-on-write pointer to the internal data.
...@@ -285,6 +281,16 @@ inline bool operator!=(const message& lhs, const message& rhs) { ...@@ -285,6 +281,16 @@ inline bool operator!=(const message& lhs, const message& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
template <class T>
struct lift_message_element {
using type = T;
};
template <class T, T V>
struct lift_message_element<std::integral_constant<T, V>> {
using type = T;
};
/** /**
* Creates a new `message` containing the elements `args...`. * Creates a new `message` containing the elements `args...`.
* @relates message * @relates message
...@@ -296,10 +302,14 @@ typename std::enable_if< ...@@ -296,10 +302,14 @@ typename std::enable_if<
message message
>::type >::type
make_message(T&& arg, Ts&&... args) { make_message(T&& arg, Ts&&... args) {
using namespace detail; using storage
using data = tuple_vals<typename strip_and_convert<T>::type, = detail::tuple_vals<typename lift_message_element<
typename strip_and_convert<Ts>::type...>; typename detail::strip_and_convert<T>::type
auto ptr = new data(std::forward<T>(arg), std::forward<Ts>(args)...); >::type,
typename lift_message_element<
typename detail::strip_and_convert<Ts>::type
>::type...>;
auto ptr = new storage(std::forward<T>(arg), std::forward<Ts>(args)...);
return message{detail::message_data::ptr{ptr}}; return message{detail::message_data::ptr{ptr}};
} }
......
...@@ -69,6 +69,13 @@ class message_handler { ...@@ -69,6 +69,13 @@ class message_handler {
*/ */
message_handler(impl_ptr ptr); message_handler(impl_ptr ptr);
/**
* Checks whether the message handler is not empty.
*/
inline operator bool() const {
return static_cast<bool>(m_impl);
}
/** /**
* Create a message handler a list of match expressions, * Create a message handler a list of match expressions,
* functors, or other message handlers. * functors, or other message handlers.
...@@ -104,7 +111,13 @@ class message_handler { ...@@ -104,7 +111,13 @@ class message_handler {
// using a behavior is safe here, because we "cast" // using a behavior is safe here, because we "cast"
// it back to a message_handler when appropriate // it back to a message_handler when appropriate
behavior tmp{std::forward<Ts>(args)...}; behavior tmp{std::forward<Ts>(args)...};
return m_impl->or_else(tmp.as_behavior_impl()); if (! tmp) {
return *this;
}
if (m_impl) {
return m_impl->or_else(tmp.as_behavior_impl());
}
return tmp;
} }
private: private:
......
...@@ -36,7 +36,6 @@ template <class Base, class Subtype, class ResponseHandleTag> ...@@ -36,7 +36,6 @@ template <class Base, class Subtype, class ResponseHandleTag>
class sync_sender_impl : public Base { class sync_sender_impl : public Base {
public: public:
using response_handle_type = response_handle<Subtype, message, using response_handle_type = response_handle<Subtype, message,
ResponseHandleTag>; ResponseHandleTag>;
...@@ -130,10 +129,12 @@ class sync_sender_impl : public Base { ...@@ -130,10 +129,12 @@ class sync_sender_impl : public Base {
**************************************************************************/ **************************************************************************/
template <class... Rs, class... Ts> template <class... Rs, class... Ts>
response_handle< response_handle<Subtype,
Subtype, typename detail::deduce_output_type< typename detail::deduce_output_type<
detail::type_list<Rs...>, detail::type_list<Ts...>>::type, detail::type_list<Rs...>,
ResponseHandleTag> detail::type_list<Ts...>
>::type,
ResponseHandleTag>
sync_send_tuple(message_priority prio, const typed_actor<Rs...>& dest, sync_send_tuple(message_priority prio, const typed_actor<Rs...>& dest,
std::tuple<Ts...> what) { std::tuple<Ts...> what) {
return sync_send_impl(prio, dest, detail::type_list<Ts...>{}, return sync_send_impl(prio, dest, detail::type_list<Ts...>{},
...@@ -157,7 +158,8 @@ class sync_sender_impl : public Base { ...@@ -157,7 +158,8 @@ class sync_sender_impl : public Base {
typename detail::deduce_output_type< typename detail::deduce_output_type<
detail::type_list<Rs...>, detail::type_list<Rs...>,
typename detail::implicit_conversions< typename detail::implicit_conversions<
typename std::decay<Ts>::type>::type...>::type, typename std::decay<Ts>::type>::type...
>::type,
ResponseHandleTag> ResponseHandleTag>
sync_send(message_priority prio, const typed_actor<Rs...>& dest, sync_send(message_priority prio, const typed_actor<Rs...>& dest,
Ts&&... what) { Ts&&... what) {
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "caf/unit.hpp" #include "caf/unit.hpp"
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/safe_equal.hpp"
namespace caf { namespace caf {
/** /**
...@@ -272,7 +274,7 @@ class optional<T&> { ...@@ -272,7 +274,7 @@ class optional<T&> {
template <class T, typename U> template <class T, typename U>
bool operator==(const optional<T>& lhs, const optional<U>& rhs) { bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
if ((lhs) && (rhs)) { if ((lhs) && (rhs)) {
return *lhs == *rhs; return detail::safe_equal(*lhs, *rhs);
} }
return !lhs && !rhs; return !lhs && !rhs;
} }
......
...@@ -40,13 +40,18 @@ class cooperative_scheduling { ...@@ -40,13 +40,18 @@ class cooperative_scheduling {
using timeout_type = int; using timeout_type = int;
template <class Actor> template <class Actor>
inline void launch(Actor* self, execution_unit* host) { inline void launch(Actor* self, execution_unit* host, bool lazy) {
// detached in scheduler::worker::run // detached in scheduler::worker::run
self->attach_to_scheduler(); self->attach_to_scheduler();
if (host) if (lazy) {
self->mailbox().try_block();
return;
}
if (host) {
host->exec_later(self); host->exec_later(self);
else } else {
detail::singletons::get_scheduling_coordinator()->enqueue(self); detail::singletons::get_scheduling_coordinator()->enqueue(self);
}
} }
template <class Actor> template <class Actor>
......
...@@ -125,6 +125,7 @@ class event_based_resume { ...@@ -125,6 +125,7 @@ class event_based_resume {
auto ptr = d->next_message(); auto ptr = d->next_message();
if (ptr) { if (ptr) {
if (d->invoke_message(ptr)) { if (d->invoke_message(ptr)) {
d->bhvr_stack().cleanup();
++handled_msgs; ++handled_msgs;
if (actor_done()) { if (actor_done()) {
CAF_LOG_DEBUG("actor exited"); CAF_LOG_DEBUG("actor exited");
...@@ -170,9 +171,8 @@ class event_based_resume { ...@@ -170,9 +171,8 @@ class event_based_resume {
} }
} }
catch (std::exception& e) { catch (std::exception& e) {
CAF_LOG_INFO("actor died because of an exception: " CAF_LOG_INFO("actor died because of an exception, what: " << e.what());
<< detail::demangle(typeid(e)) static_cast<void>(e); // keep compiler happy when not logging
<< ", what() = " << e.what());
if (d->exit_reason() == exit_reason::not_exited) { if (d->exit_reason() == exit_reason::not_exited) {
d->quit(exit_reason::unhandled_exception); d->quit(exit_reason::unhandled_exception);
} }
......
...@@ -153,36 +153,22 @@ class invoke_policy { ...@@ -153,36 +153,22 @@ class invoke_policy {
auto id = res->template get_as<uint64_t>(1); auto id = res->template get_as<uint64_t>(1);
auto msg_id = message_id::from_integer_value(id); auto msg_id = message_id::from_integer_value(id);
auto ref_opt = self->sync_handler(msg_id); auto ref_opt = self->sync_handler(msg_id);
// calls self->response_promise() if hdl is a dummy // install a behavior that calls the user-defined behavior
// argument, forwards hdl otherwise to reply to the // and using the result of its inner behavior as response
// original request message
auto fhdl = fetch_response_promise(self, hdl);
if (ref_opt) { if (ref_opt) {
behavior cpy = *ref_opt; auto fhdl = fetch_response_promise(self, hdl);
*ref_opt = behavior inner = *ref_opt;
cpy.add_continuation([=](message & intermediate) *ref_opt = behavior {
->optional<message> { others() >> [=] {
if (!intermediate.empty()) { // inner is const inside this lambda and mutable a C++14 feature
// do no use lamba expresion type to behavior cpy = inner;
// avoid recursive template instantiaton auto inner_res = cpy(self->last_dequeued());
behavior::continuation_fun f2 = [=]( if (inner_res) {
message & m)->optional<message> { fhdl.deliver(*inner_res);
return std::move(m);
};
auto mutable_mid = mid;
// recursively call invoke_fun on the
// result to correctly handle stuff like
// sync_send(...).then(...).then(...)...
return this->invoke_fun(self, intermediate,
mutable_mid, f2, fhdl);
} }
return none; }
}); };
} }
// reset res to prevent "outer" invoke_fun
// from handling the result again
res->reset();
} else { } else {
// respond by using the result of 'fun' // respond by using the result of 'fun'
CAF_LOG_DEBUG("respond via response_promise"); CAF_LOG_DEBUG("respond via response_promise");
......
...@@ -65,7 +65,7 @@ class no_scheduling { ...@@ -65,7 +65,7 @@ class no_scheduling {
} }
template <class Actor> template <class Actor>
void launch(Actor* self, execution_unit*) { void launch(Actor* self, execution_unit*, bool) {
CAF_REQUIRE(self != nullptr); CAF_REQUIRE(self != nullptr);
CAF_PUSH_AID(self->id()); CAF_PUSH_AID(self->id());
CAF_LOG_TRACE(CAF_ARG(self)); CAF_LOG_TRACE(CAF_ARG(self));
......
...@@ -20,22 +20,88 @@ ...@@ -20,22 +20,88 @@
#ifndef CAF_REPLIES_TO_HPP #ifndef CAF_REPLIES_TO_HPP
#define CAF_REPLIES_TO_HPP #define CAF_REPLIES_TO_HPP
#include <string>
#include "caf/either.hpp"
#include "caf/uniform_typeid.hpp"
#include "caf/type_name_access.hpp"
#include "caf/uniform_type_info.hpp"
#include "caf/illegal_message_element.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/type_pair.hpp"
#include "caf/detail/type_traits.hpp"
namespace caf { namespace caf {
/** @cond PRIVATE */
std::string replies_to_type_name(size_t input_size,
const std::string* input,
size_t output_opt1_size,
const std::string* output_opt1,
size_t output_opt2_size,
const std::string* output_opt2);
/** @endcond */
template <class InputTypes, class LeftOutputTypes, class RightOutputTypes>
struct typed_mpi;
template <class... Is, class... Ls, class... Rs>
struct typed_mpi<detail::type_list<Is...>,
detail::type_list<Ls...>,
detail::type_list<Rs...>> {
static_assert(sizeof...(Is) > 0, "template parameter pack Is empty");
static_assert(sizeof...(Ls) > 0, "template parameter pack Ls empty");
using input_types = detail::type_list<Is...>;
using output_opt1_types = detail::type_list<Ls...>;
using output_opt2_types = detail::type_list<Rs...>;
static_assert(!std::is_same<output_opt1_types, output_opt2_types>::value,
"result types must differ when using with_either<>::or_else<>");
static_assert(!detail::tl_exists<
input_types,
is_illegal_message_element
>::value
&& !detail::tl_exists<
output_opt1_types,
is_illegal_message_element
>::value
&& !detail::tl_exists<
output_opt2_types,
is_illegal_message_element
>::value,
"interface definition contains an illegal message type, "
"did you use with<either...> instead of with_either<...>?");
static std::string static_type_name() {
std::string input[] = {type_name_access<Is>::get()...};
std::string output_opt1[] = {type_name_access<Ls>::get()...};
// Rs... is allowed to be empty, hence we need to add a dummy element
// to make sure this array is not of size 0 (to prevent compiler errors)
std::string output_opt2[] = {std::string(), type_name_access<Rs>::get()...};
return replies_to_type_name(sizeof...(Is), input,
sizeof...(Ls), output_opt1,
sizeof...(Rs), output_opt2 + 1);
}
};
template <class... Is> template <class... Is>
struct replies_to { struct replies_to {
template <class... Os> template <class... Os>
struct with { using with = typed_mpi<detail::type_list<Is...>,
using input_types = detail::type_list<Is...>; detail::type_list<Os...>,
using output_types = detail::type_list<Os...>; detail::empty_type_list>;
template <class... Ls>
struct with_either {
template <class... Rs>
using or_else = typed_mpi<detail::type_list<Is...>,
detail::type_list<Ls...>,
detail::type_list<Rs...>>;
}; };
}; };
template <class... Is> template <class... Is>
using reacts_to = typename replies_to<Is...>::template with<void>; using reacts_to = typed_mpi<detail::type_list<Is...>,
detail::type_list<void>,
detail::empty_type_list>;
} // namespace caf } // namespace caf
......
...@@ -51,7 +51,7 @@ struct blocking_response_handle_tag {}; ...@@ -51,7 +51,7 @@ struct blocking_response_handle_tag {};
* This helper class identifies an expected response message * This helper class identifies an expected response message
* and enables `sync_send(...).then(...)`. * and enables `sync_send(...).then(...)`.
*/ */
template <class Self, class Result, class Tag> template <class Self, class ResultOptPairOrMessage, class Tag>
class response_handle; class response_handle;
/****************************************************************************** /******************************************************************************
...@@ -80,8 +80,7 @@ class response_handle<Self, message, nonblocking_response_handle_tag> { ...@@ -80,8 +80,7 @@ class response_handle<Self, message, nonblocking_response_handle_tag> {
} }
}; };
m_self->bhvr_stack().push_back(std::move(bhvr), m_mid); m_self->bhvr_stack().push_back(std::move(bhvr), m_mid);
auto ptr = m_self; return {m_mid};
return {m_mid, [ptr](message_id mid) { return ptr->sync_handler(mid); }};
} }
private: private:
...@@ -92,9 +91,8 @@ class response_handle<Self, message, nonblocking_response_handle_tag> { ...@@ -92,9 +91,8 @@ class response_handle<Self, message, nonblocking_response_handle_tag> {
/****************************************************************************** /******************************************************************************
* nonblocking + typed * * nonblocking + typed *
******************************************************************************/ ******************************************************************************/
template <class Self, class... Ts> template <class Self, class TypedOutputPair>
class response_handle<Self, detail::type_list<Ts...>, class response_handle<Self, TypedOutputPair, nonblocking_response_handle_tag> {
nonblocking_response_handle_tag> {
public: public:
response_handle() = delete; response_handle() = delete;
response_handle(const response_handle&) = default; response_handle(const response_handle&) = default;
...@@ -104,28 +102,30 @@ class response_handle<Self, detail::type_list<Ts...>, ...@@ -104,28 +102,30 @@ class response_handle<Self, detail::type_list<Ts...>,
// nop // nop
} }
template <class F, template <class... Fs>
class Enable = typename std::enable_if<
detail::is_callable<F>::value
&& !is_match_expr<F>::value
>::type>
typed_continue_helper< typed_continue_helper<
typename detail::lifted_result_type< typename detail::lifted_result_type<
typename detail::get_callable_trait<F>::result_type typename detail::common_result_type<
typename detail::get_callable_trait<Fs>::result_type...
>::type
>::type> >::type>
then(F fun) { then(Fs... fs) {
detail::assert_types<detail::type_list<Ts...>, F>(); static_assert(sizeof...(Fs) > 0, "at least one functor is requried");
static_assert(detail::conjunction<detail::is_callable<Fs>::value...>::value,
"all arguments must be callable");
static_assert(detail::conjunction<!is_match_expr<Fs>::value...>::value,
"match expressions are not allowed in this context");
detail::type_checker<TypedOutputPair, Fs...>::check();
auto selfptr = m_self; auto selfptr = m_self;
behavior tmp{ behavior tmp{
fun, fs...,
on<sync_timeout_msg>() >> [selfptr]() -> skip_message_t { on<sync_timeout_msg>() >> [selfptr]() -> skip_message_t {
selfptr->handle_sync_timeout(); selfptr->handle_sync_timeout();
return {}; return {};
} }
}; };
m_self->bhvr_stack().push_back(std::move(tmp), m_mid); m_self->bhvr_stack().push_back(std::move(tmp), m_mid);
auto get = [selfptr](message_id mid) { return selfptr->sync_handler(mid); }; return {m_mid};
return {m_mid, get};
} }
private: private:
...@@ -173,12 +173,9 @@ class response_handle<Self, message, blocking_response_handle_tag> { ...@@ -173,12 +173,9 @@ class response_handle<Self, message, blocking_response_handle_tag> {
/****************************************************************************** /******************************************************************************
* blocking + typed * * blocking + typed *
******************************************************************************/ ******************************************************************************/
template <class Self, class... Ts> template <class Self, class OutputPair>
class response_handle<Self, detail::type_list<Ts...>, class response_handle<Self, OutputPair, blocking_response_handle_tag> {
blocking_response_handle_tag> {
public: public:
using result_types = detail::type_list<Ts...>;
response_handle() = delete; response_handle() = delete;
response_handle(const response_handle&) = default; response_handle(const response_handle&) = default;
response_handle& operator=(const response_handle&) = default; response_handle& operator=(const response_handle&) = default;
...@@ -187,26 +184,27 @@ class response_handle<Self, detail::type_list<Ts...>, ...@@ -187,26 +184,27 @@ class response_handle<Self, detail::type_list<Ts...>,
// nop // nop
} }
template <class F> static constexpr bool is_either_or_handle =
void await(F fun) { !std::is_same<
using arg_types = none_t,
typename detail::tl_map< typename OutputPair::second
typename detail::get_callable_trait<F>::arg_types, >::value;
std::decay
>::type; template <class... Fs>
static constexpr size_t fun_args = detail::tl_size<arg_types>::value; void await(Fs... fs) {
static_assert(fun_args <= detail::tl_size<result_types>::value, static_assert(sizeof...(Fs) > 0,
"functor takes too much arguments"); "at least one argument is required");
using recv_types = static_assert((is_either_or_handle && sizeof...(Fs) == 2)
typename detail::tl_right< || sizeof...(Fs) == 1,
result_types, "wrong number of functors");
fun_args static_assert(detail::conjunction<detail::is_callable<Fs>::value...>::value,
>::type; "all arguments must be callable");
static_assert(std::is_same<arg_types, recv_types>::value, static_assert(detail::conjunction<!is_match_expr<Fs>::value...>::value,
"wrong functor signature"); "match expressions are not allowed in this context");
detail::type_checker<OutputPair, Fs...>::check();
auto selfptr = m_self; auto selfptr = m_self;
behavior tmp{ behavior tmp{
fun, fs...,
on<sync_timeout_msg>() >> [selfptr]() -> skip_message_t { on<sync_timeout_msg>() >> [selfptr]() -> skip_message_t {
selfptr->handle_sync_timeout(); selfptr->handle_sync_timeout();
return {}; return {};
......
...@@ -43,10 +43,10 @@ class worker : public execution_unit { ...@@ -43,10 +43,10 @@ class worker : public execution_unit {
using coordinator_ptr = coordinator<Policy>*; using coordinator_ptr = coordinator<Policy>*;
using policy_data = typename Policy::worker_data; using policy_data = typename Policy::worker_data;
worker(size_t id, coordinator_ptr parent, size_t max_throughput) worker(size_t worker_id, coordinator_ptr worker_parent, size_t throughput)
: m_max_throughput(max_throughput), : m_max_throughput(throughput),
m_id(id), m_id(worker_id),
m_parent(parent) { m_parent(worker_parent) {
// nop // nop
} }
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include "caf/uniform_type_info.hpp" #include "caf/uniform_type_info.hpp"
#include "caf/primitive_variant.hpp" #include "caf/primitive_variant.hpp"
#include "caf/detail/to_uniform_name.hpp"
namespace caf { namespace caf {
class actor_namespace; class actor_namespace;
...@@ -111,8 +109,7 @@ template <class T> ...@@ -111,8 +109,7 @@ template <class T>
serializer& operator<<(serializer& s, const T& what) { serializer& operator<<(serializer& s, const T& what) {
auto mtype = uniform_typeid<T>(); auto mtype = uniform_typeid<T>();
if (mtype == nullptr) { if (mtype == nullptr) {
throw std::logic_error("no uniform type info found for " throw std::logic_error("no uniform type info found for T");
+ detail::to_uniform_name(typeid(T)));
} }
mtype->serialize(&what, &s); mtype->serialize(&what, &s);
return s; return s;
......
...@@ -69,7 +69,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host, ...@@ -69,7 +69,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host,
"spawned without blocking_api_flag"); "spawned without blocking_api_flag");
static_assert(is_unbound(Os), static_assert(is_unbound(Os),
"top-level spawns cannot have monitor or link flag"); "top-level spawns cannot have monitor or link flag");
CAF_LOGF_TRACE("spawn " << detail::demangle<C>()); CAF_LOGF_TRACE("");
using scheduling_policy = using scheduling_policy =
typename std::conditional< typename std::conditional<
has_detach_flag(Os) || has_blocking_api_flag(Os), has_detach_flag(Os) || has_blocking_api_flag(Os),
...@@ -114,7 +114,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host, ...@@ -114,7 +114,7 @@ intrusive_ptr<C> spawn_impl(execution_unit* host,
CAF_LOGF_DEBUG("spawned actor with ID " << ptr->id()); CAF_LOGF_DEBUG("spawned actor with ID " << ptr->id());
CAF_PUSH_AID(ptr->id()); CAF_PUSH_AID(ptr->id());
before_launch_fun(ptr.get()); before_launch_fun(ptr.get());
ptr->launch(has_hide_flag(Os), host); ptr->launch(has_hide_flag(Os), has_lazy_init_flag(Os), host);
return ptr; return ptr;
} }
......
...@@ -40,8 +40,8 @@ enum class spawn_options : int { ...@@ -40,8 +40,8 @@ enum class spawn_options : int {
detach_flag = 0x04, detach_flag = 0x04,
hide_flag = 0x08, hide_flag = 0x08,
blocking_api_flag = 0x10, blocking_api_flag = 0x10,
priority_aware_flag = 0x20 priority_aware_flag = 0x20,
lazy_init_flag = 0x40
}; };
#endif #endif
...@@ -95,6 +95,12 @@ constexpr spawn_options blocking_api = spawn_options::blocking_api_flag; ...@@ -95,6 +95,12 @@ constexpr spawn_options blocking_api = spawn_options::blocking_api_flag;
*/ */
constexpr spawn_options priority_aware = spawn_options::priority_aware_flag; constexpr spawn_options priority_aware = spawn_options::priority_aware_flag;
/**
* Causes the new actor to delay its
* initialization until a message arrives.
*/
constexpr spawn_options lazy_init = spawn_options::lazy_init_flag;
/** /**
* Checks wheter `haystack` contains `needle`. * Checks wheter `haystack` contains `needle`.
* @relates spawn_options * @relates spawn_options
...@@ -151,6 +157,14 @@ constexpr bool has_blocking_api_flag(spawn_options opts) { ...@@ -151,6 +157,14 @@ constexpr bool has_blocking_api_flag(spawn_options opts) {
return has_spawn_option(opts, blocking_api); return has_spawn_option(opts, blocking_api);
} }
/**
* Checks wheter the {@link lazy_init} flag is set in `opts`.
* @relates spawn_options
*/
constexpr bool has_lazy_init_flag(spawn_options opts) {
return has_spawn_option(opts, lazy_init);
}
/** @} */ /** @} */
/** @cond PRIVATE */ /** @cond PRIVATE */
......
...@@ -72,21 +72,22 @@ void splice(std::string& str, const std::string& glue, T&& arg, Ts&&... args) { ...@@ -72,21 +72,22 @@ void splice(std::string& str, const std::string& glue, T&& arg, Ts&&... args) {
splice(str, glue, std::forward<Ts>(args)...); splice(str, glue, std::forward<Ts>(args)...);
} }
template <size_t WhatSize, size_t WithSize> template <ptrdiff_t WhatSize, ptrdiff_t WithSize>
void replace_all(std::string& str, void replace_all(std::string& str,
const char (&what)[WhatSize], const char (&what)[WhatSize],
const char (&with)[WithSize]) { const char (&with)[WithSize]) {
// end(what) - 1 points to the null-terminator // end(what) - 1 points to the null-terminator
auto next = [&](std::string::iterator pos) -> std::string::iterator{ auto next = [&](std::string::iterator pos) -> std::string::iterator {
return std::search(pos, str.end(), std::begin(what), std::end(what) - 1); return std::search(pos, str.end(), std::begin(what), std::end(what) - 1);
}; };
auto i = next(std::begin(str)); auto i = next(std::begin(str));
while (i != std::end(str)) { while (i != std::end(str)) {
auto before = static_cast<size_t>(std::distance(std::begin(str), i)); auto before = std::distance(std::begin(str), i);
CAF_REQUIRE(before >= 0);
str.replace(i, i + WhatSize - 1, with); str.replace(i, i + WhatSize - 1, with);
// i became invalidated -> use new iterator pointing // i became invalidated -> use new iterator pointing
// to the first character after the replaced text // to the first character after the replaced text
i = next(std::begin(str) + before + (WithSize - 1)); i = next(str.begin() + before + (WithSize - 1));
} }
} }
......
...@@ -44,11 +44,6 @@ std::string to_string(const actor_addr& what); ...@@ -44,11 +44,6 @@ std::string to_string(const actor_addr& what);
std::string to_string(const actor& what); std::string to_string(const actor& what);
/**
* @relates node_id
*/
//std::string to_string(const node_id::host_id_type& node_id);
/** /**
* @relates node_id * @relates node_id
*/ */
...@@ -60,7 +55,7 @@ std::string to_string(const node_id& what); ...@@ -60,7 +55,7 @@ std::string to_string(const node_id& what);
std::string to_string(const atom_value& what); std::string to_string(const atom_value& what);
/** /**
* Converts `e` to a string including the demangled type of `e` and `e.what()`. * Converts `e` to a string including `e.what()`.
*/ */
std::string to_verbose_string(const std::exception& e); std::string to_verbose_string(const std::exception& e);
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_TYPE_NAME_ACCESS_HPP
#define CAF_TYPE_NAME_ACCESS_HPP
#include <string>
#include "caf/uniform_typeid.hpp"
#include "caf/uniform_type_info.hpp"
#include "caf/detail/type_traits.hpp"
namespace caf {
template <class T, bool HasTypeName = detail::has_static_type_name<T>::value>
struct type_name_access {
static std::string get() {
auto uti = uniform_typeid<T>(true);
return uti ? uti->name() : "void";
}
};
template <class T>
struct type_name_access<T, true> {
static std::string get() {
return T::static_type_name();
}
};
} // namespace caf
#endif // CAF_TYPE_NAME_ACCESS_HPP
...@@ -131,7 +131,7 @@ class typed_actor ...@@ -131,7 +131,7 @@ class typed_actor
} }
static std::set<std::string> message_types() { static std::set<std::string> message_types() {
return {detail::to_uniform_name<Rs>()...}; return {Rs::static_type_name()...};
} }
explicit operator bool() const { return static_cast<bool>(m_ptr); } explicit operator bool() const { return static_cast<bool>(m_ptr); }
......
...@@ -20,11 +20,13 @@ ...@@ -20,11 +20,13 @@
#ifndef TYPED_BEHAVIOR_HPP #ifndef TYPED_BEHAVIOR_HPP
#define TYPED_BEHAVIOR_HPP #define TYPED_BEHAVIOR_HPP
#include "caf/either.hpp"
#include "caf/behavior.hpp" #include "caf/behavior.hpp"
#include "caf/match_expr.hpp" #include "caf/match_expr.hpp"
#include "caf/system_messages.hpp" #include "caf/system_messages.hpp"
#include "caf/typed_continue_helper.hpp" #include "caf/typed_continue_helper.hpp"
#include "caf/detail/ctm.hpp"
#include "caf/detail/typed_actor_util.hpp" #include "caf/detail/typed_actor_util.hpp"
namespace caf { namespace caf {
...@@ -46,17 +48,27 @@ struct input_only<detail::type_list<Ts...>> { ...@@ -46,17 +48,27 @@ struct input_only<detail::type_list<Ts...>> {
using skip_list = detail::type_list<skip_message_t>; using skip_list = detail::type_list<skip_message_t>;
template <class Opt1, class Opt2>
struct collapse_replies_to_statement {
using type = typename either<Opt1>::template or_else<Opt2>;
};
template <class List>
struct collapse_replies_to_statement<List, none_t> {
using type = List;
};
/*
template <class List> template <class List>
struct unbox_typed_continue_helper { struct unbox_typed_continue_helper {
// do nothing if List is actually a list, i.e., not a typed_continue_helper
using type = List; using type = List;
}; };
template <class List> template <class List>
struct unbox_typed_continue_helper< struct unbox_typed_continue_helper<typed_continue_helper<List>> {
detail::type_list<typed_continue_helper<List>>> {
using type = List; using type = List;
}; };
*/
template <class Input, class RepliesToWith> template <class Input, class RepliesToWith>
struct same_input : std::is_same<Input, typename RepliesToWith::input_types> {}; struct same_input : std::is_same<Input, typename RepliesToWith::input_types> {};
...@@ -75,8 +87,9 @@ struct valid_input_predicate { ...@@ -75,8 +87,9 @@ struct valid_input_predicate {
struct inner { struct inner {
using input_types = typename Expr::input_types; using input_types = typename Expr::input_types;
using output_types = using output_types =
typename unbox_typed_continue_helper< typename collapse_replies_to_statement<
typename Expr::output_types typename Expr::output_opt1_types,
typename Expr::output_opt2_types
>::type; >::type;
// get matching elements for input type // get matching elements for input type
using filtered_slist = using filtered_slist =
...@@ -215,10 +228,12 @@ class typed_behavior { ...@@ -215,10 +228,12 @@ class typed_behavior {
template <class... Cs> template <class... Cs>
void set(match_expr<Cs...>&& expr) { void set(match_expr<Cs...>&& expr) {
using input = using mpi =
detail::type_list<typename detail::deduce_signature<Cs>::type...>; typename detail::tl_filter_not<
// check types detail::type_list<typename detail::deduce_mpi<Cs>::type...>,
detail::static_check_typed_behavior_input<signatures, input>(); detail::is_hidden_msg_handler
>::type;
detail::static_asserter<signatures, mpi, detail::ctm>::verify_match();
// final (type-erasure) step // final (type-erasure) step
m_bhvr = std::move(expr); m_bhvr = std::move(expr);
} }
......
...@@ -32,10 +32,8 @@ template <class OutputList> ...@@ -32,10 +32,8 @@ template <class OutputList>
class typed_continue_helper { class typed_continue_helper {
public: public:
using message_id_wrapper_tag = int; using message_id_wrapper_tag = int;
using getter = std::function<optional<behavior&> (message_id msg_id)>;
typed_continue_helper(message_id mid, getter get_sync_handler) typed_continue_helper(message_id mid) : m_ch(mid) {
: m_ch(mid, std::move(get_sync_handler)) {
// nop // nop
} }
...@@ -43,14 +41,6 @@ class typed_continue_helper { ...@@ -43,14 +41,6 @@ class typed_continue_helper {
// nop // nop
} }
template <class F>
typed_continue_helper<typename detail::get_callable_trait<F>::result_type>
continue_with(F fun) {
detail::assert_types<OutputList, F>();
m_ch.continue_with(std::move(fun));
return {m_ch};
}
message_id get_message_id() const { message_id get_message_id() const {
return m_ch.get_message_id(); return m_ch.get_message_id();
} }
......
...@@ -49,7 +49,7 @@ class typed_event_based_actor : public ...@@ -49,7 +49,7 @@ class typed_event_based_actor : public
using behavior_type = typed_behavior<Rs...>; using behavior_type = typed_behavior<Rs...>;
std::set<std::string> message_types() const override { std::set<std::string> message_types() const override {
return {detail::to_uniform_name<Rs>()...}; return {Rs::static_type_name()...};
} }
protected: protected:
......
...@@ -29,20 +29,16 @@ ...@@ -29,20 +29,16 @@
#include <type_traits> #include <type_traits>
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/uniform_typeid.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/detail/demangle.hpp"
#include "caf/detail/to_uniform_name.hpp"
namespace caf { namespace caf {
class serializer; class serializer;
class deserializer; class deserializer;
class uniform_type_info; class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
struct uniform_value_t; struct uniform_value_t;
using uniform_value = std::unique_ptr<uniform_value_t>; using uniform_value = std::unique_ptr<uniform_value_t>;
...@@ -203,8 +199,8 @@ class uniform_type_info { ...@@ -203,8 +199,8 @@ class uniform_type_info {
/** /**
* Creates a copy of `other`. * Creates a copy of `other`.
*/ */
virtual uniform_value virtual uniform_value create(const uniform_value& other
create(const uniform_value& other = uniform_value{}) const = 0; = uniform_value{}) const = 0;
/** /**
* Deserializes an object of this type from `source`. * Deserializes an object of this type from `source`.
...@@ -279,18 +275,14 @@ using uniform_type_info_ptr = std::unique_ptr<uniform_type_info>; ...@@ -279,18 +275,14 @@ using uniform_type_info_ptr = std::unique_ptr<uniform_type_info>;
/** /**
* @relates uniform_type_info * @relates uniform_type_info
*/ */
template <class T>
inline const uniform_type_info* uniform_typeid() {
return uniform_typeid(typeid(T));
}
/** /**
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator==(const uniform_type_info& lhs, inline bool operator==(const uniform_type_info& lhs,
const uniform_type_info& rhs) { const uniform_type_info& rhs) {
// uniform_type_info instances are singletons, // uniform_type_info instances are singletons
// thus, equal == identical
return &lhs == &rhs; return &lhs == &rhs;
} }
...@@ -306,7 +298,7 @@ inline bool operator!=(const uniform_type_info& lhs, ...@@ -306,7 +298,7 @@ inline bool operator!=(const uniform_type_info& lhs,
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator==(const uniform_type_info& lhs, inline bool operator==(const uniform_type_info& lhs,
const std::type_info& rhs) { const std::type_info& rhs) {
return lhs.equal_to(rhs); return lhs.equal_to(rhs);
} }
...@@ -314,7 +306,7 @@ inline bool operator==(const uniform_type_info& lhs, ...@@ -314,7 +306,7 @@ inline bool operator==(const uniform_type_info& lhs,
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator!=(const uniform_type_info& lhs, inline bool operator!=(const uniform_type_info& lhs,
const std::type_info& rhs) { const std::type_info& rhs) {
return !(lhs.equal_to(rhs)); return !(lhs.equal_to(rhs));
} }
...@@ -322,7 +314,7 @@ inline bool operator!=(const uniform_type_info& lhs, ...@@ -322,7 +314,7 @@ inline bool operator!=(const uniform_type_info& lhs,
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator==(const std::type_info& lhs, inline bool operator==(const std::type_info& lhs,
const uniform_type_info& rhs) { const uniform_type_info& rhs) {
return rhs.equal_to(lhs); return rhs.equal_to(lhs);
} }
...@@ -330,7 +322,7 @@ inline bool operator==(const std::type_info& lhs, ...@@ -330,7 +322,7 @@ inline bool operator==(const std::type_info& lhs,
* @relates uniform_type_info * @relates uniform_type_info
*/ */
inline bool operator!=(const std::type_info& lhs, inline bool operator!=(const std::type_info& lhs,
const uniform_type_info& rhs) { const uniform_type_info& rhs) {
return !(rhs.equal_to(lhs)); return !(rhs.equal_to(lhs));
} }
......
...@@ -17,24 +17,23 @@ ...@@ -17,24 +17,23 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_TO_UNIFORM_NAME_HPP #ifndef CAF_UNIFORM_TYPEID_HPP
#define CAF_DETAIL_TO_UNIFORM_NAME_HPP #define CAF_UNIFORM_TYPEID_HPP
#include <string>
#include <typeinfo> #include <typeinfo>
namespace caf { namespace caf {
namespace detail {
std::string to_uniform_name(const std::string& demangled_name); class uniform_type_info;
std::string to_uniform_name(const std::type_info& tinfo);
const uniform_type_info* uniform_typeid(const std::type_info& tinf,
bool allow_nullptr = false);
template <class T> template <class T>
inline std::string to_uniform_name() { const uniform_type_info* uniform_typeid(bool allow_nullptr = false) {
return to_uniform_name(typeid(T)); return uniform_typeid(typeid(T), allow_nullptr);
} }
} // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_TO_UNIFORM_NAME_HPP #endif // CAF_UNIFORM_TYPEID_HPP
...@@ -23,11 +23,17 @@ ...@@ -23,11 +23,17 @@
namespace caf { namespace caf {
struct unit_t { struct unit_t {
constexpr unit_t() {} constexpr unit_t() {
constexpr unit_t(const unit_t&) {} // nop
}
constexpr unit_t(const unit_t&) {
// nop
}
template <class T> template <class T>
explicit constexpr unit_t(T&&) {} explicit constexpr unit_t(T&&) {
// nop
}
unit_t& operator=(const unit_t&) = default;
}; };
static constexpr unit_t unit = unit_t{}; static constexpr unit_t unit = unit_t{};
...@@ -35,25 +41,21 @@ static constexpr unit_t unit = unit_t{}; ...@@ -35,25 +41,21 @@ static constexpr unit_t unit = unit_t{};
template <class T> template <class T>
struct lift_void { struct lift_void {
using type = T; using type = T;
}; };
template <> template <>
struct lift_void<void> { struct lift_void<void> {
using type = unit_t; using type = unit_t;
}; };
template <class T> template <class T>
struct unlift_void { struct unlift_void {
using type = T; using type = T;
}; };
template <> template <>
struct unlift_void<unit_t> { struct unlift_void<unit_t> {
using type = void; using type = void;
}; };
} // namespace caf } // namespace caf
......
...@@ -94,7 +94,7 @@ class cow_tuple<Head, Tail...> { ...@@ -94,7 +94,7 @@ class cow_tuple<Head, Tail...> {
return cow_tuple<Tail...>::offset_subtuple(m_vals, 1); return cow_tuple<Tail...>::offset_subtuple(m_vals, 1);
} }
inline operator message() { inline operator message() const {
return message{m_vals}; return message{m_vals};
} }
......
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include "caf/on.hpp" #include "caf/on.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
#include "caf/detail/demangle.hpp"
#include "cppa/opt_impls.hpp" #include "cppa/opt_impls.hpp"
namespace caf { namespace caf {
...@@ -43,7 +41,8 @@ using string_proj = std::function<optional<std::string> (const std::string&)>; ...@@ -43,7 +41,8 @@ using string_proj = std::function<optional<std::string> (const std::string&)>;
inline string_proj extract_longopt_arg(const std::string& prefix) { inline string_proj extract_longopt_arg(const std::string& prefix) {
return [prefix](const std::string& arg) -> optional<std::string> { return [prefix](const std::string& arg) -> optional<std::string> {
if (arg.compare(0, prefix.size(), prefix) == 0) { if (arg.compare(0, prefix.size(), prefix) == 0) {
return std::string(arg.begin() + prefix.size(), arg.end()); return std::string(arg.begin() + static_cast<ptrdiff_t>(prefix.size()),
arg.end());
} }
return none; return none;
}; };
......
...@@ -93,7 +93,7 @@ class rd_arg_functor { ...@@ -93,7 +93,7 @@ class rd_arg_functor {
auto opt = conv_arg_impl<T>::_(arg); auto opt = conv_arg_impl<T>::_(arg);
if (!opt) { if (!opt) {
std::cerr << "*** error: cannot convert \"" << arg << "\" to " std::cerr << "*** error: cannot convert \"" << arg << "\" to "
<< detail::demangle(typeid(T).name()) << typeid(T).name()
<< " [option: \"" << m_storage->arg_name << "\"]" << " [option: \"" << m_storage->arg_name << "\"]"
<< std::endl; << std::endl;
return false; return false;
...@@ -126,7 +126,7 @@ class add_arg_functor { ...@@ -126,7 +126,7 @@ class add_arg_functor {
auto opt = conv_arg_impl<T>::_(arg); auto opt = conv_arg_impl<T>::_(arg);
if (!opt) { if (!opt) {
std::cerr << "*** error: cannot convert \"" << arg << "\" to " std::cerr << "*** error: cannot convert \"" << arg << "\" to "
<< detail::demangle(typeid(T)) << typeid(T).name()
<< " [option: \"" << m_storage->arg_name << "\"]" << " [option: \"" << m_storage->arg_name << "\"]"
<< std::endl; << std::endl;
return false; return false;
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "caf/detail/types_array.hpp" #include "caf/detail/types_array.hpp"
#include "caf/detail/decorated_tuple.hpp" #include "caf/detail/decorated_tuple.hpp"
#include "cppa/cow_tuple.hpp"
namespace caf { namespace caf {
template <class TupleIter, class PatternIter, template <class TupleIter, class PatternIter,
...@@ -133,8 +135,11 @@ auto moving_tuple_cast(message& tup) ...@@ -133,8 +135,11 @@ auto moving_tuple_cast(message& tup)
} }
} }
// same for nil, leading, and trailing // same for nil, leading, and trailing
if (std::equal(sub.begin(), sub.end(), auto eq = [](const detail::message_iterator& lhs,
arr_pos, detail::types_only_eq)) { const uniform_type_info* rhs) {
return lhs.type() == rhs;
};
if (std::equal(sub.begin(), sub.end(), arr_pos, eq)) {
return result_type::from(sub); return result_type::from(sub);
} }
return none; return none;
......
...@@ -121,8 +121,9 @@ bool abstract_actor::link_impl(linking_operation op, const actor_addr& other) { ...@@ -121,8 +121,9 @@ bool abstract_actor::link_impl(linking_operation op, const actor_addr& other) {
return remove_link_impl(other); return remove_link_impl(other);
case remove_backlink_op: case remove_backlink_op:
return remove_backlink_impl(other); return remove_backlink_impl(other);
default:
return false;
} }
return false;
} }
bool abstract_actor::establish_link_impl(const actor_addr& other) { bool abstract_actor::establish_link_impl(const actor_addr& other) {
...@@ -217,7 +218,7 @@ void abstract_actor::cleanup(uint32_t reason) { ...@@ -217,7 +218,7 @@ void abstract_actor::cleanup(uint32_t reason) {
CAF_LOG_INFO_IF(!is_remote(), "cleanup actor with ID " CAF_LOG_INFO_IF(!is_remote(), "cleanup actor with ID "
<< m_id << "; exit reason = " << m_id << "; exit reason = "
<< reason << ", class = " << reason << ", class = "
<< detail::demangle(typeid(*this))); << class_name());
// send exit messages // send exit messages
for (attachable* i = head.get(); i != nullptr; i = i->next.get()) { for (attachable* i = head.get(); i != nullptr; i = i->next.get()) {
i->actor_exited(this, reason); i->actor_exited(this, reason);
......
...@@ -44,7 +44,7 @@ bool abstract_group::subscription::matches(const token& what) { ...@@ -44,7 +44,7 @@ bool abstract_group::subscription::matches(const token& what) {
return ot.group == m_group; return ot.group == m_group;
} }
abstract_group::module::module(std::string name) : m_name(std::move(name)) { abstract_group::module::module(std::string mname) : m_name(std::move(mname)) {
// nop // nop
} }
......
...@@ -91,7 +91,7 @@ uint32_t actor_registry::next_id() { ...@@ -91,7 +91,7 @@ uint32_t actor_registry::next_id() {
} }
void actor_registry::inc_running() { void actor_registry::inc_running() {
# if CAF_LOG_LEVEL >= CAF_DEBUG # if defined(CAF_LOG_LEVEL) && CAF_LOG_LEVEL >= CAF_DEBUG
CAF_LOG_DEBUG("new value = " << ++m_running); CAF_LOG_DEBUG("new value = " << ++m_running);
# else # else
++m_running; ++m_running;
......
...@@ -24,57 +24,8 @@ ...@@ -24,57 +24,8 @@
namespace caf { namespace caf {
namespace {
class continuation_decorator : public detail::behavior_impl {
public:
using super = behavior_impl;
using continuation_fun = behavior::continuation_fun;
using pointer = typename behavior_impl::pointer;
continuation_decorator(continuation_fun fun, pointer ptr)
: super(ptr->timeout()), m_fun(fun), m_decorated(std::move(ptr)) {
CAF_REQUIRE(m_decorated != nullptr);
}
template <class T>
inline bhvr_invoke_result invoke_impl(T& tup) {
auto res = m_decorated->invoke(tup);
if (res) {
return m_fun(*res);
}
return none;
}
bhvr_invoke_result invoke(message& tup) {
return invoke_impl(tup);
}
bhvr_invoke_result invoke(const message& tup) {
return invoke_impl(tup);
}
pointer copy(const generic_timeout_definition& tdef) const {
return new continuation_decorator(m_fun, m_decorated->copy(tdef));
}
void handle_timeout() {
m_decorated->handle_timeout();
}
private:
continuation_fun m_fun;
pointer m_decorated;
};
} // namespace <anonymous>
behavior::behavior(const message_handler& mh) : m_impl(mh.as_behavior_impl()) { behavior::behavior(const message_handler& mh) : m_impl(mh.as_behavior_impl()) {
// nop // nop
} }
behavior behavior::add_continuation(continuation_fun fun) {
return behavior::impl_ptr{new continuation_decorator(std::move(fun), m_impl)};
}
} // namespace caf } // namespace caf
...@@ -30,6 +30,10 @@ blocking_actor::blocking_actor() { ...@@ -30,6 +30,10 @@ blocking_actor::blocking_actor() {
is_blocking(true); is_blocking(true);
} }
blocking_actor::~blocking_actor() {
// avoid weak-vtables warning
}
void blocking_actor::await_all_other_actors_done() { void blocking_actor::await_all_other_actors_done() {
detail::singletons::get_actor_registry()->await_running_count_equal(1); detail::singletons::get_actor_registry()->await_running_count_equal(1);
} }
......
...@@ -22,18 +22,8 @@ ...@@ -22,18 +22,8 @@
namespace caf { namespace caf {
continue_helper::continue_helper(message_id mid, getter g) continue_helper::continue_helper(message_id mid) : m_mid(mid) {
: m_mid(mid), m_getter(std::move(g)) {} // nop
continue_helper& continue_helper::continue_with(behavior::continuation_fun f) {
auto ref_opt = m_getter(m_mid); //m_self->sync_handler(m_mid);
if (ref_opt) {
behavior cpy = *ref_opt;
*ref_opt = cpy.add_continuation(std::move(f));
} else {
CAF_LOG_ERROR("failed to add continuation");
}
return *this;
} }
} // namespace caf } // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/either.hpp"
#include "caf/to_string.hpp"
#include "caf/string_algorithms.hpp"
namespace caf {
std::string either_or_else_type_name(size_t lefts_size,
const std::string* lefts,
size_t rights_size,
const std::string* rights) {
std::string glue = ",";
std::string result;
result = "caf::either<";
result += join(lefts, lefts + lefts_size, glue);
result += ">::or_else<";
result += join(rights, rights + rights_size, glue);
result += ">";
return result;
}
} // namespace caf
...@@ -64,8 +64,8 @@ actor_exited::~actor_exited() noexcept { ...@@ -64,8 +64,8 @@ actor_exited::~actor_exited() noexcept {
// nop // nop
} }
actor_exited::actor_exited(uint32_t reason) : caf_exception(ae_what(reason)) { actor_exited::actor_exited(uint32_t rsn) : caf_exception(ae_what(rsn)) {
m_reason = reason; m_reason = rsn;
} }
network_error::network_error(const std::string& str) : super(str) { network_error::network_error(const std::string& str) : super(str) {
......
/******************************************************************************
* _________________________ *
* __ ____/__ |__ ____/ C++ *
* _ / __ /| |_ /_ Actor *
* / /___ _ ___ | __/ Framework *
* ____/ /_/ |_/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENCE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
/******************************************************************************\
* Based on work by the mingw-w64 project; *
* original header: *
* *
* Copyright (c) 2012 mingw-w64 project *
* *
* Contributing author: Kai Tietz *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is 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 Software. *
* *
* THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
\ ******************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <sstream>
#include <iostream>
#include "cppa/detail/execinfo_windows.hpp"
namespace cppa {
namespace detail {
int backtrace(void** buffer, int size) {
if (size <= 0) return 0;
auto frames = CaptureStackBackTrace (0, (DWORD) size, buffer, NULL);
return static_cast<int>(frames);
}
void backtrace_symbols_fd(void* const* buffer, int size, int fd) {
std::ostringstream out;
for (int i = 0; i < size; i++) {
out << "[" << std::hex << reinterpret_cast<size_t>(buffer[i])
<< "]" << std::endl;
auto s = out.str();
write(fd, s.c_str(), s.size());
}
_commit(fd);
}
} // namespace detail
} // namespace cppa
...@@ -17,63 +17,63 @@ ...@@ -17,63 +17,63 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#include "caf/forwarding_actor_proxy.hpp"
#include "caf/send.hpp" #include "caf/send.hpp"
#include "caf/locks.hpp"
#include "caf/to_string.hpp" #include "caf/to_string.hpp"
#include "caf/io/middleman.hpp"
#include "caf/io/remote_actor_proxy.hpp"
#include "caf/detail/memory.hpp"
#include "caf/detail/logging.hpp" #include "caf/detail/logging.hpp"
#include "caf/detail/singletons.hpp"
#include "caf/detail/sync_request_bouncer.hpp"
using namespace std; using namespace std;
namespace caf { namespace caf {
namespace io {
inline sync_request_info* new_req_info(actor_addr sptr, message_id id) {
return detail::memory::create<sync_request_info>(std::move(sptr), id);
}
sync_request_info::~sync_request_info() { forwarding_actor_proxy::forwarding_actor_proxy(actor_id aid, node_id nid,
// nop actor mgr)
: actor_proxy(aid, nid),
m_manager(mgr) {
CAF_REQUIRE(mgr != invalid_actor);
CAF_LOG_INFO(CAF_ARG(aid) << ", " << CAF_TARG(nid, to_string));
} }
sync_request_info::sync_request_info(actor_addr sptr, message_id id) forwarding_actor_proxy::~forwarding_actor_proxy() {
: next(nullptr), sender(std::move(sptr)), mid(id) { anon_send(m_manager, make_message(atom("_DelProxy"), node(), id()));
// nop
} }
remote_actor_proxy::remote_actor_proxy(actor_id aid, node_id nid, actor parent) actor forwarding_actor_proxy::manager() const {
: super(aid, nid), m_parent(parent) { actor result;
CAF_REQUIRE(parent != invalid_actor); {
CAF_LOG_INFO(CAF_ARG(aid) << ", " << CAF_TARG(nid, to_string)); shared_lock<detail::shared_spinlock> m_guard(m_manager_mtx);
result = m_manager;
}
return result;
} }
remote_actor_proxy::~remote_actor_proxy() { void forwarding_actor_proxy::manager(actor new_manager) {
anon_send(m_parent, make_message(atom("_DelProxy"), node(), id())); std::unique_lock<detail::shared_spinlock> m_guard(m_manager_mtx);
m_manager.swap(new_manager);
} }
void remote_actor_proxy::forward_msg(const actor_addr& sender, message_id mid, void forwarding_actor_proxy::forward_msg(const actor_addr& sender,
message msg) { message_id mid, message msg) {
CAF_LOG_TRACE(CAF_ARG(id()) << ", " << CAF_TSARG(sender) << ", " CAF_LOG_TRACE(CAF_ARG(id()) << ", " << CAF_TSARG(sender) << ", "
<< CAF_MARG(mid, integer_value) << ", " << CAF_MARG(mid, integer_value) << ", "
<< CAF_TSARG(msg)); << CAF_TSARG(msg));
m_parent->enqueue( shared_lock<detail::shared_spinlock> m_guard(m_manager_mtx);
invalid_actor_addr, invalid_message_id, m_manager->enqueue(invalid_actor_addr, invalid_message_id,
make_message(atom("_Dispatch"), sender, address(), mid, std::move(msg)), make_message(atom("_Dispatch"), sender,
nullptr); address(), mid, std::move(msg)),
nullptr);
} }
void remote_actor_proxy::enqueue(const actor_addr& sender, message_id mid, void forwarding_actor_proxy::enqueue(const actor_addr& sender, message_id mid,
message m, execution_unit*) { message m, execution_unit*) {
forward_msg(sender, mid, std::move(m)); forward_msg(sender, mid, std::move(m));
} }
bool remote_actor_proxy::link_impl(linking_operation op, bool forwarding_actor_proxy::link_impl(linking_operation op,
const actor_addr& other) { const actor_addr& other) {
switch (op) { switch (op) {
case establish_link_op: case establish_link_op:
if (establish_link_impl(other)) { if (establish_link_impl(other)) {
...@@ -83,7 +83,7 @@ bool remote_actor_proxy::link_impl(linking_operation op, ...@@ -83,7 +83,7 @@ bool remote_actor_proxy::link_impl(linking_operation op,
make_message(atom("_Link"), other)); make_message(atom("_Link"), other));
return true; return true;
} }
return false; break;
case remove_link_op: case remove_link_op:
if (remove_link_impl(other)) { if (remove_link_impl(other)) {
// causes remote actor to unlink from (proxy of) other // causes remote actor to unlink from (proxy of) other
...@@ -91,7 +91,7 @@ bool remote_actor_proxy::link_impl(linking_operation op, ...@@ -91,7 +91,7 @@ bool remote_actor_proxy::link_impl(linking_operation op,
make_message(atom("_Unlink"), other)); make_message(atom("_Unlink"), other));
return true; return true;
} }
return false; break;
case establish_backlink_op: case establish_backlink_op:
if (establish_backlink_impl(other)) { if (establish_backlink_impl(other)) {
// causes remote actor to unlink from (proxy of) other // causes remote actor to unlink from (proxy of) other
...@@ -99,7 +99,7 @@ bool remote_actor_proxy::link_impl(linking_operation op, ...@@ -99,7 +99,7 @@ bool remote_actor_proxy::link_impl(linking_operation op,
make_message(atom("_Link"), other)); make_message(atom("_Link"), other));
return true; return true;
} }
return false; break;
case remove_backlink_op: case remove_backlink_op:
if (remove_backlink_impl(other)) { if (remove_backlink_impl(other)) {
// causes remote actor to unlink from (proxy of) other // causes remote actor to unlink from (proxy of) other
...@@ -107,22 +107,21 @@ bool remote_actor_proxy::link_impl(linking_operation op, ...@@ -107,22 +107,21 @@ bool remote_actor_proxy::link_impl(linking_operation op,
make_message(atom("_Unlink"), other)); make_message(atom("_Unlink"), other));
return true; return true;
} }
return false; break;
} }
return false; return false;
} }
void remote_actor_proxy::local_link_to(const actor_addr& other) { void forwarding_actor_proxy::local_link_to(const actor_addr& other) {
establish_link_impl(other); establish_link_impl(other);
} }
void remote_actor_proxy::local_unlink_from(const actor_addr& other) { void forwarding_actor_proxy::local_unlink_from(const actor_addr& other) {
remove_link_impl(other); remove_link_impl(other);
} }
void remote_actor_proxy::kill_proxy(uint32_t reason) { void forwarding_actor_proxy::kill_proxy(uint32_t reason) {
cleanup(reason); cleanup(reason);
} }
} // namespace io
} // namespace caf } // namespace caf
...@@ -134,10 +134,10 @@ std::vector<iface_info> get_mac_addresses() { ...@@ -134,10 +134,10 @@ std::vector<iface_info> get_mac_addresses() {
oss << hex; oss << hex;
oss.width(2); oss.width(2);
oss << ctoi(item->ifr_hwaddr.sa_data[0]); oss << ctoi(item->ifr_hwaddr.sa_data[0]);
for (size_t i = 1; i < 6; ++i) { for (size_t j = 1; j < 6; ++j) {
oss << ":"; oss << ":";
oss.width(2); oss.width(2);
oss << ctoi(item->ifr_hwaddr.sa_data[i]); oss << ctoi(item->ifr_hwaddr.sa_data[j]);
} }
auto addr = oss.str(); auto addr = oss.str();
if (addr != "00:00:00:00:00:00") { if (addr != "00:00:00:00:00:00") {
......
...@@ -30,7 +30,7 @@ group::group(const invalid_group_t&) : m_ptr(nullptr) { ...@@ -30,7 +30,7 @@ group::group(const invalid_group_t&) : m_ptr(nullptr) {
// nop // nop
} }
group::group(abstract_group_ptr ptr) : m_ptr(std::move(ptr)) { group::group(abstract_group_ptr gptr) : m_ptr(std::move(gptr)) {
// nop // nop
} }
......
...@@ -32,7 +32,7 @@ namespace caf { ...@@ -32,7 +32,7 @@ namespace caf {
// later on in spawn(); this prevents subtle bugs that lead to segfaults, // later on in spawn(); this prevents subtle bugs that lead to segfaults,
// e.g., when calling address() in the ctor of a derived class // e.g., when calling address() in the ctor of a derived class
local_actor::local_actor() local_actor::local_actor()
: super(1), : super(size_t{1}),
m_dummy_node(), m_dummy_node(),
m_current_node(&m_dummy_node), m_current_node(&m_dummy_node),
m_planned_exit_reason(exit_reason::not_exited) { m_planned_exit_reason(exit_reason::not_exited) {
...@@ -103,13 +103,13 @@ void local_actor::reply_message(message&& what) { ...@@ -103,13 +103,13 @@ void local_actor::reply_message(message&& what) {
if (!whom) { if (!whom) {
return; return;
} }
auto& id = m_current_node->mid; auto& mid = m_current_node->mid;
if (id.valid() == false || id.is_response()) { if (mid.valid() == false || mid.is_response()) {
send_tuple(actor_cast<channel>(whom), std::move(what)); send_tuple(actor_cast<channel>(whom), std::move(what));
} else if (!id.is_answered()) { } else if (!mid.is_answered()) {
auto ptr = actor_cast<actor>(whom); auto ptr = actor_cast<actor>(whom);
ptr->enqueue(address(), id.response_id(), std::move(what), host()); ptr->enqueue(address(), mid.response_id(), std::move(what), host());
id.mark_as_answered(); mid.mark_as_answered();
} }
} }
...@@ -117,10 +117,10 @@ void local_actor::forward_message(const actor& dest, message_priority prio) { ...@@ -117,10 +117,10 @@ void local_actor::forward_message(const actor& dest, message_priority prio) {
if (!dest) { if (!dest) {
return; return;
} }
auto id = (prio == message_priority::high) auto mid = (prio == message_priority::high)
? m_current_node->mid.with_high_priority() ? m_current_node->mid.with_high_priority()
: m_current_node->mid.with_normal_priority(); : m_current_node->mid.with_normal_priority();
dest->enqueue(m_current_node->sender, id, m_current_node->msg, host()); dest->enqueue(m_current_node->sender, mid, m_current_node->msg, host());
// treat this message as asynchronous message from now on // treat this message as asynchronous message from now on
m_current_node->mid = invalid_message_id; m_current_node->mid = invalid_message_id;
} }
...@@ -130,11 +130,11 @@ void local_actor::send_tuple(message_priority prio, const channel& dest, ...@@ -130,11 +130,11 @@ void local_actor::send_tuple(message_priority prio, const channel& dest,
if (!dest) { if (!dest) {
return; return;
} }
message_id id; message_id mid;
if (prio == message_priority::high) { if (prio == message_priority::high) {
id = id.with_high_priority(); mid = mid.with_high_priority();
} }
dest->enqueue(address(), id, std::move(what), host()); dest->enqueue(address(), mid, std::move(what), host());
} }
void local_actor::send_exit(const actor_addr& whom, uint32_t reason) { void local_actor::send_exit(const actor_addr& whom, uint32_t reason) {
...@@ -166,8 +166,8 @@ void local_actor::cleanup(uint32_t reason) { ...@@ -166,8 +166,8 @@ void local_actor::cleanup(uint32_t reason) {
} }
void local_actor::quit(uint32_t reason) { void local_actor::quit(uint32_t reason) {
CAF_LOG_TRACE("reason = " << reason << ", class " CAF_LOG_TRACE("reason = " << reason << ", class = "
<< detail::demangle(typeid(*this))); << class_name());
planned_exit_reason(reason); planned_exit_reason(reason);
if (is_blocking()) { if (is_blocking()) {
throw actor_exited(reason); throw actor_exited(reason);
......
...@@ -33,7 +33,7 @@ message::message(message&& other) : m_vals(std::move(other.m_vals)) { ...@@ -33,7 +33,7 @@ message::message(message&& other) : m_vals(std::move(other.m_vals)) {
// nop // nop
} }
message::message(const data_ptr& vals) : m_vals(vals) { message::message(const data_ptr& ptr) : m_vals(ptr) {
// nop // nop
} }
...@@ -103,4 +103,15 @@ bool message::dynamically_typed() const { ...@@ -103,4 +103,15 @@ bool message::dynamically_typed() const {
return m_vals ? m_vals->dynamically_typed() : false; return m_vals ? m_vals->dynamically_typed() : false;
} }
message::const_iterator message::begin() const {
return m_vals ? m_vals->begin() : const_iterator{nullptr, 0};
}
/**
* Returns an iterator to the end.
*/
message::const_iterator message::end() const {
return m_vals ? m_vals->end() : const_iterator{nullptr, 0};
}
} // namespace caf } // namespace caf
...@@ -46,6 +46,8 @@ class message_builder::dynamic_msg_data : public detail::message_data { ...@@ -46,6 +46,8 @@ class message_builder::dynamic_msg_data : public detail::message_data {
// nop // nop
} }
~dynamic_msg_data();
const void* at(size_t pos) const override { const void* at(size_t pos) const override {
CAF_REQUIRE(pos < size()); CAF_REQUIRE(pos < size());
return m_elements[pos]->val; return m_elements[pos]->val;
...@@ -76,6 +78,10 @@ class message_builder::dynamic_msg_data : public detail::message_data { ...@@ -76,6 +78,10 @@ class message_builder::dynamic_msg_data : public detail::message_data {
std::vector<uniform_value> m_elements; std::vector<uniform_value> m_elements;
}; };
message_builder::dynamic_msg_data::~dynamic_msg_data() {
// avoid weak-vtables warning
}
message_builder::message_builder() { message_builder::message_builder() {
init(); init();
} }
......
...@@ -27,9 +27,13 @@ message_data::message_data(bool is_dynamic) : m_is_dynamic(is_dynamic) { ...@@ -27,9 +27,13 @@ message_data::message_data(bool is_dynamic) : m_is_dynamic(is_dynamic) {
} }
bool message_data::equals(const message_data& other) const { bool message_data::equals(const message_data& other) const {
auto full_eq = [](const message_iterator& lhs, const message_iterator& rhs) {
return lhs.type() == rhs.type()
&& lhs.type()->equals(lhs.value(), rhs.value());
};
return this == &other return this == &other
|| (size() == other.size() || (size() == other.size()
&& std::equal(begin(), end(), other.begin(), detail::full_eq)); && std::equal(begin(), end(), other.begin(), full_eq));
} }
message_data::message_data(const message_data& other) message_data::message_data(const message_data& other)
......
...@@ -17,24 +17,26 @@ ...@@ -17,24 +17,26 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_DETAIL_DEMANGLE_HPP #include "caf/detail/message_iterator.hpp"
#define CAF_DETAIL_DEMANGLE_HPP
#include <string> #include "caf/detail/message_data.hpp"
#include <typeinfo>
namespace caf { namespace caf {
namespace detail { namespace detail {
std::string demangle(const char* typeid_name); message_iterator::message_iterator(const_pointer dataptr, size_t pos)
std::string demangle(const std::type_info& tinf); : m_pos(pos),
m_data(dataptr) {
// nop
}
const void* message_iterator::value() const {
return m_data->at(m_pos);
}
template <class T> const uniform_type_info* message_iterator::type() const {
inline std::string demangle() { return m_data->type_at(m_pos);
return demangle(typeid(T));
} }
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
#endif // CAF_DETAIL_DEMANGLE_HPP
...@@ -68,8 +68,9 @@ void host_id_from_string(const std::string& hash, ...@@ -68,8 +68,9 @@ void host_id_from_string(const std::string& hash,
for (size_t i = 0; i < node_id.size(); ++i) { for (size_t i = 0; i < node_id.size(); ++i) {
// read two characters, each representing 4 bytes // read two characters, each representing 4 bytes
auto& val = node_id[i]; auto& val = node_id[i];
val = static_cast<uint8_t>(hex_char_value(*j++) << 4); val = static_cast<uint8_t>(hex_char_value(j[0]) << 4)
val |= hex_char_value(*j++); | hex_char_value(j[1]);
j += 2;
} }
} }
...@@ -84,8 +85,9 @@ bool equal(const std::string& hash, const node_id::host_id_type& node_id) { ...@@ -84,8 +85,9 @@ bool equal(const std::string& hash, const node_id::host_id_type& node_id) {
for (size_t i = 0; i < node_id.size(); ++i) { for (size_t i = 0; i < node_id.size(); ++i) {
// read two characters, each representing 4 bytes // read two characters, each representing 4 bytes
uint8_t val; uint8_t val;
val = static_cast<uint8_t>(hex_char_value(*j++) << 4); val = static_cast<uint8_t>(hex_char_value(j[0]) << 4)
val |= hex_char_value(*j++); | hex_char_value(j[1]);
j += 2;
if (val != node_id[i]) { if (val != node_id[i]) {
return false; return false;
} }
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/replies_to.hpp"
#include "caf/to_string.hpp"
#include "caf/string_algorithms.hpp"
namespace caf {
std::string replies_to_type_name(size_t input_size,
const std::string* input,
size_t output_opt1_size,
const std::string* output_opt1,
size_t output_opt2_size,
const std::string* output_opt2) {
std::string glue = ",";
std::string result;
// 'void' is not an announced type, hence we check whether uniform_typeid
// did return a valid pointer to identify 'void' (this has the
// possibility of false positives, but those will be catched anyways)
result = "caf::replies_to<";
result += join(input, input + input_size, glue);
if (output_opt2_size == 0) {
result += ">::with<";
result += join(output_opt1, output_opt1 + output_opt1_size, glue);
} else {
result += ">::with_either<";
result += join(output_opt1, output_opt1 + output_opt1_size, glue);
result += ">::or_else<";
result += join(output_opt2, output_opt2 + output_opt2_size, glue);
}
result += ">";
return result;
}
} // namespace caf
...@@ -65,12 +65,16 @@ namespace { ...@@ -65,12 +65,16 @@ namespace {
using byte = unsigned char; using byte = unsigned char;
using dword = uint32_t; using dword = uint32_t;
static_assert(sizeof(dword) == sizeof(unsigned), "platform not supported");
// macro definitions // macro definitions
// collect four bytes into one word: // collect four bytes into one word:
#define BYTES_TO_DWORD(strptr) \ #define BYTES_TO_DWORD(strptr) \
(((dword) * ((strptr) + 3) << 24) | ((dword) * ((strptr) + 2) << 16) \ ((static_cast<dword>(*((strptr) + 3)) << 24) \
| ((dword) * ((strptr) + 1) << 8) | ((dword) * (strptr))) | (static_cast<dword>(*((strptr) + 2)) << 16) \
| (static_cast<dword>(*((strptr) + 1)) << 8) \
| (static_cast<dword>(*(strptr))))
// ROL(x, n) cyclically rotates x over n bits to the left // ROL(x, n) cyclically rotates x over n bits to the left
// x must be of an unsigned 32 bits type and 0 <= n < 32. // x must be of an unsigned 32 bits type and 0 <= n < 32.
...@@ -93,28 +97,28 @@ using dword = uint32_t; ...@@ -93,28 +97,28 @@ using dword = uint32_t;
#define GG(a, b, c, d, e, x, s) \ #define GG(a, b, c, d, e, x, s) \
{ \ { \
(a) += G((b), (c), (d)) + (x) + 0x5a827999UL; \ (a) += G((b), (c), (d)) + (x) + 0x5a827999U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define HH(a, b, c, d, e, x, s) \ #define HH(a, b, c, d, e, x, s) \
{ \ { \
(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define II(a, b, c, d, e, x, s) \ #define II(a, b, c, d, e, x, s) \
{ \ { \
(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL; \ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define JJ(a, b, c, d, e, x, s) \ #define JJ(a, b, c, d, e, x, s) \
{ \ { \
(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL; \ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
...@@ -128,28 +132,28 @@ using dword = uint32_t; ...@@ -128,28 +132,28 @@ using dword = uint32_t;
#define GGG(a, b, c, d, e, x, s) \ #define GGG(a, b, c, d, e, x, s) \
{ \ { \
(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL; \ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define HHH(a, b, c, d, e, x, s) \ #define HHH(a, b, c, d, e, x, s) \
{ \ { \
(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL; \ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define III(a, b, c, d, e, x, s) \ #define III(a, b, c, d, e, x, s) \
{ \ { \
(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL; \ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
#define JJJ(a, b, c, d, e, x, s) \ #define JJJ(a, b, c, d, e, x, s) \
{ \ { \
(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL; \ (a) += J((b), (c), (d)) + (x) + 0x50a28be6U; \
(a) = ROL((a), (s)) + (e); \ (a) = ROL((a), (s)) + (e); \
(c) = ROL((c), 10); \ (c) = ROL((c), 10); \
} }
...@@ -360,10 +364,10 @@ void MDfinish(dword* MDbuf, const byte* strptr, dword lswlen, dword mswlen) { ...@@ -360,10 +364,10 @@ void MDfinish(dword* MDbuf, const byte* strptr, dword lswlen, dword mswlen) {
// put bytes from strptr into X // put bytes from strptr into X
for (unsigned int i = 0; i < (lswlen & 63); ++i) { for (unsigned int i = 0; i < (lswlen & 63); ++i) {
// byte i goes into word X[i div 4] at pos. 8*(i mod 4) // byte i goes into word X[i div 4] at pos. 8*(i mod 4)
X[i >> 2] ^= (dword) * strptr++ << (8 * (i & 3)); X[i >> 2] ^= static_cast<dword>(*strptr++) << (8 * (i & 3));
} }
// append the bit m_n == 1 // append the bit m_n == 1
X[(lswlen >> 2) & 15] ^= (dword)1 << (8 * (lswlen & 3) + 7); X[(lswlen >> 2) & 15] ^= static_cast<dword>(1) << (8 * (lswlen & 3) + 7);
if ((lswlen & 63) > 55) { if ((lswlen & 63) > 55) {
// length goes to next block // length goes to next block
compress(MDbuf, X); compress(MDbuf, X);
......
...@@ -609,7 +609,7 @@ string to_string(const node_id& what) { ...@@ -609,7 +609,7 @@ string to_string(const node_id& what) {
string to_verbose_string(const std::exception& e) { string to_verbose_string(const std::exception& e) {
std::ostringstream oss; std::ostringstream oss;
oss << detail::demangle(typeid(e)) << ": " << e.what(); oss << "std::exception, what(): " << e.what();
return oss.str(); return oss.str();
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment