Commit e893f505 authored by Joseph Noir's avatar Joseph Noir

Merge branch 'unstable' into topic/opencl

Conflicts:
	configure
	cppa/opencl/actor_facade.hpp
	cppa/opencl/command.hpp
parents 0fc8d66c ffed360f
...@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.8) ...@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.8)
project(cppa C CXX) project(cppa C CXX)
set(LIBCPPA_VERSION_MAJOR 0) set(LIBCPPA_VERSION_MAJOR 0)
set(LIBCPPA_VERSION_MINOR 8) set(LIBCPPA_VERSION_MINOR 9)
set(LIBCPPA_VERSION_PATCH 1) set(LIBCPPA_VERSION_PATCH 0)
# prohibit in-source builds # prohibit in-source builds
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
...@@ -57,7 +57,7 @@ endif (HAVE_VALGRIND_H) ...@@ -57,7 +57,7 @@ endif (HAVE_VALGRIND_H)
# check for g++ >= 4.7 or clang++ > = 3.2 # check for g++ >= 4.7 or clang++ > = 3.2
try_run(ProgramResult try_run(ProgramResult
CompilationSucceeded CompilationSucceeded
${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/get_compiler_version.cpp ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/get_compiler_version.cpp
RUN_OUTPUT_VARIABLE CompilerVersion) RUN_OUTPUT_VARIABLE CompilerVersion)
if (NOT CompilationSucceeded OR NOT ProgramResult EQUAL 0) if (NOT CompilationSucceeded OR NOT ProgramResult EQUAL 0)
message(FATAL_ERROR "Cannot determine compiler version") message(FATAL_ERROR "Cannot determine compiler version")
...@@ -77,7 +77,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") ...@@ -77,7 +77,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
message(STATUS "NOTE: Automatically added -stdlib=libc++ flag, " message(STATUS "NOTE: Automatically added -stdlib=libc++ flag, "
"you can override this by defining CMAKE_CXX_FLAGS " "you can override this by defining CMAKE_CXX_FLAGS "
"(see 'configure --help')") "(see 'configure --help')")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif () endif ()
else () else ()
message(FATAL_ERROR "Your C++ compiler does not support C++11 " message(FATAL_ERROR "Your C++ compiler does not support C++11 "
...@@ -88,12 +88,20 @@ endif () ...@@ -88,12 +88,20 @@ endif ()
if (ENABLE_DEBUG) if (ENABLE_DEBUG)
set(CMAKE_BUILD_TYPE Debug) set(CMAKE_BUILD_TYPE Debug)
add_definitions(-DCPPA_DEBUG_MODE) add_definitions(-DCPPA_DEBUG_MODE)
message(STATUS "Enable libcppa's debug mode")
endif (ENABLE_DEBUG) endif (ENABLE_DEBUG)
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)
if (CPPA_LOG_LEVEL) if (CPPA_LOG_LEVEL)
add_definitions(-DCPPA_LOG_LEVEL=${CPPA_LOG_LEVEL}) add_definitions(-DCPPA_LOG_LEVEL=${CPPA_LOG_LEVEL})
endif(CPPA_LOG_LEVEL) endif(CPPA_LOG_LEVEL)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
# set build default build type if not set # set build default build type if not set
if ("${CMAKE_BUILD_TYPE}" STREQUAL "") if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo) set(CMAKE_BUILD_TYPE RelWithDebInfo)
...@@ -120,11 +128,16 @@ file(GLOB LIBCPPA_HDRS "cppa/*.hpp" ...@@ -120,11 +128,16 @@ file(GLOB LIBCPPA_HDRS "cppa/*.hpp"
# list cpp files including platform-dependent files # list cpp files including platform-dependent files
set(LIBCPPA_SRC set(LIBCPPA_SRC
${LIBCPPA_PLATFORM_SRC} ${LIBCPPA_PLATFORM_SRC}
src/abstract_actor.cpp
src/abstract_channel.cpp
src/abstract_group.cpp
src/abstract_tuple.cpp src/abstract_tuple.cpp
src/actor.cpp src/actor.cpp
src/actor_addr.cpp
src/actor_namespace.cpp src/actor_namespace.cpp
src/actor_proxy.cpp src/actor_proxy.cpp
src/actor_registry.cpp src/actor_registry.cpp
src/actor_ostream.cpp
src/algorithm.cpp src/algorithm.cpp
src/any_tuple.cpp src/any_tuple.cpp
src/atom.cpp src/atom.cpp
...@@ -135,9 +148,11 @@ set(LIBCPPA_SRC ...@@ -135,9 +148,11 @@ set(LIBCPPA_SRC
src/binary_serializer.cpp src/binary_serializer.cpp
src/broker.cpp src/broker.cpp
src/buffer.cpp src/buffer.cpp
src/blocking_actor.cpp
src/channel.cpp src/channel.cpp
src/context_switching_actor.cpp src/context_switching_resume.cpp
src/continuable.cpp src/continuable.cpp
src/continue_helper.cpp
src/decorated_tuple.cpp src/decorated_tuple.cpp
src/actor_proxy.cpp src/actor_proxy.cpp
src/peer.cpp src/peer.cpp
...@@ -149,9 +164,10 @@ set(LIBCPPA_SRC ...@@ -149,9 +164,10 @@ set(LIBCPPA_SRC
src/event_based_actor.cpp src/event_based_actor.cpp
src/exception.cpp src/exception.cpp
src/exit_reason.cpp src/exit_reason.cpp
src/factory.cpp
src/fd_util.cpp src/fd_util.cpp
src/fiber.cpp src/fiber.cpp
src/functor_based_actor.cpp
src/functor_based_blocking_actor.cpp
src/get_root_uuid.cpp src/get_root_uuid.cpp
src/get_mac_addresses.cpp src/get_mac_addresses.cpp
src/group.cpp src/group.cpp
...@@ -175,19 +191,17 @@ set(LIBCPPA_SRC ...@@ -175,19 +191,17 @@ set(LIBCPPA_SRC
src/partial_function.cpp src/partial_function.cpp
src/primitive_variant.cpp src/primitive_variant.cpp
src/ref_counted.cpp src/ref_counted.cpp
src/resumable.cpp
src/remote_actor_proxy.cpp src/remote_actor_proxy.cpp
src/response_handle.cpp src/response_promise.cpp
src/ripemd_160.cpp src/ripemd_160.cpp
src/scheduled_actor.cpp
src/scheduled_actor_dummy.cpp
src/scheduler.cpp src/scheduler.cpp
src/send.cpp src/scoped_actor.cpp
src/self.cpp
src/serializer.cpp src/serializer.cpp
src/shared_spinlock.cpp src/shared_spinlock.cpp
src/singleton_manager.cpp src/singleton_manager.cpp
src/string_serialization.cpp src/string_serialization.cpp
src/thread_mapped_actor.cpp src/sync_request_bouncer.cpp
src/thread_pool_scheduler.cpp src/thread_pool_scheduler.cpp
src/to_uniform_name.cpp src/to_uniform_name.cpp
src/type_lookup_table.cpp src/type_lookup_table.cpp
...@@ -238,6 +252,18 @@ else (DISABLE_CONTEXT_SWITCHING) ...@@ -238,6 +252,18 @@ else (DISABLE_CONTEXT_SWITCHING)
set(DISABLE_CONTEXT_SWITCHING true) set(DISABLE_CONTEXT_SWITCHING true)
else (NOT Boost_FOUND) else (NOT Boost_FOUND)
if (${Boost_VERSION} LESS 105400) if (${Boost_VERSION} LESS 105400)
set(LD_FLAGS ${LD_FLAGS} ${Boost_CONTEXT_LIBRARY})
# nothing to do in this case
else ()
# for boost >= 1.54, we need coroutines as well
message(STATUS "Detected Boost >= 1.54.0, check for coroutines & system")
find_package(Boost 1.51.0 COMPONENTS system context coroutine)
if (Boost_FOUND)
set(LD_FLAGS ${LD_FLAGS} ${Boost_COROUTINE_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY})
endif ()
endif ()
# check again, as second find_package might set this to false
if (Boost_FOUND)
# This hack fixes a problem when the linker search path is the same as # This hack fixes a problem when the linker search path is the same as
# the one provided by the compiler. In this case, CMake replaces the absolute # the one provided by the compiler. In this case, CMake replaces the absolute
# path (e.g., /path/to/lib.so) with -l<lib>, which may cause it to pick up the wrong # path (e.g., /path/to/lib.so) with -l<lib>, which may cause it to pick up the wrong
...@@ -247,10 +273,9 @@ else (DISABLE_CONTEXT_SWITCHING) ...@@ -247,10 +273,9 @@ else (DISABLE_CONTEXT_SWITCHING)
set(CMAKE_EXE_LINKER_FLAGS -L${Boost_LIBRARY_DIRS}) set(CMAKE_EXE_LINKER_FLAGS -L${Boost_LIBRARY_DIRS})
set(INCLUDE_DIRS ${INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) set(INCLUDE_DIRS ${INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
set(LD_DIRS ${LD_DIRS} ${Boost_LIBRARY_DIRS}) set(LD_DIRS ${LD_DIRS} ${Boost_LIBRARY_DIRS})
set(LD_FLAGS ${LD_FLAGS} ${Boost_CONTEXT_LIBRARY})
set(DISABLE_CONTEXT_SWITCHING false) set(DISABLE_CONTEXT_SWITCHING false)
else () else ()
message(WARNING "Boost >= 1.54 is not supported due the unstable API of Boost.Coroutines") # disable implicitly
set(DISABLE_CONTEXT_SWITCHING true) set(DISABLE_CONTEXT_SWITCHING true)
endif () endif ()
endif (NOT Boost_FOUND) endif (NOT Boost_FOUND)
...@@ -348,7 +373,7 @@ endif () ...@@ -348,7 +373,7 @@ endif ()
# check for doxygen and add custom "doc" target to Makefile # check for doxygen and add custom "doc" target to Makefile
find_package(Doxygen) find_package(Doxygen)
if (DOXYGEN_FOUND) if (DOXYGEN_FOUND)
configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_SOURCE_DIR}/Doxyfile configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
@ONLY) @ONLY)
add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_HOME_DIRECTORY}/Doxyfile add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_HOME_DIRECTORY}/Doxyfile
WORKING_DIRECTORY ${CMAKE_HOME_DIRECTORY} WORKING_DIRECTORY ${CMAKE_HOME_DIRECTORY}
......
Version 0.9.0
-------------
__2014_XX_XX__
- Redesigned large parts of the library related to type-safe actors:
* No more thread-local `self`, because it can only return a type-erased handle
* New type `actor` replaces `actor_ptr`, can be used to send any message
* New type `actor_addr` can only be used for monitoring and identifying actors
* New type `exit_msg` is now used instead of messages using the atom `EXIT`
* New type `down_msg` is now used instead of messages using the atom `DOWN`
* New header `system_messages.hpp` for message types used by the runtime
Version 0.8.1 Version 0.8.1
------------- -------------
......
...@@ -31,7 +31,7 @@ PROJECT_NAME = libcppa ...@@ -31,7 +31,7 @@ PROJECT_NAME = libcppa
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # if some version control system is used.
PROJECT_NUMBER = "Version 0.8.1" PROJECT_NUMBER = "Version 0.9.0"
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put. # base path where the generated documentation will be put.
......
...@@ -45,6 +45,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]... ...@@ -45,6 +45,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--enable-debug compile in debugging mode --enable-debug compile in debugging mode
(always sets --build-type=Debug) (always sets --build-type=Debug)
--enable-perftools use Google perftools --enable-perftools use Google perftools
--enable-address-sanitizer use Clang's address sanitizer
--with-cppa-log-level=LVL sets the debugging output, possible values: --with-cppa-log-level=LVL sets the debugging output, possible values:
- ERROR - ERROR
- WARNING - WARNING
...@@ -123,7 +124,7 @@ configure () ...@@ -123,7 +124,7 @@ configure ()
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
...@@ -136,7 +137,6 @@ configure () ...@@ -136,7 +137,6 @@ configure ()
# Set defaults. # Set defaults.
builddir="$sourcedir/build" builddir="$sourcedir/build"
CMakeCacheEntries="" CMakeCacheEntries=""
append_cache_entry CMAKE_BUILD_TYPE STRING RelWithDebInfo
append_cache_entry CMAKE_INSTALL_PREFIX PATH /usr/local append_cache_entry CMAKE_INSTALL_PREFIX PATH /usr/local
append_cache_entry ENABLE_DEBUG BOOL false append_cache_entry ENABLE_DEBUG BOOL false
append_cache_entry DISABLE_CONTEXT_SWITCHING BOOL false append_cache_entry DISABLE_CONTEXT_SWITCHING BOOL false
...@@ -162,6 +162,9 @@ while [ $# -ne 0 ]; do ...@@ -162,6 +162,9 @@ while [ $# -ne 0 ]; do
--enable-debug) --enable-debug)
append_cache_entry ENABLE_DEBUG BOOL true append_cache_entry ENABLE_DEBUG BOOL true
;; ;;
--enable-address-sanitizer)
append_cache_entry ENABLE_ADDRESS_SANITIZER BOOL true
;;
--with-opencl) --with-opencl)
append_cache_entry ENABLE_OPENCL BOOL true append_cache_entry ENABLE_OPENCL BOOL true
;; ;;
......
cppa/abstract_actor.hpp
cppa/abstract_channel.hpp
cppa/abstract_group.hpp
cppa/actor.hpp cppa/actor.hpp
cppa/actor_addressing.hpp cppa/actor_addr.hpp
cppa/actor_companion_mixin.hpp cppa/actor_namespace.hpp
cppa/actor_ostream.hpp
cppa/actor_proxy.hpp cppa/actor_proxy.hpp
cppa/actor_state.hpp
cppa/announce.hpp cppa/announce.hpp
cppa/any_tuple.hpp cppa/any_tuple.hpp
cppa/anything.hpp cppa/anything.hpp
cppa/atom.hpp cppa/atom.hpp
cppa/attachable.hpp cppa/attachable.hpp
cppa/behavior.hpp cppa/behavior.hpp
cppa/behavior_policy.hpp
cppa/behavior_stack_based.hpp
cppa/binary_deserializer.hpp cppa/binary_deserializer.hpp
cppa/binary_serializer.hpp cppa/binary_serializer.hpp
cppa/blocking_actor.hpp
cppa/channel.hpp cppa/channel.hpp
cppa/config.hpp cppa/config.hpp
cppa/context_switching_actor.hpp cppa/continue_helper.hpp
cppa/cow_ptr.hpp cppa/cow_ptr.hpp
cppa/cow_tuple.hpp cppa/cow_tuple.hpp
cppa/cppa.hpp cppa/cppa.hpp
...@@ -30,10 +38,9 @@ cppa/detail/default_uniform_type_info_impl.hpp ...@@ -30,10 +38,9 @@ cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/demangle.hpp cppa/detail/demangle.hpp
cppa/detail/disablable_delete.hpp cppa/detail/disablable_delete.hpp
cppa/detail/empty_tuple.hpp cppa/detail/empty_tuple.hpp
cppa/detail/event_based_actor_factory.hpp
cppa/detail/fd_util.hpp cppa/detail/fd_util.hpp
cppa/detail/fwd.hpp cppa/detail/functor_based_actor.hpp
cppa/detail/get_behavior.hpp cppa/detail/functor_based_blocking_actor.hpp
cppa/detail/group_manager.hpp cppa/detail/group_manager.hpp
cppa/detail/handle.hpp cppa/detail/handle.hpp
cppa/detail/ieee_754.hpp cppa/detail/ieee_754.hpp
...@@ -46,11 +53,11 @@ cppa/detail/opt_impls.hpp ...@@ -46,11 +53,11 @@ cppa/detail/opt_impls.hpp
cppa/detail/optional_variant_data.hpp cppa/detail/optional_variant_data.hpp
cppa/detail/pair_member.hpp cppa/detail/pair_member.hpp
cppa/detail/projection.hpp cppa/detail/projection.hpp
cppa/detail/proper_actor.hpp
cppa/detail/pseudo_tuple.hpp cppa/detail/pseudo_tuple.hpp
cppa/detail/ptype_to_type.hpp cppa/detail/ptype_to_type.hpp
cppa/detail/receive_loop_helper.hpp cppa/detail/raw_access.hpp
cppa/detail/receive_policy.hpp cppa/detail/response_handle_util.hpp
cppa/detail/scheduled_actor_dummy.hpp
cppa/detail/serialize_tuple.hpp cppa/detail/serialize_tuple.hpp
cppa/detail/singleton_manager.hpp cppa/detail/singleton_manager.hpp
cppa/detail/singleton_mixin.hpp cppa/detail/singleton_mixin.hpp
...@@ -75,7 +82,6 @@ cppa/event_based_actor.hpp ...@@ -75,7 +82,6 @@ cppa/event_based_actor.hpp
cppa/exception.hpp cppa/exception.hpp
cppa/exit_reason.hpp cppa/exit_reason.hpp
cppa/extend.hpp cppa/extend.hpp
cppa/factory.hpp
cppa/from_string.hpp cppa/from_string.hpp
cppa/get.hpp cppa/get.hpp
cppa/group.hpp cppa/group.hpp
...@@ -89,12 +95,7 @@ cppa/io/broker.hpp ...@@ -89,12 +95,7 @@ cppa/io/broker.hpp
cppa/io/buffered_writing.hpp cppa/io/buffered_writing.hpp
cppa/io/connection_handle.hpp cppa/io/connection_handle.hpp
cppa/io/continuable.hpp cppa/io/continuable.hpp
cppa/io/default_actor_addressing.hpp
cppa/io/default_actor_proxy.hpp
cppa/io/default_message_queue.hpp cppa/io/default_message_queue.hpp
cppa/io/default_peer.hpp
cppa/io/default_peer_acceptor.hpp
cppa/io/default_protocol.hpp
cppa/io/event.hpp cppa/io/event.hpp
cppa/io/input_stream.hpp cppa/io/input_stream.hpp
cppa/io/ipv4_acceptor.hpp cppa/io/ipv4_acceptor.hpp
...@@ -102,7 +103,9 @@ cppa/io/ipv4_io_stream.hpp ...@@ -102,7 +103,9 @@ cppa/io/ipv4_io_stream.hpp
cppa/io/middleman.hpp cppa/io/middleman.hpp
cppa/io/middleman_event_handler.hpp cppa/io/middleman_event_handler.hpp
cppa/io/output_stream.hpp cppa/io/output_stream.hpp
cppa/io/protocol.hpp cppa/io/peer.hpp
cppa/io/peer_acceptor.hpp
cppa/io/remote_actor_proxy.hpp
cppa/io/stream.hpp cppa/io/stream.hpp
cppa/local_actor.hpp cppa/local_actor.hpp
cppa/logging.hpp cppa/logging.hpp
...@@ -113,10 +116,10 @@ cppa/match_expr.hpp ...@@ -113,10 +116,10 @@ cppa/match_expr.hpp
cppa/match_hint.hpp cppa/match_hint.hpp
cppa/memory_cached.hpp cppa/memory_cached.hpp
cppa/memory_managed.hpp cppa/memory_managed.hpp
cppa/message_future.hpp
cppa/message_header.hpp cppa/message_header.hpp
cppa/message_id.hpp cppa/message_id.hpp
cppa/message_priority.hpp cppa/message_priority.hpp
cppa/node_id.hpp
cppa/none.hpp cppa/none.hpp
cppa/object.hpp cppa/object.hpp
cppa/on.hpp cppa/on.hpp
...@@ -132,29 +135,41 @@ cppa/opt.hpp ...@@ -132,29 +135,41 @@ cppa/opt.hpp
cppa/optional.hpp cppa/optional.hpp
cppa/optional_variant.hpp cppa/optional_variant.hpp
cppa/partial_function.hpp cppa/partial_function.hpp
cppa/policy.hpp
cppa/policy/context_switching_resume.hpp
cppa/policy/cooperative_scheduling.hpp
cppa/policy/event_based_resume.hpp
cppa/policy/invoke_policy.hpp
cppa/policy/middleman_scheduling.hpp
cppa/policy/nestable_invoke.hpp
cppa/policy/no_resume.hpp
cppa/policy/no_scheduling.hpp
cppa/policy/not_prioritizing.hpp
cppa/policy/policies.hpp
cppa/policy/prioritizing.hpp
cppa/policy/priority_policy.hpp
cppa/policy/resume_policy.hpp
cppa/policy/scheduling_policy.hpp
cppa/policy/sequential_invoke.hpp
cppa/primitive_type.hpp cppa/primitive_type.hpp
cppa/primitive_variant.hpp cppa/primitive_variant.hpp
cppa/prioritizing.hpp
cppa/process_information.hpp
cppa/qtsupport/actor_widget_mixin.hpp cppa/qtsupport/actor_widget_mixin.hpp
cppa/receive.hpp
cppa/ref_counted.hpp cppa/ref_counted.hpp
cppa/replies_to.hpp cppa/replies_to.hpp
cppa/response_handle.hpp cppa/response_handle.hpp
cppa/response_promise.hpp
cppa/resumable.hpp
cppa/sb_actor.hpp cppa/sb_actor.hpp
cppa/scheduled_actor.hpp
cppa/scheduler.hpp cppa/scheduler.hpp
cppa/self.hpp cppa/scoped_actor.hpp
cppa/send.hpp
cppa/serializer.hpp cppa/serializer.hpp
cppa/single_timeout.hpp
cppa/singletons.hpp cppa/singletons.hpp
cppa/spawn.hpp cppa/spawn.hpp
cppa/spawn_fwd.hpp
cppa/spawn_options.hpp cppa/spawn_options.hpp
cppa/stacked.hpp cppa/sync_sender.hpp
cppa/stackless.hpp cppa/system_messages.hpp
cppa/thread_mapped_actor.hpp
cppa/threaded.hpp
cppa/threadless.hpp
cppa/timeout_definition.hpp cppa/timeout_definition.hpp
cppa/to_string.hpp cppa/to_string.hpp
cppa/tpartial_function.hpp cppa/tpartial_function.hpp
...@@ -163,6 +178,8 @@ cppa/type_lookup_table.hpp ...@@ -163,6 +178,8 @@ cppa/type_lookup_table.hpp
cppa/typed_actor.hpp cppa/typed_actor.hpp
cppa/typed_actor_ptr.hpp cppa/typed_actor_ptr.hpp
cppa/typed_behavior.hpp cppa/typed_behavior.hpp
cppa/typed_continue_helper.hpp
cppa/typed_event_based_actor.hpp
cppa/uniform_type_info.hpp cppa/uniform_type_info.hpp
cppa/unit.hpp cppa/unit.hpp
cppa/util/abstract_uniform_type_info.hpp cppa/util/abstract_uniform_type_info.hpp
...@@ -177,6 +194,7 @@ cppa/util/duration.hpp ...@@ -177,6 +194,7 @@ cppa/util/duration.hpp
cppa/util/fiber.hpp cppa/util/fiber.hpp
cppa/util/get_mac_addresses.hpp cppa/util/get_mac_addresses.hpp
cppa/util/get_root_uuid.hpp cppa/util/get_root_uuid.hpp
cppa/util/guard.hpp
cppa/util/int_list.hpp cppa/util/int_list.hpp
cppa/util/left_or_right.hpp cppa/util/left_or_right.hpp
cppa/util/limited_vector.hpp cppa/util/limited_vector.hpp
...@@ -207,21 +225,24 @@ examples/opencl/proper_matrix.cpp ...@@ -207,21 +225,24 @@ examples/opencl/proper_matrix.cpp
examples/opencl/simple_matrix.cpp examples/opencl/simple_matrix.cpp
examples/qtsupport/chatwidget.cpp examples/qtsupport/chatwidget.cpp
examples/qtsupport/chatwidget.hpp examples/qtsupport/chatwidget.hpp
examples/qtsupport/chatwindow.ui
examples/qtsupport/qt_group_chat.cpp examples/qtsupport/qt_group_chat.cpp
examples/remote_actors/distributed_calculator.cpp examples/remote_actors/distributed_calculator.cpp
examples/remote_actors/group_chat.cpp examples/remote_actors/group_chat.cpp
examples/remote_actors/group_server.cpp examples/remote_actors/group_server.cpp
examples/remote_actors/protobuf.scala
examples/remote_actors/protobuf_broker.cpp examples/remote_actors/protobuf_broker.cpp
examples/type_system/announce_1.cpp examples/type_system/announce_1.cpp
examples/type_system/announce_2.cpp examples/type_system/announce_2.cpp
examples/type_system/announce_3.cpp examples/type_system/announce_3.cpp
examples/type_system/announce_4.cpp examples/type_system/announce_4.cpp
examples/type_system/announce_5.cpp examples/type_system/announce_5.cpp
src/abstract_actor.cpp
src/abstract_channel.cpp
src/abstract_group.cpp
src/abstract_tuple.cpp src/abstract_tuple.cpp
src/actor.cpp src/actor.cpp
src/actor_addressing.cpp src/actor_addr.cpp
src/actor_namespace.cpp
src/actor_ostream.cpp
src/actor_proxy.cpp src/actor_proxy.cpp
src/actor_registry.cpp src/actor_registry.cpp
src/algorithm.cpp src/algorithm.cpp
...@@ -232,17 +253,14 @@ src/behavior.cpp ...@@ -232,17 +253,14 @@ src/behavior.cpp
src/behavior_stack.cpp src/behavior_stack.cpp
src/binary_deserializer.cpp src/binary_deserializer.cpp
src/binary_serializer.cpp src/binary_serializer.cpp
src/blocking_actor.cpp
src/broker.cpp src/broker.cpp
src/buffer.cpp src/buffer.cpp
src/channel.cpp src/channel.cpp
src/context_switching_actor.cpp src/context_switching_resume.cpp
src/continuable.cpp src/continuable.cpp
src/continue_helper.cpp
src/decorated_tuple.cpp src/decorated_tuple.cpp
src/default_actor_addressing.cpp
src/default_actor_proxy.cpp
src/default_peer.cpp
src/default_peer_acceptor.cpp
src/default_protocol.cpp
src/demangle.cpp src/demangle.cpp
src/deserializer.cpp src/deserializer.cpp
src/duration.cpp src/duration.cpp
...@@ -253,6 +271,8 @@ src/exit_reason.cpp ...@@ -253,6 +271,8 @@ src/exit_reason.cpp
src/factory.cpp src/factory.cpp
src/fd_util.cpp src/fd_util.cpp
src/fiber.cpp src/fiber.cpp
src/functor_based_actor.cpp
src/functor_based_blocking_actor.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
...@@ -270,6 +290,7 @@ src/middleman.cpp ...@@ -270,6 +290,7 @@ src/middleman.cpp
src/middleman_event_handler.cpp src/middleman_event_handler.cpp
src/middleman_event_handler_epoll.cpp src/middleman_event_handler_epoll.cpp
src/middleman_event_handler_poll.cpp src/middleman_event_handler_poll.cpp
src/node_id.cpp
src/object.cpp src/object.cpp
src/object_array.cpp src/object_array.cpp
src/on.cpp src/on.cpp
...@@ -279,22 +300,22 @@ src/opencl/opencl_metainfo.cpp ...@@ -279,22 +300,22 @@ src/opencl/opencl_metainfo.cpp
src/opencl/program.cpp src/opencl/program.cpp
src/opt.cpp src/opt.cpp
src/partial_function.cpp src/partial_function.cpp
src/peer.cpp
src/peer_acceptor.cpp
src/primitive_variant.cpp src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp src/protocol.cpp
src/ref_counted.cpp src/ref_counted.cpp
src/response_handle.cpp src/remote_actor_proxy.cpp
src/response_promise.cpp
src/resumable.cpp
src/ripemd_160.cpp src/ripemd_160.cpp
src/scheduled_actor.cpp
src/scheduled_actor_dummy.cpp
src/scheduler.cpp src/scheduler.cpp
src/self.cpp src/scoped_actor.cpp
src/send.cpp
src/serializer.cpp src/serializer.cpp
src/shared_spinlock.cpp src/shared_spinlock.cpp
src/singleton_manager.cpp src/singleton_manager.cpp
src/string_serialization.cpp src/string_serialization.cpp
src/thread_mapped_actor.cpp src/sync_request_bouncer.cpp
src/thread_pool_scheduler.cpp src/thread_pool_scheduler.cpp
src/to_uniform_name.cpp src/to_uniform_name.cpp
src/type_lookup_table.cpp src/type_lookup_table.cpp
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_ABSTRACT_ACTOR_HPP
#define CPPA_ABSTRACT_ACTOR_HPP
#include <set>
#include <mutex>
#include <atomic>
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
#include <type_traits>
#include "cppa/node_id.hpp"
#include "cppa/cppa_fwd.hpp"
#include "cppa/attachable.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_channel.hpp"
#include "cppa/util/type_traits.hpp"
namespace cppa {
class actor_addr;
class serializer;
class deserializer;
/**
* @brief A unique actor ID.
* @relates abstract_actor
*/
typedef std::uint32_t actor_id;
class actor;
class abstract_actor;
typedef intrusive_ptr<abstract_actor> abstract_actor_ptr;
/**
* @brief Base class for all actor implementations.
*/
class abstract_actor : public abstract_channel {
public:
/**
* @brief Attaches @p ptr to this actor.
*
* The actor will call <tt>ptr->detach(...)</tt> on exit, or immediately
* if it already finished execution.
* @param ptr A callback object that's executed if the actor finishes
* execution.
* @returns @c true if @p ptr was successfully attached to the actor;
* otherwise (actor already exited) @p false.
* @warning The actor takes ownership of @p ptr.
*/
bool attach(attachable_ptr ptr);
/**
* @brief Convenience function that attaches the functor
* or function @p f to this actor.
*
* The actor executes <tt>f()</tt> on exit, or immediatley
* if it already finished execution.
* @param f A functor, function or lambda expression that's executed
* if the actor finishes execution.
* @returns @c true if @p f was successfully attached to the actor;
* otherwise (actor already exited) @p false.
*/
template<typename F>
bool attach_functor(F&& f);
/**
* @brief Returns the address of this actor.
*/
actor_addr address() const;
/**
* @brief Detaches the first attached object that matches @p what.
*/
void detach(const attachable::token& what);
/**
* @brief Links this actor to @p whom.
* @param other Actor instance that whose execution is coupled to the
* execution of this Actor.
*/
virtual void link_to(const actor_addr& whom);
/**
* @copydoc abstract_actor::link_to(const actor_addr&)
*/
template<typename ActorHandle>
void link_to(const ActorHandle& whom) {
link_to(whom.address());
}
/**
* @brief Unlinks this actor from @p whom.
* @param other Linked Actor.
* @note Links are automatically removed if the actor finishes execution.
*/
virtual void unlink_from(const actor_addr& whom);
/**
* @copydoc abstract_actor::unlink_from(const actor_addr&)
*/
template<class ActorHandle>
void unlink_from(const ActorHandle& whom) {
unlink_from(whom.address());
}
/**
* @brief Establishes a link relation between this actor and @p other.
* @param other Actor instance that wants to link against this Actor.
* @returns @c true if this actor is running and added @p other to its
* list of linked actors; otherwise @c false.
*/
virtual bool establish_backlink(const actor_addr& other);
/**
* @brief Removes a link relation between this actor and @p other.
* @param other Actor instance that wants to unlink from this Actor.
* @returns @c true if this actor is running and removed @p other
* from its list of linked actors; otherwise @c false.
*/
virtual bool remove_backlink(const actor_addr& other);
/**
* @brief Gets an integer value that uniquely identifies this Actor in
* the process it's executed in.
* @returns The unique identifier of this actor.
*/
inline actor_id id() const;
/**
* @brief Checks if this actor is running on a remote node.
* @returns @c true if this actor represents a remote actor;
* otherwise @c false.
*/
inline bool is_proxy() const;
/**
* @brief Returns the ID of the node this actor is running on.
*/
inline const node_id& node() const;
/**
* @brief Returns the actor's exit reason of
* <tt>exit_reason::not_exited</tt> if it's still alive.
*/
inline std::uint32_t exit_reason() const;
/**
* @brief Returns the type interface as set of strings.
* @note The returned set is empty for all untyped actors.
*/
virtual std::set<std::string> interface() const;
protected:
abstract_actor();
abstract_actor(actor_id aid);
/**
* @brief Should be overridden by subtypes and called upon termination.
* @note Default implementation sets 'exit_reason' accordingly.
* @note Overridden functions should always call super::cleanup().
*/
virtual void cleanup(std::uint32_t reason);
/**
* @brief The default implementation for {@link link_to()}.
*/
bool link_to_impl(const actor_addr& other);
/**
* @brief The default implementation for {@link unlink_from()}.
*/
bool unlink_from_impl(const actor_addr& other);
/**
* @brief Returns <tt>exit_reason() != exit_reason::not_exited</tt>.
*/
inline bool exited() const;
// cannot be changed after construction
const actor_id m_id;
// you're either a proxy or you're not
const bool m_is_proxy;
private:
// initially exit_reason::not_exited
std::atomic<std::uint32_t> m_exit_reason;
// guards access to m_exit_reason, m_attachables, and m_links
std::mutex m_mtx;
// links to other actors
std::vector<abstract_actor_ptr> m_links;
// attached functors that are executed on cleanup
std::vector<attachable_ptr> m_attachables;
protected:
// identifies the node this actor is running on
node_id_ptr m_node;
};
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
inline std::uint32_t abstract_actor::id() const {
return m_id;
}
inline bool abstract_actor::is_proxy() const {
return m_is_proxy;
}
inline std::uint32_t abstract_actor::exit_reason() const {
return m_exit_reason;
}
inline bool abstract_actor::exited() const {
return exit_reason() != exit_reason::not_exited;
}
inline const node_id& abstract_actor::node() const {
return *m_node;
}
template<class F>
struct functor_attachable : attachable {
F m_functor;
template<typename T>
inline functor_attachable(T&& arg) : m_functor(std::forward<T>(arg)) { }
void actor_exited(std::uint32_t reason) { m_functor(reason); }
bool matches(const attachable::token&) { return false; }
};
template<typename F>
bool abstract_actor::attach_functor(F&& f) {
typedef typename util::rm_const_and_ref<F>::type f_type;
typedef functor_attachable<f_type> impl;
return attach(attachable_ptr{new impl(std::forward<F>(f))});
}
} // namespace cppa
#endif // CPPA_ABSTRACT_ACTOR_HPP
...@@ -28,26 +28,38 @@ ...@@ -28,26 +28,38 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_SCHEDULED_ACTOR_DUMMY_HPP #ifndef CPPA_ABSTRACT_CHANNEL_HPP
#define CPPA_SCHEDULED_ACTOR_DUMMY_HPP #define CPPA_ABSTRACT_CHANNEL_HPP
#include "cppa/scheduled_actor.hpp" #include "cppa/ref_counted.hpp"
namespace cppa { namespace detail { namespace cppa {
struct scheduled_actor_dummy : scheduled_actor { // forward declarations
scheduled_actor_dummy(); class any_tuple;
void enqueue(const message_header&, any_tuple) override; class message_header;
resume_result resume(util::fiber*, actor_ptr&) override;
void quit(std::uint32_t) override; /**
void dequeue(behavior&) override; * @brief Interface for all message receivers.
void dequeue_response(behavior&, message_id) override; *
void do_become(behavior&&, bool) override; * This interface describes an entity that can receive messages
void become_waiting_for(behavior, message_id) override; * and is implemented by {@link actor} and {@link group}.
bool has_behavior() override; */
scheduled_actor_type impl_type() override; class abstract_channel : public ref_counted {
public:
/**
* @brief Enqueues @p msg to the list of received messages.
*/
virtual void enqueue(const message_header& hdr, any_tuple msg) = 0;
protected:
virtual ~abstract_channel();
}; };
} } // namespace cppa::detail } // namespace cppa
#endif // CPPA_SCHEDULED_ACTOR_DUMMY_HPP #endif // CPPA_ABSTRACT_CHANNEL_HPP
...@@ -28,132 +28,153 @@ ...@@ -28,132 +28,153 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_SELF_HPP #ifndef CPPA_ABSTRACT_GROUP_HPP
#define CPPA_SELF_HPP #define CPPA_ABSTRACT_GROUP_HPP
#include "cppa/actor.hpp" #include <string>
#include "cppa/intrusive_ptr.hpp" #include <memory>
#include "cppa/channel.hpp"
#include "cppa/attachable.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/abstract_channel.hpp"
namespace cppa { namespace detail {
class group_manager;
class peer_connection;
} } // namespace cppa::detail
namespace cppa { namespace cppa {
#ifdef CPPA_DOCUMENTATION class group;
class serializer;
class deserializer;
/** /**
* @brief Always points to the current actor. Similar to @c this in * @brief A multicast group.
* an object-oriented context.
*/ */
extern local_actor* self; class abstract_group : public abstract_channel {
#else // CPPA_DOCUMENTATION friend class detail::group_manager;
friend class detail::peer_connection; // needs access to remote_enqueue
class local_actor; public:
// convertible<...> enables "actor_ptr this_actor = self;" class subscription;
class self_type : public convertible<self_type, actor*>,
public convertible<self_type, channel*> {
self_type(const self_type&) = delete; // needs access to unsubscribe()
self_type& operator=(const self_type&) = delete; friend class subscription;
public: // unsubscribes its channel from the group on destruction
class subscription {
typedef local_actor* pointer; friend class abstract_group;
constexpr self_type() { } subscription(const subscription&) = delete;
subscription& operator=(const subscription&) = delete;
// "inherited" from convertible<...> public:
inline actor* do_convert() const {
return convert_impl();
}
inline pointer get() const { subscription() = default;
return get_impl(); subscription(subscription&&) = default;
} subscription(const channel& s, const intrusive_ptr<abstract_group>& g);
// allow "self" wherever an local_actor or actor pointer is expected ~subscription();
inline operator pointer() const {
return get_impl();
}
inline pointer operator->() const { inline bool valid() const { return (m_subscriber) && (m_group); }
return get_impl();
}
// @pre get_unchecked() == nullptr private:
inline void set(pointer ptr) const {
set_impl(ptr);
}
// @returns The current value without converting the calling context channel m_subscriber;
// to an actor on-the-fly. intrusive_ptr<abstract_group> m_group;
inline pointer unchecked() const {
return get_unchecked_impl();
}
inline pointer release() const { };
return release_impl();
}
inline void adopt(pointer ptr) const { /**
adopt_impl(ptr); * @brief Module interface.
} */
class module {
static void cleanup_fun(pointer); std::string m_name;
private: protected:
static void set_impl(pointer); module(std::string module_name);
static pointer get_unchecked_impl(); public:
static pointer get_impl(); /**
* @brief Get the name of this module implementation.
* @returns The name of this module implementation.
* @threadsafe
*/
const std::string& name();
static actor* convert_impl(); /**
* @brief Get a pointer to the group associated with
* the name @p group_name.
* @threadsafe
*/
virtual group get(const std::string& group_name) = 0;
static pointer release_impl(); virtual group deserialize(deserializer* source) = 0;
static void adopt_impl(pointer); };
}; typedef module* module_ptr;
typedef std::unique_ptr<module> unique_module_ptr;
/* virtual void serialize(serializer* sink) = 0;
* "self" emulates a new keyword. The object itself is useless, all it does
* is to provide syntactic sugar like "self->trap_exit(true)".
*/
constexpr self_type self;
class scoped_self_setter { /**
* @brief A string representation of the group identifier.
* @returns The group identifier as string (e.g. "224.0.0.1" for IPv4
* multicast or a user-defined string for local groups).
*/
const std::string& identifier() const;
scoped_self_setter(const scoped_self_setter&) = delete; module_ptr get_module() const;
scoped_self_setter& operator=(const scoped_self_setter&) = delete;
public: /**
* @brief The name of the module.
* @returns The module name of this group (e.g. "local").
*/
const std::string& module_name() const;
inline scoped_self_setter(local_actor* new_value) { /**
m_original_value = self.release(); * @brief Subscribe @p who to this group.
self.adopt(new_value); * @returns A {@link subscription} object that unsubscribes @p who
} * if the lifetime of @p who ends.
*/
virtual subscription subscribe(const channel& who) = 0;
inline ~scoped_self_setter() { protected:
// restore self
static_cast<void>(self.release());
self.adopt(m_original_value);
}
private: abstract_group(module_ptr module, std::string group_id);
local_actor* m_original_value; virtual void unsubscribe(const channel& who) = 0;
module_ptr m_module;
std::string m_identifier;
}; };
// disambiguation (compiler gets confused with cast operator otherwise) /**
bool operator==(const actor_ptr& lhs, const self_type& rhs); * @brief A smart pointer type that manages instances of {@link group}.
bool operator==(const self_type& lhs, const actor_ptr& rhs); * @relates group
bool operator!=(const actor_ptr& lhs, const self_type& rhs); */
bool operator!=(const self_type& lhs, const actor_ptr& rhs); typedef intrusive_ptr<abstract_group> abstract_group_ptr;
#endif // CPPA_DOCUMENTATION /**
* @brief Makes *all* local groups accessible via network on address @p addr
* and @p port.
* @throws bind_failure
* @throws network_error
*/
void publish_local_groups(std::uint16_t port, const char* addr = nullptr);
} // namespace cppa } // namespace cppa
#endif // CPPA_SELF_HPP #endif // CPPA_ABSTRACT_GROUP_HPP
...@@ -31,227 +31,165 @@ ...@@ -31,227 +31,165 @@
#ifndef CPPA_ACTOR_HPP #ifndef CPPA_ACTOR_HPP
#define CPPA_ACTOR_HPP #define CPPA_ACTOR_HPP
#include <mutex> #include <cstddef>
#include <atomic>
#include <memory>
#include <vector>
#include <cstdint> #include <cstdint>
#include <utility>
#include <type_traits> #include <type_traits>
#include "cppa/group.hpp"
#include "cppa/channel.hpp"
#include "cppa/cppa_fwd.hpp"
#include "cppa/attachable.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/util/comparable.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
namespace cppa { namespace cppa {
class actor; class actor_addr;
class self_type; class actor_proxy;
class serializer; class local_actor;
class deserializer; class blocking_actor;
class event_based_actor;
/** struct invalid_actor_addr_t;
* @brief A unique actor ID.
* @relates actor namespace io {
*/ class broker;
typedef std::uint32_t actor_id; } // namespace io
namespace opencl {
template <typename Signature>
class actor_facade;
} // namespace opencl
namespace detail {
class raw_access;
} // namespace detail
struct invalid_actor_t { constexpr invalid_actor_t() { } };
/** /**
* @brief A smart pointer type that manages instances of {@link actor}. * @brief Identifies an invalid {@link actor}.
* @relates actor * @relates actor
*/ */
typedef intrusive_ptr<actor> actor_ptr; constexpr invalid_actor_t invalid_actor = invalid_actor_t{};
template<typename T>
struct is_convertible_to_actor {
static constexpr bool value = std::is_base_of<io::broker, T>::value
|| std::is_base_of<actor_proxy, T>::value
|| std::is_base_of<blocking_actor, T>::value
|| std::is_base_of<event_based_actor, T>::value;
};
template<typename T>
struct is_convertible_to_actor<opencl::actor_facade<T>> {
static constexpr bool value = true;
};
/** /**
* @brief Base class for all actor implementations. * @brief Identifies an untyped actor.
*
* Can be used with derived types of {@link event_based_actor},
* {@link blocking_actor}, {@link actor_proxy}, or
* {@link io::broker}.
*/ */
class actor : public channel { class actor : util::comparable<actor>
, util::comparable<actor, actor_addr>
, util::comparable<actor, invalid_actor_t>
, util::comparable<actor, invalid_actor_addr_t> {
friend class local_actor;
friend class detail::raw_access;
public: public:
/** actor() = default;
* @brief Attaches @p ptr to this actor.
*
* The actor will call <tt>ptr->detach(...)</tt> on exit, or immediately
* if it already finished execution.
* @param ptr A callback object that's executed if the actor finishes
* execution.
* @returns @c true if @p ptr was successfully attached to the actor;
* otherwise (actor already exited) @p false.
* @warning The actor takes ownership of @p ptr.
*/
bool attach(attachable_ptr ptr);
/** actor(actor&&) = default;
* @brief Convenience function that attaches the functor
* or function @p f to this actor.
*
* The actor executes <tt>f()</tt> on exit, or immediatley
* if it already finished execution.
* @param f A functor, function or lambda expression that's executed
* if the actor finishes execution.
* @returns @c true if @p f was successfully attached to the actor;
* otherwise (actor already exited) @p false.
*/
template<typename F>
bool attach_functor(F&& f);
/** actor(const actor&) = default;
* @brief Detaches the first attached object that matches @p what.
*/
void detach(const attachable::token& what);
/** template<typename T>
* @brief Links this actor to @p other. actor(intrusive_ptr<T> ptr,
* @param other Actor instance that whose execution is coupled to the typename std::enable_if<is_convertible_to_actor<T>::value>::type* = 0)
* execution of this Actor. : m_ptr(std::move(ptr)) { }
*/
virtual void link_to(const actor_ptr& other);
/** template<typename T>
* @brief Unlinks this actor from @p other. actor(T* ptr,
* @param other Linked Actor. typename std::enable_if<is_convertible_to_actor<T>::value>::type* = 0)
* @note Links are automatically removed if the actor finishes execution. : m_ptr(ptr) { }
*/
virtual void unlink_from(const actor_ptr& other);
/** actor(const invalid_actor_t&);
* @brief Establishes a link relation between this actor and @p other.
* @param other Actor instance that wants to link against this Actor.
* @returns @c true if this actor is running and added @p other to its
* list of linked actors; otherwise @c false.
*/
virtual bool establish_backlink(const actor_ptr& other);
/** actor& operator=(actor&&) = default;
* @brief Removes a link relation between this actor and @p other.
* @param other Actor instance that wants to unlink from this Actor.
* @returns @c true if this actor is running and removed @p other
* from its list of linked actors; otherwise @c false.
*/
virtual bool remove_backlink(const actor_ptr& other);
/** actor& operator=(const actor&) = default;
* @brief Gets an integer value that uniquely identifies this Actor in
* the process it's executed in.
* @returns The unique identifier of this actor.
*/
inline actor_id id() const;
/** template<typename T>
* @brief Checks if this actor is running on a remote node. typename std::enable_if<is_convertible_to_actor<T>::value, actor&>::type
* @returns @c true if this actor represents a remote actor; operator=(intrusive_ptr<T> ptr) {
* otherwise @c false. actor tmp{std::move(ptr)};
*/ swap(tmp);
inline bool is_proxy() const; return *this;
}
template<typename T>
typename std::enable_if<is_convertible_to_actor<T>::value, actor&>::type
operator=(T* ptr) {
actor tmp{ptr};
swap(tmp);
return *this;
}
protected: actor& operator=(const invalid_actor_t&);
actor(); inline operator bool() const {
return static_cast<bool>(m_ptr);
}
actor(actor_id aid); inline bool operator!() const {
return !m_ptr;
}
/** /**
* @brief Should be overridden by subtypes and called upon termination. * @brief Returns a handle that grants access to
* @note Default implementation sets 'exit_reason' accordingly. * actor operations such as enqueue.
* @note Overridden functions should always call super::cleanup().
*/ */
virtual void cleanup(std::uint32_t reason); inline abstract_actor* operator->() const {
return m_ptr.get();
}
/** inline abstract_actor& operator*() const {
* @brief The default implementation for {@link link_to()}. return *m_ptr;
*/ }
bool link_to_impl(const actor_ptr& other);
/** intptr_t compare(const actor& other) const;
* @brief The default implementation for {@link unlink_from()}.
*/
bool unlink_from_impl(const actor_ptr& other);
/** intptr_t compare(const actor_addr&) const;
* @brief Returns the actor's exit reason of
* <tt>exit_reason::not_exited</tt> if it's still alive.
*/
inline std::uint32_t exit_reason() const;
/** inline intptr_t compare(const invalid_actor_t&) const {
* @brief Returns <tt>exit_reason() != exit_reason::not_exited</tt>. return m_ptr ? 1 : 0;
*/ }
inline bool exited() const;
// cannot be changed after construction inline intptr_t compare(const invalid_actor_addr_t&) const {
const actor_id m_id; return compare(invalid_actor);
}
// you're either a proxy or you're not /**
const bool m_is_proxy; * @brief Queries the address of the stored actor.
*/
actor_addr address() const;
private: private:
// initially exit_reason::not_exited void swap(actor& other);
std::atomic<std::uint32_t> m_exit_reason;
// guards access to m_exit_reason, m_attachables, and m_links
std::mutex m_mtx;
// links to other actors actor(abstract_actor*);
std::vector<actor_ptr> m_links;
// attached functors that are executed on cleanup abstract_actor_ptr m_ptr;
std::vector<attachable_ptr> m_attachables;
}; };
// undocumented, because self_type is hidden in documentation
bool operator==(const actor_ptr&, const self_type&);
bool operator!=(const self_type&, const actor_ptr&);
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
inline std::uint32_t actor::id() const {
return m_id;
}
inline bool actor::is_proxy() const {
return m_is_proxy;
}
inline std::uint32_t actor::exit_reason() const {
return m_exit_reason;
}
inline bool actor::exited() const {
return exit_reason() != exit_reason::not_exited;
}
template<class F>
struct functor_attachable : attachable {
F m_functor;
template<typename T>
inline functor_attachable(T&& arg) : m_functor(std::forward<T>(arg)) { }
void actor_exited(std::uint32_t reason) { m_functor(reason); }
bool matches(const attachable::token&) { return false; }
};
template<typename F>
bool actor::attach_functor(F&& f) {
typedef typename util::rm_const_and_ref<F>::type f_type;
typedef functor_attachable<f_type> impl;
return attach(attachable_ptr{new impl(std::forward<F>(f))});
}
} // namespace cppa } // namespace cppa
#endif // CPPA_ACTOR_HPP #endif // CPPA_ACTOR_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_ACTOR_ADDR_HPP
#define CPPA_ACTOR_ADDR_HPP
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/util/comparable.hpp"
namespace cppa {
class actor;
class local_actor;
class actor_namespace;
namespace detail { class raw_access; }
/**
* @brief Identifies an invalid {@link actor_addr}.
* @relates actor_addr
*/
struct invalid_actor_addr_t { constexpr invalid_actor_addr_t() { } };
constexpr invalid_actor_addr_t invalid_actor_addr = invalid_actor_addr_t{};
/**
* @brief Stores the address of typed as well as untyped actors.
*/
class actor_addr : util::comparable<actor_addr>
, util::comparable<actor_addr, abstract_actor*>
, util::comparable<actor_addr, abstract_actor_ptr> {
friend class actor;
friend class abstract_actor;
friend class detail::raw_access;
public:
actor_addr() = default;
actor_addr(actor_addr&&) = default;
actor_addr(const actor_addr&) = default;
actor_addr& operator=(actor_addr&&) = default;
actor_addr& operator=(const actor_addr&) = default;
actor_addr(const invalid_actor_addr_t&);
actor_addr operator=(const invalid_actor_addr_t&);
inline explicit operator bool() const {
return static_cast<bool>(m_ptr);
}
inline bool operator!() const {
return !m_ptr;
}
intptr_t compare(const actor_addr& other) const;
intptr_t compare(const abstract_actor* other) const;
inline intptr_t compare(const abstract_actor_ptr& other) const {
return compare(other.get());
}
actor_id id() const;
const node_id& node() const;
/**
* @brief Returns whether this is an address of a
* remote actor.
*/
bool is_remote() const;
private:
explicit actor_addr(abstract_actor*);
abstract_actor_ptr m_ptr;
};
} // namespace cppa
#endif // CPPA_ACTOR_ADDR_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_ACTOR_COMPANION_MIXIN_HPP
#define CPPA_ACTOR_COMPANION_MIXIN_HPP
#include <mutex> // std::lock_guard
#include <memory> // std::unique_ptr
#include "cppa/self.hpp"
#include "cppa/actor.hpp"
#include "cppa/extend.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/shared_spinlock.hpp"
#include "cppa/util/shared_lock_guard.hpp"
#include "cppa/detail/memory.hpp"
namespace cppa {
/**
* @brief Adds co-existing objects (companions) to a class,
* which serve as gateways, thereby enabling libcppa's message passing.
*/
template<typename Base>
class actor_companion_mixin : public Base {
typedef Base super;
public:
typedef std::unique_ptr<mailbox_element, detail::disposer> message_pointer;
template<typename... Ts>
actor_companion_mixin(Ts&&... args) : super(std::forward<Ts>(args)...) {
m_self.reset(detail::memory::create<companion>(this));
}
~actor_companion_mixin() {
m_self->disconnect();
}
/**
* @brief Returns a smart pointer to the companion object.
*/
inline actor_ptr as_actor() const { return m_self; }
protected:
/**
* @brief This callback is invoked by the companion object whenever a
* new messages arrives.
* @warning Implementation has to be thread-safe.
*/
virtual void new_message(message_pointer ptr) = 0;
/**
* @brief Defines the message handler.
* @note While the message handler is invoked, @p self will point
* to the companion object to enable function calls to send().
*/
template<typename... Ts>
void set_message_handler(Ts&&... args) {
m_message_handler = match_expr_convert(std::forward<Ts>(args)...);
}
/**
* @brief Invokes the message handler with @p msg.
* @note While the message handler is invoked, @p self will point
* to the companion object to enable function calls to send().
*/
void handle_message(const message_pointer& msg) {
if (!msg) return;
scoped_self_setter sss(m_self.get());
m_self->m_current_node = msg.get();
auto f = m_message_handler; // make sure ref count >= 2
f(msg->msg);
}
private:
class companion : public local_actor {
friend class actor_companion_mixin;
typedef util::shared_spinlock lock_type;
public:
companion(actor_companion_mixin* parent) : m_parent(parent) { }
void disconnect() {
{ // lifetime scope of guard
std::lock_guard<lock_type> guard(m_lock);
m_parent = nullptr;
}
cleanup(exit_reason::normal);
}
void enqueue(const message_header& hdr, any_tuple msg) override {
using std::move;
util::shared_lock_guard<lock_type> guard(m_lock);
if (!m_parent) return;
message_pointer ptr;
ptr.reset(detail::memory::create<mailbox_element>(hdr, move(msg)));
m_parent->new_message(move(ptr));
}
bool initialized() const override { return true; }
void quit(std::uint32_t) override {
throw std::runtime_error("Using actor_companion_mixin::quit "
"is prohibited; use Qt's widget "
"management instead.");
}
void dequeue(behavior&) override {
throw_no_recv();
}
void dequeue_response(behavior&, message_id) override {
throw_no_recv();
}
void become_waiting_for(behavior, message_id) override {
throw_no_become();
}
protected:
void do_become(behavior&&, bool) override { throw_no_become(); }
private:
void throw_no_become() {
throw std::runtime_error("actor_companion_companion "
"does not support libcppa's "
"become() API");
}
void throw_no_recv() {
throw std::runtime_error("actor_companion_companion "
"does not support libcppa's "
"receive() API");
}
// guards access to m_parent
lock_type m_lock;
// set to nullptr if this companion became detached
actor_companion_mixin* m_parent;
};
// used as 'self' before calling message handler
intrusive_ptr<companion> m_self;
// user-defined message handler for incoming messages
partial_function m_message_handler;
};
} // namespace cppa
#endif // CPPA_ACTOR_COMPANION_MIXIN_HPP
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* * * *
* You should have received a copy of the GNU Lesser General Public License * * You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. * * along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_ACTOR_NAMESPACE_HPP #ifndef CPPA_ACTOR_NAMESPACE_HPP
...@@ -52,7 +52,7 @@ namespace io { class middleman; } ...@@ -52,7 +52,7 @@ namespace io { class middleman; }
class actor_namespace { class actor_namespace {
public: public:
typedef std::function<actor_proxy_ptr(actor_id, node_id_ptr)> typedef std::function<actor_proxy_ptr(actor_id, node_id_ptr)>
factory_fun; factory_fun;
...@@ -60,77 +60,77 @@ class actor_namespace { ...@@ -60,77 +60,77 @@ class actor_namespace {
new_element_callback; new_element_callback;
inline void set_proxy_factory(factory_fun fun); inline void set_proxy_factory(factory_fun fun);
inline void set_new_element_callback(new_element_callback fun); inline void set_new_element_callback(new_element_callback fun);
void write(serializer* sink, const actor_ptr& ptr); void write(serializer* sink, const actor_addr& ptr);
actor_ptr read(deserializer* source); actor_addr read(deserializer* source);
/** /**
* @brief A map that stores weak actor proxy pointers by actor ids. * @brief A map that stores weak actor proxy pointers by actor ids.
*/ */
typedef std::map<actor_id, weak_actor_proxy_ptr> proxy_map; typedef std::map<actor_id, weak_actor_proxy_ptr> proxy_map;
/** /**
* @brief Returns the number of proxies for @p node. * @brief Returns the number of proxies for @p node.
*/ */
size_t count_proxies(const node_id& node); size_t count_proxies(const node_id& node);
/** /**
* @brief Returns the proxy instance identified by @p node and @p aid * @brief Returns the proxy instance identified by @p node and @p aid
* or @p nullptr if the actor is unknown. * or @p nullptr if the actor is unknown.
*/ */
actor_ptr get(const node_id& node, actor_id aid); actor_proxy_ptr get(const node_id& node, actor_id aid);
/** /**
* @brief Returns the proxy instance identified by @p node and @p aid * @brief Returns the proxy instance identified by @p node and @p aid
* or creates a new (default) proxy instance. * or creates a new (default) proxy instance.
*/ */
actor_ptr get_or_put(node_id_ptr node, actor_id aid); actor_proxy_ptr get_or_put(node_id_ptr node, actor_id aid);
/** /**
* @brief Stores @p proxy in the list of known actor proxies. * @brief Stores @p proxy in the list of known actor proxies.
*/ */
void put(const node_id& parent, void put(const node_id& parent,
actor_id aid, actor_id aid,
const actor_proxy_ptr& proxy); const actor_proxy_ptr& proxy);
/** /**
* @brief Returns the map of known actors for @p node. * @brief Returns the map of known actors for @p node.
*/ */
proxy_map& proxies(node_id& node); proxy_map& proxies(node_id& node);
/** /**
* @brief Deletes all proxies for @p node. * @brief Deletes all proxies for @p node.
*/ */
void erase(node_id& node); void erase(node_id& node);
/** /**
* @brief Deletes the proxy with id @p aid for @p node. * @brief Deletes the proxy with id @p aid for @p node.
*/ */
void erase(node_id& node, actor_id aid); void erase(node_id& node, actor_id aid);
private: private:
factory_fun m_factory; factory_fun m_factory;
new_element_callback m_new_element_callback; new_element_callback m_new_element_callback;
node_id_ptr m_node; node_id_ptr m_node;
std::map<node_id, proxy_map> m_proxies; std::map<node_id, proxy_map> m_proxies;
}; };
inline void actor_namespace::set_proxy_factory(factory_fun fun) { inline void actor_namespace::set_proxy_factory(factory_fun fun) {
m_factory = std::move(fun); m_factory = std::move(fun);
} }
inline void actor_namespace::set_new_element_callback(new_element_callback fun) { inline void actor_namespace::set_new_element_callback(new_element_callback fun) {
m_new_element_callback = std::move(fun); m_new_element_callback = std::move(fun);
} }
} // namespace cppa } // namespace cppa
#endif #endif
...@@ -28,68 +28,82 @@ ...@@ -28,68 +28,82 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_TYPED_ACTOR_PTR_HPP #ifndef CPPA_ACTOR_OSTREAM_HPP
#define CPPA_TYPED_ACTOR_PTR_HPP #define CPPA_ACTOR_OSTREAM_HPP
#include "cppa/replies_to.hpp" #include "cppa/actor.hpp"
#include "cppa/match_expr.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/spawn_options.hpp" #include "cppa/to_string.hpp"
#include "cppa/detail/typed_actor_util.hpp"
namespace cppa { namespace cppa {
template<typename... Signatures> class local_actor;
class typed_actor_ptr { class scoped_actor;
class actor_ostream {
public: public:
typedef util::type_list<Signatures...> signatures; typedef actor_ostream& (*fun_type)(actor_ostream&);
typed_actor_ptr() = default; actor_ostream(actor_ostream&&) = default;
typed_actor_ptr(typed_actor_ptr&&) = default; actor_ostream(const actor_ostream&) = default;
typed_actor_ptr(const typed_actor_ptr&) = default;
typed_actor_ptr& operator=(typed_actor_ptr&&) = default;
typed_actor_ptr& operator=(const typed_actor_ptr&) = default;
template<typename... Others> actor_ostream& operator=(actor_ostream&&) = default;
typed_actor_ptr(typed_actor_ptr<Others...> other) { actor_ostream& operator=(const actor_ostream&) = default;
set(std::move(other));
}
template<typename... Others> explicit actor_ostream(local_actor* self);
typed_actor_ptr& operator=(typed_actor_ptr<Others...> other) {
set(std::move(other)); actor_ostream& write(std::string arg);
return *this;
}
/** @cond PRIVATE */ actor_ostream& flush();
static typed_actor_ptr cast_from(actor_ptr from) {
return {std::move(from)}; inline actor_ostream& operator<<(std::string arg) {
return write(move(arg));
} }
const actor_ptr& type_erased() const { return m_ptr; }
actor_ptr& type_erased() { return m_ptr; }
/** @endcond */
private: inline actor_ostream& operator<<(const any_tuple& arg) {
return write(cppa::to_string(arg));
}
typed_actor_ptr(actor_ptr ptr) : m_ptr(std::move(ptr)) { } // disambiguate between conversion to string and to any_tuple
inline actor_ostream& operator<<(const char* arg) {
return *this << std::string{arg};
}
template<class ListA, class ListB> template<typename T>
inline void check_signatures() { inline typename std::enable_if<
static_assert(util::tl_is_strict_subset<ListA, ListB>::value, !std::is_convertible<T, std::string>::value
"'this' must be a strict subset of 'other'"); && !std::is_convertible<T, any_tuple>::value,
actor_ostream&
>::type
operator<<(T&& arg) {
return write(std::to_string(std::forward<T>(arg)));
} }
template<typename... Others> inline actor_ostream& operator<<(actor_ostream::fun_type f) {
inline void set(typed_actor_ptr<Others...> other) { return f(*this);
check_signatures<signatures, util::type_list<Others...>>();
m_ptr = std::move(other.type_erased());
} }
actor_ptr m_ptr; private:
local_actor* m_self;
actor m_printer;
}; };
inline actor_ostream aout(local_actor* self) {
return actor_ostream{self};
}
actor_ostream aout(scoped_actor& self);
} // namespace cppa } // namespace cppa
#endif // CPPA_TYPED_ACTOR_PTR_HPP namespace std {
// provide convenience overlaods for aout; implemented in logging.cpp
cppa::actor_ostream& endl(cppa::actor_ostream& o);
cppa::actor_ostream& flush(cppa::actor_ostream& o);
} // namespace std
#endif // CPPA_ACTOR_OSTREAM_HPP
...@@ -31,8 +31,9 @@ ...@@ -31,8 +31,9 @@
#ifndef CPPA_ACTOR_PROXY_HPP #ifndef CPPA_ACTOR_PROXY_HPP
#define CPPA_ACTOR_PROXY_HPP #define CPPA_ACTOR_PROXY_HPP
#include "cppa/actor.hpp"
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/message_header.hpp" #include "cppa/message_header.hpp"
#include "cppa/enable_weak_ptr.hpp" #include "cppa/enable_weak_ptr.hpp"
#include "cppa/weak_intrusive_ptr.hpp" #include "cppa/weak_intrusive_ptr.hpp"
...@@ -43,9 +44,9 @@ class actor_proxy_cache; ...@@ -43,9 +44,9 @@ class actor_proxy_cache;
/** /**
* @brief Represents a remote actor. * @brief Represents a remote actor.
* @extends actor * @extends abstract_actor
*/ */
class actor_proxy : public extend<actor>::with<enable_weak_ptr> { class actor_proxy : public extend<abstract_actor>::with<enable_weak_ptr> {
typedef combined_type super; typedef combined_type super;
...@@ -55,12 +56,12 @@ class actor_proxy : public extend<actor>::with<enable_weak_ptr> { ...@@ -55,12 +56,12 @@ class actor_proxy : public extend<actor>::with<enable_weak_ptr> {
* @brief Establishes a local link state that's not synchronized back * @brief Establishes a local link state that's not synchronized back
* to the remote instance. * to the remote instance.
*/ */
virtual void local_link_to(const intrusive_ptr<actor>& other) = 0; virtual void local_link_to(const actor_addr& other) = 0;
/** /**
* @brief Removes a local link state. * @brief Removes a local link state.
*/ */
virtual void local_unlink_from(const actor_ptr& other) = 0; virtual void local_unlink_from(const actor_addr& other) = 0;
/** /**
* @brief Delivers given message via this proxy instance. * @brief Delivers given message via this proxy instance.
......
...@@ -156,16 +156,29 @@ compound_member(const std::pair<GRes (Parent::*)() const, ...@@ -156,16 +156,29 @@ compound_member(const std::pair<GRes (Parent::*)() const,
return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)}; return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)};
} }
/** /**
* @brief Adds a new type mapping for @p T to the libcppa type system. * @brief Adds a new type mapping for @p C to the libcppa type system.
* @param args Members of @p T. * @tparam C A class that is default constructible, copy constructible,
* and comparable.
* @param arg First members of @p C.
* @param args Additional members of @p C.
* @warning @p announce is <b>not</b> thead safe! * @warning @p announce is <b>not</b> thead safe!
*/ */
template<typename T, typename... Ts> template<class C, typename... Ts>
inline const uniform_type_info* announce(const Ts&... args) { inline const uniform_type_info* announce(const Ts&... args) {
auto ptr = new detail::default_uniform_type_info_impl<T>(args...); auto ptr = new detail::default_uniform_type_info_impl<C>(args...);
return announce(typeid(T), std::unique_ptr<uniform_type_info>{ptr}); return announce(typeid(C), std::unique_ptr<uniform_type_info>{ptr});
}
/**
* @brief Adds a new type mapping for an empty or "tag" class.
* @tparam C A class without any member.
* @warning @p announce_tag is <b>not</b> thead safe!
*/
template<class C>
inline const uniform_type_info* announce_tag() {
auto ptr = new detail::empty_uniform_type_info_impl<C>();
return announce(typeid(C), std::unique_ptr<uniform_type_info>{ptr});
} }
/** /**
......
...@@ -91,7 +91,7 @@ class any_tuple { ...@@ -91,7 +91,7 @@ class any_tuple {
* @brief Creates a tuple from a set of values. * @brief Creates a tuple from a set of values.
*/ */
template<typename T, typename... Ts> template<typename T, typename... Ts>
any_tuple(T v0, Ts&&... vs) explicit any_tuple(T v0, Ts&&... vs)
: m_vals(make_cow_tuple(std::move(v0), std::forward<Ts>(vs)...).vals()) { } : m_vals(make_cow_tuple(std::move(v0), std::forward<Ts>(vs)...).vals()) { }
/** /**
......
...@@ -112,6 +112,10 @@ class behavior { ...@@ -112,6 +112,10 @@ class behavior {
*/ */
behavior add_continuation(continuation_fun fun); behavior add_continuation(continuation_fun fun);
inline operator bool() const {
return static_cast<bool>(m_impl);
}
private: private:
impl_ptr m_impl; impl_ptr m_impl;
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_BEHAVIOR_POLICY_HPP
#define CPPA_BEHAVIOR_POLICY_HPP
namespace cppa {
template<bool DiscardBehavior>
struct behavior_policy { static constexpr bool discard_old = DiscardBehavior; };
template<typename T>
struct is_behavior_policy : std::false_type { };
template<bool DiscardBehavior>
struct is_behavior_policy<behavior_policy<DiscardBehavior>> : std::true_type { };
typedef behavior_policy<false> keep_behavior_t;
typedef behavior_policy<true > discard_behavior_t;
/**
* @brief Policy tag that causes {@link event_based_actor::become} to
* discard the current behavior.
* @relates local_actor
*/
constexpr discard_behavior_t discard_behavior = discard_behavior_t{};
/**
* @brief Policy tag that causes {@link event_based_actor::become} to
* keep the current behavior available.
* @relates local_actor
*/
constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
} // namespace cppa
#endif // CPPA_BEHAVIOR_POLICY_HPP
...@@ -28,146 +28,161 @@ ...@@ -28,146 +28,161 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_STACKED_ACTOR_MIXIN_HPP #ifndef CPPA_BEHAVIOR_STACK_BASED_HPP
#define CPPA_STACKED_ACTOR_MIXIN_HPP #define CPPA_BEHAVIOR_STACK_BASED_HPP
#include <chrono> #include "cppa/message_id.hpp"
#include <memory> #include "cppa/single_timeout.hpp"
#include <functional> #include "cppa/typed_behavior.hpp"
#include "cppa/behavior_policy.hpp"
#include "cppa/behavior.hpp" #include "cppa/response_handle.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/util/dptr.hpp"
#include "cppa/detail/behavior_stack.hpp" #include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/receive_policy.hpp"
namespace cppa { namespace cppa {
/** template<class Base, class Subtype, class BehaviorType>
* @brief An actor that uses the blocking API of @p libcppa and thus needs class behavior_stack_based_impl : public single_timeout<Base, Subtype> {
* its own stack.
*/ typedef single_timeout<Base, Subtype> super;
template<class Base, class Subtype>
class stacked : public Base {
friend class detail::receive_policy; public:
friend class detail::behavior_stack;
protected: /**************************************************************************
* typedefs and constructor *
**************************************************************************/
typedef stacked combined_type; typedef BehaviorType behavior_type;
public: typedef behavior_stack_based_impl combined_type;
typedef response_handle<behavior_stack_based_impl,
any_tuple,
nonblocking_response_handle_tag>
response_handle_type;
static constexpr auto receive_flag = detail::rp_nestable; template <typename... Ts>
behavior_stack_based_impl(Ts&&... vs) : super(std::forward<Ts>(vs)...) { }
void dequeue(behavior& bhvr) override { /**************************************************************************
++m_nested_count; * become() member function family *
m_recv_policy.receive(util::dptr<Subtype>(this), bhvr); **************************************************************************/
--m_nested_count;
check_quit(); void become(behavior_type bhvr) {
do_become(std::move(bhvr), true);
} }
void dequeue_response(behavior& bhvr, message_id request_id) override { template<bool Discard>
++m_nested_count; void become(behavior_policy<Discard>, behavior_type bhvr) {
m_recv_policy.receive(util::dptr<Subtype>(this), bhvr, request_id); do_become(std::move(bhvr), Discard);
--m_nested_count;
check_quit();
} }
virtual void run() { template<typename T, typename... Ts>
exec_behavior_stack(); inline typename std::enable_if<
if (m_behavior) m_behavior(); !is_behavior_policy<typename util::rm_const_and_ref<T>::type>::value,
auto dthis = util::dptr<Subtype>(this); void
auto rsn = dthis->planned_exit_reason(); >::type
dthis->cleanup(rsn == exit_reason::not_exited ? exit_reason::normal : rsn); become(T&& arg, Ts&&... args) {
do_become(behavior_type{std::forward<T>(arg),
std::forward<Ts>(args)...},
true);
} }
inline void set_behavior(std::function<void()> fun) { template<bool Discard, typename... Ts>
m_behavior = std::move(fun); void become(behavior_policy<Discard>, Ts&&... args) {
do_become(behavior_type{std::forward<Ts>(args)...}, Discard);
} }
void exec_behavior_stack() override { inline void unbecome() {
m_in_bhvr_loop = true; m_bhvr_stack.pop_async_back();
auto dthis = util::dptr<Subtype>(this);
if (!stack_empty() && !m_nested_count) {
while (!stack_empty()) {
++m_nested_count;
dthis->m_bhvr_stack.exec(m_recv_policy, dthis);
--m_nested_count;
check_quit();
}
}
m_in_bhvr_loop = false;
} }
protected: /**************************************************************************
* convenience member function for stack manipulation *
**************************************************************************/
template<typename... Ts> inline bool has_behavior() const {
stacked(Ts&&... args) : Base(std::forward<Ts>(args)...) return m_bhvr_stack.empty() == false;
, m_in_bhvr_loop(false) }
, m_nested_count(0) { }
void do_become(behavior&& bhvr, bool discard_old) override { inline behavior& get_behavior() {
become_impl(std::move(bhvr), discard_old, message_id()); CPPA_REQUIRE(m_bhvr_stack.empty() == false);
return m_bhvr_stack.back();
} }
void become_waiting_for(behavior bhvr, message_id mid) override { optional<behavior&> sync_handler(message_id msg_id) override {
become_impl(std::move(bhvr), false, mid); return m_bhvr_stack.sync_handler(msg_id);
} }
virtual bool has_behavior() { inline void remove_handler(message_id mid) {
return static_cast<bool>(m_behavior) m_bhvr_stack.erase(mid);
|| !util::dptr<Subtype>(this)->m_bhvr_stack.empty();
} }
std::function<void()> m_behavior; inline detail::behavior_stack& bhvr_stack() {
detail::receive_policy m_recv_policy; return m_bhvr_stack;
}
private: private:
inline bool stack_empty() { void do_become(behavior_type bhvr, bool discard_old) {
return util::dptr<Subtype>(this)->m_bhvr_stack.empty(); if (discard_old) this->m_bhvr_stack.pop_async_back();
} this->reset_timeout();
void become_impl(behavior&& bhvr, bool discard_old, message_id mid) {
auto dthis = util::dptr<Subtype>(this);
if (bhvr.timeout().valid()) { if (bhvr.timeout().valid()) {
dthis->reset_timeout(); this->request_timeout(bhvr.timeout());
dthis->request_timeout(bhvr.timeout());
} }
if (!dthis->m_bhvr_stack.empty() && discard_old) { this->m_bhvr_stack.push_back(std::move(unbox(bhvr)));
dthis->m_bhvr_stack.pop_async_back();
}
dthis->m_bhvr_stack.push_back(std::move(bhvr), mid);
} }
void check_quit() { static inline behavior& unbox(behavior& arg) {
// do nothing if other message handlers are still running return arg;
if (m_nested_count > 0) return; }
auto dthis = util::dptr<Subtype>(this);
auto rsn = dthis->planned_exit_reason(); template<typename... Ts>
if (rsn != exit_reason::not_exited) { static inline behavior& unbox(typed_behavior<Ts...>& arg) {
dthis->on_exit(); return arg.unbox();
if (stack_empty()) { }
dthis->cleanup(rsn);
throw actor_exited(rsn); // utility for getting a pointer-to-derived-type
} Subtype* dptr() {
else { return static_cast<Subtype*>(this);
dthis->planned_exit_reason(exit_reason::not_exited); }
if (!m_in_bhvr_loop) exec_behavior_stack();
} // utility for getting a const pointer-to-derived-type
} const Subtype* dptr() const {
return static_cast<const Subtype*>(this);
} }
bool m_in_bhvr_loop; // allows actors to keep previous behaviors and enables unbecome()
size_t m_nested_count; detail::behavior_stack m_bhvr_stack;
};
/**
* @brief Mixin for actors using a stack-based message processing.
* @note This mixin implicitly includes {@link single_timeout}.
*/
template<class BehaviorType>
class behavior_stack_based {
public:
template<class Base, class Subtype>
class impl : public behavior_stack_based_impl<Base, Subtype, BehaviorType> {
typedef behavior_stack_based_impl<Base, Subtype, BehaviorType> super;
public:
typedef impl combined_type;
template<typename... Ts>
impl(Ts&&... args) : super(std::forward<Ts>(args)...) { }
};
}; };
} // namespace cppa } // namespace cppa
#endif // CPPA_STACKED_ACTOR_MIXIN_HPP #endif // CPPA_BEHAVIOR_STACK_BASED_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_BLOCKING_UNTYPED_ACTOR_HPP
#define CPPA_BLOCKING_UNTYPED_ACTOR_HPP
#include "cppa/on.hpp"
#include "cppa/extend.hpp"
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/sync_sender.hpp"
#include "cppa/typed_actor.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/response_handle.hpp"
namespace cppa {
/**
* @brief A thread-mapped or context-switching actor using a blocking
* receive rather than a behavior-stack based message processing.
* @extends local_actor
*/
class blocking_actor
: public extend<local_actor, blocking_actor>::
with<mailbox_based,
sync_sender<blocking_response_handle_tag>::impl> {
public:
/**************************************************************************
* utility stuff and receive() member function family *
**************************************************************************/
typedef std::chrono::high_resolution_clock::time_point timeout_type;
struct receive_while_helper {
std::function<void(behavior&)> m_dq;
std::function<bool()> m_stmt;
template<typename... Ts>
void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0,
"operator() requires at least one argument");
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
while (m_stmt()) m_dq(bhvr);
}
};
template<typename T>
struct receive_for_helper {
std::function<void(behavior&)> m_dq;
T& begin;
T end;
template<typename... Ts>
void operator()(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
for ( ; begin != end; ++begin) m_dq(bhvr);
}
};
struct do_receive_helper {
std::function<void(behavior&)> m_dq;
behavior m_bhvr;
template<typename Statement>
void until(Statement stmt) {
do { m_dq(m_bhvr); }
while (stmt() == false);
}
};
/**
* @brief Dequeues the next message from the mailbox that
* is matched by given behavior.
*/
template<typename... Ts>
void receive(Ts&&... args) {
static_assert(sizeof...(Ts), "at least one argument required");
dequeue(match_expr_convert(std::forward<Ts>(args)...));
}
/**
* @brief Receives messages in an endless loop.
* Semantically equal to: <tt>for (;;) { receive(...); }</tt>
*/
template<typename... Ts>
void receive_loop(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
for (;;) dequeue(bhvr);
}
/**
* @brief Receives messages as in a range-based loop.
*
* Semantically equal to:
* <tt>for ( ; begin != end; ++begin) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_for(i, 10) (
* on(atom("get")) >> [&]() -> any_tuple { return {"result", i}; }
* );
* @endcode
* @param begin First value in range.
* @param end Last value in range (excluded).
* @returns A functor implementing the loop.
*/
template<typename T>
receive_for_helper<T> receive_for(T& begin, const T& end) {
return {make_dequeue_callback(), begin, end};
}
/**
* @brief Receives messages as long as @p stmt returns true.
*
* Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_while([&]() { return (++i <= 10); })
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* );
* @endcode
* @param stmt Lambda expression, functor or function returning a @c bool.
* @returns A functor implementing the loop.
*/
template<typename Statement>
receive_while_helper receive_while(Statement stmt) {
static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean");
return {make_dequeue_callback(), stmt};
}
/**
* @brief Receives messages until @p stmt returns true.
*
* Semantically equal to:
* <tt>do { receive(...); } while (stmt() == false);</tt>
*
* <b>Usage example:</b>
* @code
* int i = 0;
* do_receive
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* )
* .until([&]() { return (++i >= 10); };
* @endcode
* @param bhvr Denotes the actor's response the next incoming message.
* @returns A functor providing the @c until member function.
*/
template<typename... Ts>
do_receive_helper do_receive(Ts&&... args) {
return { make_dequeue_callback()
, match_expr_convert(std::forward<Ts>(args)...)};
}
optional<behavior&> sync_handler(message_id msg_id) override {
auto i = m_sync_handler.find(msg_id);
if (i != m_sync_handler.end()) return i->second;
return none;
}
/**
* @brief Blocks this actor until all other actors are done.
*/
void await_all_other_actors_done();
/**
* @brief Implements the actor's behavior.
*/
virtual void act() = 0;
/**
* @brief Unwinds the stack by throwing an actor_exited exception.
* @throws actor_exited
*/
virtual void quit(std::uint32_t reason = exit_reason::normal);
/** @cond PRIVATE */
// required from invoke_policy; unused in blocking actors
inline void remove_handler(message_id) { }
// required by receive() member function family
inline void dequeue(behavior&& bhvr) {
behavior tmp{std::move(bhvr)};
dequeue(tmp);
}
// required by receive() member function family
inline void dequeue(behavior& bhvr) {
dequeue_response(bhvr, message_id::invalid);
}
// implemented by detail::proper_actor
virtual void dequeue_response(behavior& bhvr, message_id mid) = 0;
/** @endcond */
private:
// helper function to implement receive_(for|while) and do_receive
std::function<void(behavior&)> make_dequeue_callback() {
return [=](behavior& bhvr) { dequeue(bhvr); };
}
std::map<message_id, behavior> m_sync_handler;
};
} // namespace cppa
#endif // CPPA_BLOCKING_UNTYPED_ACTOR_HPP
...@@ -31,69 +31,79 @@ ...@@ -31,69 +31,79 @@
#ifndef CPPA_CHANNEL_HPP #ifndef CPPA_CHANNEL_HPP
#define CPPA_CHANNEL_HPP #define CPPA_CHANNEL_HPP
#include <cstddef>
#include <type_traits> #include <type_traits>
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_channel.hpp"
#include "cppa/util/comparable.hpp"
namespace cppa { namespace cppa {
// forward declarations
class actor; class actor;
class group; class group;
class any_tuple;
class message_header;
typedef intrusive_ptr<actor> actor_ptr; struct invalid_actor_t;
struct invalid_group_t;
namespace detail { class raw_access; }
/** /**
* @brief Interface for all message receivers. * @brief A handle to instances of {@link abstract_channel}.
*
* This interface describes an entity that can receive messages
* and is implemented by {@link actor} and {@link group}.
*/ */
class channel : public ref_counted { class channel : util::comparable<channel>
, util::comparable<channel, actor>
, util::comparable<channel, abstract_channel*> {
friend class actor; friend class detail::raw_access;
friend class group;
public: public:
/** channel() = default;
* @brief Enqueues @p msg to the list of received messages.
*/
virtual void enqueue(const message_header& hdr, any_tuple msg) = 0;
channel(const actor&);
/** channel(const group&);
* @brief Enqueues @p msg to the list of received messages and returns
* true if this is an scheduled actor that successfully changed
* its state to @p pending in response to the enqueue operation.
*/
virtual bool chained_enqueue(const message_header& hdr, any_tuple msg);
/** channel(const invalid_actor_t&);
* @brief Sets the state from @p pending to @p ready.
*/
virtual void unchain();
protected: channel(const invalid_group_t&);
virtual ~channel(); template<typename T>
channel(intrusive_ptr<T> ptr,
typename std::enable_if<
std::is_base_of<abstract_channel, T>::value
>::type* = 0)
: m_ptr(ptr) { }
}; channel(abstract_channel* ptr);
/** inline explicit operator bool() const {
* @brief A smart pointer type that manages instances of {@link channel}. return static_cast<bool>(m_ptr);
* @relates channel }
*/
typedef intrusive_ptr<channel> channel_ptr;
/** inline bool operator!() const {
* @brief Convenience alias. return !m_ptr;
*/ }
template<typename T, typename R = void>
using enable_if_channel = std::enable_if<std::is_base_of<channel, T>::value, R>;
void enqueue(const message_header& hdr, any_tuple msg) const;
intptr_t compare(const channel& other) const;
intptr_t compare(const actor& other) const;
intptr_t compare(const abstract_channel* other) const;
static intptr_t compare(const abstract_channel* lhs,
const abstract_channel* rhs);
private:
intrusive_ptr<abstract_channel> m_ptr;
};
} // namespace cppa } // namespace cppa
......
...@@ -31,10 +31,6 @@ ...@@ -31,10 +31,6 @@
#ifndef CPPA_CONFIG_HPP #ifndef CPPA_CONFIG_HPP
#define CPPA_CONFIG_HPP #define CPPA_CONFIG_HPP
// uncomment this line or use define CPPA_DISABLE_CONTEXT_SWITCHING using CMAKE
// if boost.context is not available on your platform
//#define CPPA_DISABLE_CONTEXT_SWITCHING
#if defined(__clang__) #if defined(__clang__)
# define CPPA_CLANG # define CPPA_CLANG
# define CPPA_DEPRECATED __attribute__((__deprecated__)) # define CPPA_DEPRECATED __attribute__((__deprecated__))
...@@ -54,6 +50,10 @@ ...@@ -54,6 +50,10 @@
# endif # endif
#elif defined(__linux__) #elif defined(__linux__)
# define CPPA_LINUX # define CPPA_LINUX
# include <linux/version.h>
# if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
# define CPPA_POLL_IMPL
# endif
#elif defined(WIN32) #elif defined(WIN32)
# define CPPA_WINDOWS # define CPPA_WINDOWS
#else #else
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
CPPA_REQUIRE__(#stmt, __FILE__, __LINE__); \ CPPA_REQUIRE__(#stmt, __FILE__, __LINE__); \
}((void) 0) }((void) 0)
#else // CPPA_DEBUG_MODE #else // CPPA_DEBUG_MODE
#define CPPA_REQUIRE(unused) ((void) 0) #define CPPA_REQUIRE(unused) static_cast<void>(0)
#endif // CPPA_DEBUG_MODE #endif // CPPA_DEBUG_MODE
#define CPPA_CRITICAL__(error, file, line) { \ #define CPPA_CRITICAL__(error, file, line) { \
...@@ -105,7 +105,6 @@ std::unique_ptr<T> create_unique(Args&&... args) { ...@@ -105,7 +105,6 @@ std::unique_ptr<T> create_unique(Args&&... args) {
return std::unique_ptr<T>{new T(std::forward<Args>(args)...)}; return std::unique_ptr<T>{new T(std::forward<Args>(args)...)};
} }
#ifdef CPPA_WINDOWS #ifdef CPPA_WINDOWS
typedef SOCKET native_socket_type; typedef SOCKET native_socket_type;
typedef const char* socket_send_ptr; typedef const char* socket_send_ptr;
......
...@@ -28,68 +28,64 @@ ...@@ -28,68 +28,64 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_CONTEXT_SWITCHING_ACTOR_HPP #ifndef CONTINUE_HELPER_HPP
#define CPPA_CONTEXT_SWITCHING_ACTOR_HPP #define CONTINUE_HELPER_HPP
#include <stack> #include <functional>
#include "cppa/config.hpp" #include "cppa/on.hpp"
#include "cppa/extend.hpp" #include "cppa/behavior.hpp"
#include "cppa/stacked.hpp" #include "cppa/message_id.hpp"
#include "cppa/scheduled_actor.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/yield_interface.hpp"
namespace cppa { namespace cppa {
class local_actor;
/** /**
* @brief Context-switching actor implementation. * @brief Helper class to enable users to add continuations
* @extends scheduled_actor * when dealing with synchronous sends.
*/ */
class context_switching_actor : public extend<scheduled_actor, context_switching_actor>::with<stacked> { class continue_helper {
friend class detail::behavior_stack; public:
friend class detail::receive_policy;
typedef combined_type super; typedef int message_id_wrapper_tag;
public: continue_helper(message_id mid, local_actor* self);
/** /**
* @brief Creates a context-switching actor running @p fun. * @brief Adds a continuation to the synchronous message handler
* that is invoked if the response handler successfully returned.
* @param fun The continuation as functor object.
*/ */
context_switching_actor(std::function<void()> fun); template<typename F>
continue_helper& continue_with(F fun) {
resume_result resume(util::fiber* from, actor_ptr& next_job); return continue_with(behavior::continuation_fun{partial_function{
on(any_vals, arg_match) >> fun
scheduled_actor_type impl_type(); }});
}
protected:
typedef std::chrono::high_resolution_clock::time_point timeout_type;
timeout_type init_timeout(const util::duration& rel_time);
mailbox_element* await_message();
mailbox_element* await_message(const timeout_type& abs_time); /**
* @brief Adds a continuation to the synchronous message handler
* that is invoked if the response handler successfully returned.
* @param fun The continuation as functor object.
*/
continue_helper& continue_with(behavior::continuation_fun fun);
inline mailbox_element* try_pop() { /**
return m_mailbox.try_pop(); * @brief Returns the ID of the expected response message.
*/
message_id get_message_id() const {
return m_mid;
} }
private: private:
// required by util::fiber message_id m_mid;
static void trampoline(void* _this); local_actor* m_self;
// members
util::fiber m_fiber;
}; };
} // namespace cppa } // namespace cppa
#endif // CPPA_CONTEXT_SWITCHING_ACTOR_HPP #endif // CONTINUE_HELPER_HPP
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <type_traits> #include <type_traits>
#include "cppa/get.hpp" #include "cppa/get.hpp"
#include "cppa/actor.hpp"
#include "cppa/cow_ptr.hpp" #include "cppa/cow_ptr.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
......
This diff is collapsed.
...@@ -39,15 +39,20 @@ namespace cppa { ...@@ -39,15 +39,20 @@ namespace cppa {
class actor; class actor;
class group; class group;
class channel; class channel;
class node_id;
class behavior; class behavior;
class any_tuple; class any_tuple;
class self_type; class actor_addr;
class actor_proxy; class actor_proxy;
class scoped_actor;
class abstract_actor;
class abstract_group;
class blocking_actor;
class message_header; class message_header;
class partial_function; class partial_function;
class uniform_type_info; class uniform_type_info;
class event_based_actor;
class primitive_variant; class primitive_variant;
class node_id;
// structs // structs
struct anything; struct anything;
...@@ -62,11 +67,9 @@ template<typename> class intrusive_ptr; ...@@ -62,11 +67,9 @@ template<typename> class intrusive_ptr;
template<typename> class weak_intrusive_ptr; template<typename> class weak_intrusive_ptr;
// intrusive pointer typedefs // intrusive pointer typedefs
typedef intrusive_ptr<actor> actor_ptr; typedef intrusive_ptr<abstract_group> abstract_group_ptr;
typedef intrusive_ptr<group> group_ptr;
typedef intrusive_ptr<channel> channel_ptr;
typedef intrusive_ptr<actor_proxy> actor_proxy_ptr; typedef intrusive_ptr<actor_proxy> actor_proxy_ptr;
typedef intrusive_ptr<node_id> node_id_ptr; typedef intrusive_ptr<node_id> node_id_ptr;
// weak intrusive pointer typedefs // weak intrusive pointer typedefs
typedef weak_intrusive_ptr<actor_proxy> weak_actor_proxy_ptr; typedef weak_intrusive_ptr<actor_proxy> weak_actor_proxy_ptr;
......
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
#include <cstdint> #include <cstdint>
#include <condition_variable> #include <condition_variable>
#include "cppa/actor.hpp"
#include "cppa/attachable.hpp" #include "cppa/attachable.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/util/shared_spinlock.hpp" #include "cppa/util/shared_spinlock.hpp"
#include "cppa/detail/singleton_mixin.hpp" #include "cppa/detail/singleton_mixin.hpp"
...@@ -59,7 +59,7 @@ class actor_registry : public singleton_mixin<actor_registry> { ...@@ -59,7 +59,7 @@ class actor_registry : public singleton_mixin<actor_registry> {
* exit reason. An entry with a nullptr means the actor has finished * exit reason. An entry with a nullptr means the actor has finished
* execution for given reason. * execution for given reason.
*/ */
typedef std::pair<actor_ptr, std::uint32_t> value_type; typedef std::pair<abstract_actor_ptr, std::uint32_t> value_type;
/** /**
* @brief Returns the {nullptr, invalid_exit_reason}. * @brief Returns the {nullptr, invalid_exit_reason}.
...@@ -67,11 +67,11 @@ class actor_registry : public singleton_mixin<actor_registry> { ...@@ -67,11 +67,11 @@ class actor_registry : public singleton_mixin<actor_registry> {
value_type get_entry(actor_id key) const; value_type get_entry(actor_id key) const;
// return nullptr if the actor wasn't put *or* finished execution // return nullptr if the actor wasn't put *or* finished execution
inline actor_ptr get(actor_id key) const { inline abstract_actor_ptr get(actor_id key) const {
return get_entry(key).first; return get_entry(key).first;
} }
void put(actor_id key, const actor_ptr& value); void put(actor_id key, const abstract_actor_ptr& value);
void erase(actor_id key, std::uint32_t reason); void erase(actor_id key, std::uint32_t reason);
......
...@@ -94,44 +94,6 @@ class behavior_stack ...@@ -94,44 +94,6 @@ class behavior_stack
m_erased_elements.clear(); m_erased_elements.clear();
} }
template<class Policy, class Client>
bool invoke(Policy& policy, Client* client, mailbox_element* node) {
CPPA_REQUIRE(!empty());
CPPA_REQUIRE(client != nullptr);
CPPA_REQUIRE(node != nullptr);
// use a copy of bhvr, because invoked behavior might change m_elements
auto id = m_elements.back().second;
auto bhvr = m_elements.back().first;
if (policy.invoke(client, node, bhvr, id)) {
bool repeat;
// try to match cached messages
do {
// remove synchronous response handler if needed
if (id.valid()) {
erase_if([id](const element_type& value) {
return id == value.second;
});
}
if (!empty()) {
id = m_elements.back().second;
bhvr = m_elements.back().first;
repeat = policy.invoke_from_cache(client, bhvr, id);
}
else repeat = false;
} while (repeat);
return true;
}
return false;
}
template<class Policy, class Client>
void exec(Policy& policy, Client* client) {
while (!empty()) {
invoke(policy, client, policy.fetch_message(client));
cleanup();
}
}
private: private:
std::vector<element_type> m_elements; std::vector<element_type> m_elements;
......
...@@ -457,16 +457,68 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T ...@@ -457,16 +457,68 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
m_members.push_back(unique_uti(new result_type)); m_members.push_back(unique_uti(new result_type));
} }
void serialize(const void* obj, serializer* s) const { void serialize(const void* obj, serializer* s) const override {
for (auto& m : m_members) m->serialize(obj, s); for (auto& m : m_members) m->serialize(obj, s);
} }
void deserialize(void* obj, deserializer* d) const { void deserialize(void* obj, deserializer* d) const override {
for (auto& m : m_members) m->deserialize(obj, d); for (auto& m : m_members) m->deserialize(obj, d);
} }
}; };
template<typename T>
class empty_uniform_type_info_impl : public uniform_type_info {
public:
bool equals(const std::type_info& tinfo) const override {
return typeid(T) == tinfo;
}
const char* name() const override {
return m_name.c_str();
}
any_tuple as_any_tuple(void*) const override {
return make_any_tuple(T{});
}
void serialize(const void*, serializer*) const override {
// no members means: nothing to do
}
void deserialize(void*, deserializer*) const override {
// no members means: nothing to do
}
empty_uniform_type_info_impl() {
auto uname = detail::to_uniform_name<T>();
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;
}
protected:
bool equals(const void*, const void*) const override {
return true;
}
void* new_instance(const void*) const override {
return new T();
}
void delete_instance(void* instance) const override {
delete reinterpret_cast<T*>(instance);
}
private:
std::string m_name;
};
} } // namespace detail } } // namespace detail
#endif // CPPA_DEFAULT_UNIFORM_TYPE_INFO_IMPL_HPP #endif // CPPA_DEFAULT_UNIFORM_TYPE_INFO_IMPL_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_EVENT_BASED_ACTOR_FACTORY_HPP
#define CPPA_EVENT_BASED_ACTOR_FACTORY_HPP
#include <type_traits>
#include "cppa/scheduler.hpp"
#include "cppa/event_based_actor.hpp"
#include "cppa/detail/tdata.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/util/type_list.hpp"
namespace cppa { namespace detail {
template<typename InitFun, typename CleanupFun, typename... Members>
class event_based_actor_impl : public event_based_actor {
public:
template<typename... Ts>
event_based_actor_impl(InitFun fun, CleanupFun cfun, Ts&&... args)
: m_init(std::move(fun)), m_on_exit(std::move(cfun))
, m_members(std::forward<Ts>(args)...) { }
void init() { apply(m_init); }
void on_exit() override {
typedef typename util::get_callable_trait<CleanupFun>::arg_types arg_types;
std::integral_constant<size_t, util::tl_size<arg_types>::value> token;
on_exit_impl(m_on_exit, token);
}
private:
InitFun m_init;
CleanupFun m_on_exit;
tdata<Members...> m_members;
template<typename F>
void apply(F& f, typename std::add_pointer<Members>::type... args) {
f(args...);
}
template<typename F, typename... Ts>
void apply(F& f, Ts... args) {
apply(f, args..., &get_ref<sizeof...(Ts)>(m_members));
}
typedef std::integral_constant<size_t, 0> zero_t;
template<typename OnExit, typename Token>
typename std::enable_if<std::is_same<Token, zero_t>::value>::type
on_exit_impl(OnExit& fun, Token) {
fun();
}
template<typename OnExit, typename Token>
typename std::enable_if<std::is_same<Token, zero_t>::value == false>::type
on_exit_impl(OnExit& fun, Token) {
apply(fun);
}
};
template<typename InitFun, typename CleanupFun, typename... Members>
class event_based_actor_factory {
public:
typedef event_based_actor_impl<InitFun, CleanupFun, Members...> impl;
event_based_actor_factory(InitFun fun, CleanupFun cfun)
: m_init(std::move(fun)), m_on_exit(std::move(cfun)) { }
template<typename... Ts>
actor_ptr spawn(Ts&&... args) {
auto ptr = make_counted<impl>(m_init, m_on_exit, std::forward<Ts>(args)...);
return get_scheduler()->exec(no_spawn_options, ptr);
}
private:
InitFun m_init;
CleanupFun m_on_exit;
};
// event-based actor factory from type list
template<typename InitFun, typename CleanupFun, class TypeList>
struct ebaf_from_type_list;
template<typename InitFun, typename CleanupFun, typename... Ts>
struct ebaf_from_type_list<InitFun, CleanupFun, util::type_list<Ts...> > {
typedef event_based_actor_factory<InitFun, CleanupFun, Ts...> type;
};
template<typename Init, typename Cleanup>
struct ebaf_from_functor {
typedef typename util::get_callable_trait<Init>::arg_types arg_types;
typedef typename util::get_callable_trait<Cleanup>::arg_types arg_types2;
static_assert(util::tl_forall<arg_types, std::is_pointer>::value,
"First functor takes non-pointer arguments");
static_assert( std::is_same<arg_types, arg_types2>::value
|| util::tl_empty<arg_types2>::value,
"Second functor must provide either the same signature "
"as the first one or must take zero arguments");
typedef typename util::tl_map<arg_types, std::remove_pointer>::type mems;
typedef typename ebaf_from_type_list<Init, Cleanup, mems>::type type;
};
} } // namespace cppa::detail
#endif // CPPA_EVENT_BASED_ACTOR_FACTORY_HPP
...@@ -28,81 +28,94 @@ ...@@ -28,81 +28,94 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_RECEIVE_LOOP_HELPER_HPP #ifndef CPPA_FUNCTOR_BASED_ACTOR_HPP
#define CPPA_RECEIVE_LOOP_HELPER_HPP #define CPPA_FUNCTOR_BASED_ACTOR_HPP
#include <new> #include <type_traits>
#include "cppa/self.hpp" #include "cppa/event_based_actor.hpp"
#include "cppa/behavior.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/type_list.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename Statement> class functor_based_actor : public event_based_actor {
struct receive_while_helper {
Statement m_stmt;
template<typename S>
receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt)) { }
template<typename... Ts>
void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0,
"operator() requires at least one argument");
behavior tmp = match_expr_convert(std::forward<Ts>(args)...);
local_actor* sptr = self;
while (m_stmt()) sptr->dequeue(tmp);
}
};
template<typename T>
class receive_for_helper {
T& begin;
T end;
public: public:
receive_for_helper(T& first, const T& last) : begin(first), end(last) { } typedef std::function<behavior(event_based_actor*)> make_behavior_fun;
template<typename... Ts> typedef std::function<void(event_based_actor*)> void_fun;
void operator()(Ts&&... args) {
auto tmp = match_expr_convert(std::forward<Ts>(args)...); template<typename F, typename... Ts>
local_actor* sptr = self; functor_based_actor(F f, Ts&&... vs) {
for ( ; begin != end; ++begin) sptr->dequeue(tmp); event_based_actor* dummy = nullptr;
create(dummy, f, std::forward<Ts>(vs)...);
} }
}; behavior make_behavior() override;
class do_receive_helper { private:
behavior m_bhvr; void create(event_based_actor*, void_fun);
public: template<class Actor, typename F, typename... Ts>
auto create(Actor*, F f, Ts&&... vs) ->
typename std::enable_if<
std::is_convertible<
decltype(f(std::forward<Ts>(vs)...)),
behavior
>::value
>::type {
auto fun = std::bind(f, std::forward<Ts>(vs)...);
m_make_behavior = [fun](Actor*) -> behavior { return fun(); };
}
inline do_receive_helper(behavior&& bhvr) : m_bhvr(std::move(bhvr)) { } template<class Actor, typename F, typename... Ts>
auto create(Actor* dummy, F f, Ts&&... vs) ->
typename std::enable_if<
std::is_convertible<
decltype(f(dummy, std::forward<Ts>(vs)...)),
behavior
>::value
>::type {
auto fun = std::bind(f, std::placeholders::_1, std::forward<Ts>(vs)...);
m_make_behavior = [fun](Actor* self) -> behavior { return fun(self); };
}
do_receive_helper(do_receive_helper&&) = default; template<class Actor, typename F, typename... Ts>
auto create(Actor*, F f, Ts&&... vs) ->
typename std::enable_if<
std::is_same<
decltype(f(std::forward<Ts>(vs)...)),
void
>::value
>::type {
std::function<void()> fun = std::bind(f, std::forward<Ts>(vs)...);
m_make_behavior = [fun](Actor*) -> behavior {
fun();
return behavior{};
};
}
template<typename Statement> template<class Actor, typename F, typename... Ts>
void until(Statement&& stmt) { auto create(Actor* dummy, F f, Ts&&... vs) ->
static_assert(std::is_same<bool, decltype(stmt())>::value, typename std::enable_if<
"functor or function does not return a boolean"); std::is_same<
local_actor* sptr = self; decltype(f(dummy, std::forward<Ts>(vs)...)),
do { void
sptr->dequeue(m_bhvr); >::value
} >::type {
while (stmt() == false); std::function<void(Actor*)> fun = std::bind(f, std::placeholders::_1,
std::forward<Ts>(vs)...);
m_make_behavior = [fun](Actor* self) -> behavior {
fun(self);
return behavior{};
};
} }
make_behavior_fun m_make_behavior;
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // CPPA_RECEIVE_LOOP_HELPER_HPP #endif // CPPA_FUNCTOR_BASED_ACTOR_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef FUNCTOR_BASED_BLOCKING_ACTOR_HPP
#define FUNCTOR_BASED_BLOCKING_ACTOR_HPP
#include "cppa/blocking_actor.hpp"
namespace cppa {
namespace detail {
class functor_based_blocking_actor : public blocking_actor {
public:
typedef std::function<void (blocking_actor*)> act_fun;
template<typename F, typename... Ts>
functor_based_blocking_actor(F f, Ts&&... vs) {
blocking_actor* dummy = nullptr;
create(dummy, f, std::forward<Ts>(vs)...);
}
protected:
void act() override;
private:
void create(blocking_actor*, act_fun);
template<class Actor, typename F, typename T0, typename... Ts>
auto create(Actor* dummy, F f, T0&& v0, Ts&&... vs) ->
typename std::enable_if<
std::is_same<
decltype(f(dummy, std::forward<T0>(v0), std::forward<Ts>(vs)...)),
void
>::value
>::type {
create(dummy, std::bind(f, std::placeholders::_1,
std::forward<T0>(v0), std::forward<Ts>(vs)...));
}
template<class Actor, typename F, typename T0, typename... Ts>
auto create(Actor* dummy, F f, T0&& v0, Ts&&... vs) ->
typename std::enable_if<
std::is_same<
decltype(f(std::forward<T0>(v0), std::forward<Ts>(vs)...)),
void
>::value
>::type {
std::function<void()> fun = std::bind(f, std::forward<T0>(v0),
std::forward<Ts>(vs)...);
create(dummy, [fun](Actor*) { fun(); });
}
act_fun m_act;
};
} // namespace detail
} // namespace cppa
#endif // FUNCTOR_BASED_BLOCKING_ACTOR_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_GET_BEHAVIOR_HPP
#define CPPA_GET_BEHAVIOR_HPP
#include <type_traits>
#include "cppa/util/call.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/tdata.hpp"
#include "cppa/scheduled_actor.hpp"
namespace cppa { namespace detail {
// default: <true, false, F>
template<bool IsFunctionPtr, bool HasArguments, typename F, typename... Ts>
class ftor_behavior : public scheduled_actor {
F m_fun;
public:
ftor_behavior(F ptr) : m_fun(ptr) { }
virtual void act() { m_fun(); }
};
template<typename F, typename... Ts>
class ftor_behavior<true, true, F, Ts...> : public scheduled_actor {
static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
F m_fun;
typedef typename tdata_from_type_list<
typename util::tl_map<util::type_list<Ts...>,
implicit_conversions>::type>::type
tdata_type;
tdata_type m_args;
public:
ftor_behavior(F ptr, const Ts&... args) : m_fun(ptr), m_args(args...) { }
virtual void act() {
util::apply_args(m_fun, m_args, util::get_indices(m_args));
}
};
template<typename F>
class ftor_behavior<false, false, F> : public scheduled_actor {
F m_fun;
public:
ftor_behavior(const F& arg) : m_fun(arg) { }
ftor_behavior(F&& arg) : m_fun(std::move(arg)) { }
virtual void act() { m_fun(); }
};
template<typename F, typename... Ts>
class ftor_behavior<false, true, F, Ts...> : public scheduled_actor {
static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
F m_fun;
typedef typename tdata_from_type_list<
typename util::tl_map<util::type_list<Ts...>,
implicit_conversions>::type>::type
tdata_type;
tdata_type m_args;
public:
ftor_behavior(const F& f, const Ts&... args) : m_fun(f), m_args(args...) {
}
ftor_behavior(F&& f, const Ts&... args)
: m_fun(std::move(f)), m_args(args...) { }
virtual void act() {
util::apply_args(m_fun, m_args, util::get_indices(m_args));
}
};
template<typename R>
scheduled_actor* get_behavior(std::integral_constant<bool, true>, R (*fptr)()) {
static_assert(std::is_convertible<R, scheduled_actor*>::value == false,
"Spawning a function returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that function?");
return new ftor_behavior<true, false, R (*)()>(fptr);
}
template<typename F>
scheduled_actor* get_behavior(std::integral_constant<bool, false>, F&& ftor) {
static_assert(std::is_convertible<decltype(ftor()), scheduled_actor*>::value == false,
"Spawning a functor returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that functor?");
typedef typename util::rm_const_and_ref<F>::type ftype;
return new ftor_behavior<false, false, ftype>(std::forward<F>(ftor));
}
template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::true_type, F fptr, const T& arg, const Ts&... args) {
static_assert(std::is_convertible<decltype(fptr(arg, args...)), scheduled_actor*>::value == false,
"Spawning a function returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that function?");
typedef ftor_behavior<true, true, F, T, Ts...> impl;
return new impl(fptr, arg, args...);
}
template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::false_type, F ftor, const T& arg, const Ts&... args) {
static_assert(std::is_convertible<decltype(ftor(arg, args...)), scheduled_actor*>::value == false,
"Spawning a functor returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that functor?");
typedef typename util::rm_const_and_ref<F>::type ftype;
typedef ftor_behavior<false, true, ftype, T, Ts...> impl;
return new impl(std::forward<F>(ftor), arg, args...);
}
} } // namespace cppa::detail
#endif // CPPA_GET_BEHAVIOR_HPP
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include "cppa/group.hpp" #include "cppa/abstract_group.hpp"
#include "cppa/util/shared_spinlock.hpp" #include "cppa/util/shared_spinlock.hpp"
#include "cppa/detail/singleton_mixin.hpp" #include "cppa/detail/singleton_mixin.hpp"
...@@ -48,18 +48,18 @@ class group_manager : public singleton_mixin<group_manager> { ...@@ -48,18 +48,18 @@ class group_manager : public singleton_mixin<group_manager> {
public: public:
intrusive_ptr<group> get(const std::string& module_name, group get(const std::string& module_name,
const std::string& group_identifier); const std::string& group_identifier);
intrusive_ptr<group> anonymous(); group anonymous();
void add_module(group::unique_module_ptr); void add_module(abstract_group::unique_module_ptr);
group::module_ptr get_module(const std::string& module_name); abstract_group::module_ptr get_module(const std::string& module_name);
private: private:
typedef std::map<std::string, group::unique_module_ptr> modules_map; typedef std::map<std::string, abstract_group::unique_module_ptr> modules_map;
modules_map m_mmap; modules_map m_mmap;
std::mutex m_mmap_mtx; std::mutex m_mmap_mtx;
......
...@@ -34,9 +34,6 @@ ...@@ -34,9 +34,6 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include "cppa/self.hpp"
#include "cppa/actor.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
namespace cppa { class local_actor; } namespace cppa { class local_actor; }
...@@ -76,10 +73,9 @@ struct implicit_conversions { ...@@ -76,10 +73,9 @@ struct implicit_conversions {
typedef typename util::replace_type< typedef typename util::replace_type<
subtype3, subtype3,
actor_ptr, actor,
std::is_convertible<T, actor*>, std::is_convertible<T, abstract_actor*>,
std::is_convertible<T, local_actor*>, std::is_same<scoped_actor, T>
std::is_same<self_type, T>
>::type >::type
type; type;
......
This diff is collapsed.
...@@ -28,27 +28,49 @@ ...@@ -28,27 +28,49 @@
\******************************************************************************/ \******************************************************************************/
#include "cppa/detail/scheduled_actor_dummy.hpp" #ifndef CPPA_RAW_ACCESS_HPP
#define CPPA_RAW_ACCESS_HPP
#include "cppa/actor.hpp"
#include "cppa/group.hpp"
#include "cppa/channel.hpp"
#include "cppa/actor_addr.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/abstract_group.hpp"
#include "cppa/abstract_channel.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
scheduled_actor_dummy::scheduled_actor_dummy() class raw_access {
: scheduled_actor(actor_state::blocked, false) { }
public:
static abstract_actor* get(const actor& hdl) {
return hdl.m_ptr.get();
}
static abstract_actor* get(const actor_addr& hdl) {
return hdl.m_ptr.get();
}
void scheduled_actor_dummy::enqueue(const message_header&, any_tuple) { } static abstract_channel* get(const channel& hdl) {
void scheduled_actor_dummy::quit(std::uint32_t) { } return hdl.m_ptr.get();
void scheduled_actor_dummy::dequeue(behavior&) { } }
void scheduled_actor_dummy::dequeue_response(behavior&, message_id) { }
void scheduled_actor_dummy::do_become(behavior&&, bool) { }
void scheduled_actor_dummy::become_waiting_for(behavior, message_id) { }
bool scheduled_actor_dummy::has_behavior() { return false; }
resume_result scheduled_actor_dummy::resume(util::fiber*, actor_ptr&) { static abstract_group* get(const group& hdl) {
return resume_result::actor_blocked; return hdl.m_ptr.get();
} }
scheduled_actor_type scheduled_actor_dummy::impl_type() { static actor unsafe_cast(abstract_actor* ptr) {
return event_based_impl; return {ptr};
} }
static actor unsafe_cast(const actor_addr& hdl) {
return {get(hdl)};
}
};
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // CPPA_RAW_ACCESS_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_DETAIL_RESPONSE_FUTURE_UTIL_HPP
#define CPPA_DETAIL_RESPONSE_FUTURE_UTIL_HPP
#include "cppa/on.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/util/type_traits.hpp"
namespace cppa {
namespace detail {
template<typename Actor, typename... Fs>
behavior fs2bhvr(Actor* self, Fs... fs) {
auto handle_sync_timeout = [self]() -> match_hint {
self->handle_sync_timeout();
return match_hint::skip;
};
return behavior{
on<sync_timeout_msg>() >> handle_sync_timeout,
on<unit_t>() >> skip_message,
on<sync_exited_msg>() >> skip_message,
(on(any_vals, arg_match) >> std::move(fs))...
};
}
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_RESPONSE_FUTURE_UTIL_HPP
...@@ -33,29 +33,22 @@ ...@@ -33,29 +33,22 @@
#include <cstdint> #include <cstdint>
#include "cppa/atom.hpp" namespace cppa {
#include "cppa/actor.hpp"
#include "cppa/any_tuple.hpp" class actor_addr;
#include "cppa/message_id.hpp" class message_id;
#include "cppa/exit_reason.hpp" class local_actor;
#include "cppa/mailbox_element.hpp" class mailbox_element;
} // namespace cppa
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct sync_request_bouncer { struct sync_request_bouncer {
std::uint32_t rsn; std::uint32_t rsn;
constexpr sync_request_bouncer(std::uint32_t r) explicit sync_request_bouncer(std::uint32_t r);
: rsn(r == exit_reason::not_exited ? exit_reason::normal : r) { } void operator()(const actor_addr& sender, const message_id& mid) const;
inline void operator()(const actor_ptr& sender, const message_id& mid) const { void operator()(const mailbox_element& e) const;
CPPA_REQUIRE(rsn != exit_reason::not_exited);
if (mid.is_request() && sender != nullptr) {
sender->enqueue({nullptr, sender, mid.response_id()},
make_any_tuple(atom("EXITED"), rsn));
}
}
inline void operator()(const mailbox_element& e) const {
(*this)(e.sender, e.mid);
}
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
#include <thread> #include <thread>
#include "cppa/resumable.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/context_switching_actor.hpp"
#include "cppa/util/producer_consumer_list.hpp" #include "cppa/util/producer_consumer_list.hpp"
#include "cppa/detail/scheduled_actor_dummy.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -46,8 +46,9 @@ class thread_pool_scheduler : public scheduler { ...@@ -46,8 +46,9 @@ class thread_pool_scheduler : public scheduler {
public: public:
using scheduler::init_callback; struct dummy : resumable {
using scheduler::void_function; resume_result resume(util::fiber*) override;
};
struct worker; struct worker;
...@@ -59,24 +60,20 @@ class thread_pool_scheduler : public scheduler { ...@@ -59,24 +60,20 @@ class thread_pool_scheduler : public scheduler {
void destroy(); void destroy();
void enqueue(scheduled_actor* what); void enqueue(resumable* what) override;
local_actor_ptr exec(spawn_options opts, scheduled_actor_ptr ptr) override;
local_actor_ptr exec(spawn_options opts, init_callback init_cb, void_function f) override;
private: private:
//typedef util::single_reader_queue<abstract_scheduled_actor> job_queue; //typedef util::single_reader_queue<abstract_scheduled_actor> job_queue;
typedef util::producer_consumer_list<scheduled_actor> job_queue; typedef util::producer_consumer_list<resumable> job_queue;
size_t m_num_threads; size_t m_num_threads;
job_queue m_queue; job_queue m_queue;
scheduled_actor_dummy m_dummy; dummy m_dummy;
std::thread m_supervisor; std::thread m_supervisor;
static void worker_loop(worker*); static void worker_loop(worker*);
static void supervisor_loop(job_queue*, scheduled_actor*, size_t); static void supervisor_loop(job_queue*, resumable*, size_t);
}; };
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "cppa/unit.hpp" #include "cppa/unit.hpp"
#include "cppa/none.hpp" #include "cppa/none.hpp"
#include "cppa/node_id.hpp" #include "cppa/node_id.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/util/buffer.hpp" #include "cppa/util/buffer.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
...@@ -60,16 +61,21 @@ namespace cppa { namespace detail { ...@@ -60,16 +61,21 @@ namespace cppa { namespace detail {
// ordered according to demangled type name (see uniform_type_info_map.cpp) // ordered according to demangled type name (see uniform_type_info_map.cpp)
using mapped_type_list = util::type_list< using mapped_type_list = util::type_list<
bool, bool,
actor,
actor_addr,
any_tuple, any_tuple,
atom_value, atom_value,
actor_ptr, channel,
channel_ptr, down_msg,
group_ptr, exit_msg,
group,
node_id_ptr, node_id_ptr,
io::accept_handle, io::accept_handle,
io::connection_handle, io::connection_handle,
message_header, message_header,
std::nullptr_t, sync_exited_msg,
sync_timeout_msg,
timeout_msg,
unit_t, unit_t,
util::buffer, util::buffer,
util::duration, util::duration,
......
...@@ -28,52 +28,50 @@ ...@@ -28,52 +28,50 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_ABSTRACT_EVENT_BASED_ACTOR_HPP #ifndef CPPA_UNTYPED_ACTOR_HPP
#define CPPA_ABSTRACT_EVENT_BASED_ACTOR_HPP #define CPPA_UNTYPED_ACTOR_HPP
#include <tuple> #include "cppa/on.hpp"
#include <stack>
#include <memory>
#include <vector>
#include "cppa/config.hpp"
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/behavior.hpp" #include "cppa/logging.hpp"
#include "cppa/stackless.hpp" #include "cppa/local_actor.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/sync_sender.hpp"
#include "cppa/detail/receive_policy.hpp" #include "cppa/mailbox_based.hpp"
#include "cppa/response_handle.hpp"
#include "cppa/behavior_stack_based.hpp"
#include "cppa/detail/response_handle_util.hpp"
namespace cppa { namespace cppa {
/** /**
* @brief Base class for all event-based actor implementations. * @brief A cooperatively scheduled, event-based actor implementation.
* @extends scheduled_actor *
* This is the recommended base class for user-defined actors and is used
* implicitly when spawning functor-based actors without the
* {@link blocking_api} flag.
*
* @extends local_actor
*/ */
class event_based_actor : public extend<scheduled_actor>::with<stackless> { class event_based_actor : public extend<local_actor, event_based_actor>::
with<mailbox_based,
friend class detail::receive_policy; behavior_stack_based<behavior>::impl,
sync_sender<nonblocking_response_handle_tag>::impl> {
typedef combined_type super; protected:
public:
resume_result resume(util::fiber*, actor_ptr&);
/** /**
* @brief Initializes the actor. * @brief Returns the initial actor behavior.
*/ */
virtual void init() = 0; virtual behavior make_behavior() = 0;
scheduled_actor_type impl_type(); /**
* @brief Forwards the last received message to @p whom.
static intrusive_ptr<event_based_actor> from(std::function<void()> fun); */
void forward_to(const actor& whom);
protected:
event_based_actor(actor_state st = actor_state::blocked);
}; };
} // namespace cppa } // namespace cppa
#endif // CPPA_ABSTRACT_EVENT_BASED_ACTOR_HPP #endif // CPPA_UNTYPED_ACTOR_HPP
...@@ -51,8 +51,8 @@ struct extend_helper<D, B, M, Ms...> : extend_helper<D, M<B, D>, Ms...> { }; ...@@ -51,8 +51,8 @@ struct extend_helper<D, B, M, Ms...> : extend_helper<D, M<B, D>, Ms...> { };
/** /**
* @brief Allows convenient definition of types using mixins. * @brief Allows convenient definition of types using mixins.
* For example, @p extend<ar, T>::with<ob, fo> is an alias for * For example, "extend<ar, T>::with<ob, fo>" is an alias for
* @p fo<ob<ar, T>, T>. * "fo<ob<ar, T>, T>".
* *
* Mixins in libcppa always have two template parameters: base type and * Mixins in libcppa always have two template parameters: base type and
* derived type. This allows mixins to make use of the curiously recurring * derived type. This allows mixins to make use of the curiously recurring
...@@ -64,7 +64,7 @@ struct extend { ...@@ -64,7 +64,7 @@ struct extend {
/** /**
* @brief Identifies the combined type. * @brief Identifies the combined type.
*/ */
template<template<class, class> class... Mixins> template<CPPA_MIXIN... Mixins>
using with = typename detail::extend_helper<Derived, Base, Mixins...>::type; using with = typename detail::extend_helper<Derived, Base, Mixins...>::type;
}; };
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_FACTORY_HPP
#define CPPA_FACTORY_HPP
#include "cppa/detail/event_based_actor_factory.hpp"
namespace cppa { namespace factory {
void default_cleanup();
/**
* @brief Returns a factory for event-based actors using @p fun as
* implementation for {@link cppa::event_based_actor::init() init()}.
*
* @p fun must take pointer arguments only. The factory creates an event-based
* actor implementation with member variables according to the functor's
* signature, as shown in the example below.
*
* @code
* auto f = factory::event_based([](int* a, int* b) { ... });
* auto actor1 = f.spawn();
* auto actor2 = f.spawn(1);
* auto actor3 = f.spawn(1, 2);
* @endcode
*
* The arguments @p a and @p b will point to @p int member variables of the
* actor. All member variables are initialized using the default constructor
* unless an initial value is passed to @p spawn.
*/
template<typename InitFun>
inline typename detail::ebaf_from_functor<InitFun, void (*)()>::type
event_based(InitFun init) {
return {std::move(init), default_cleanup};
}
/**
* @brief Returns a factory for event-based actors using @p fun0 as
* implementation for {@link cppa::event_based_actor::init() init()}
* and @p fun1 as implementation for
* {@link cppa::event_based_actor::on_exit() on_exit()}.
*/
template<typename InitFun, typename OnExitFun>
inline typename detail::ebaf_from_functor<InitFun, OnExitFun>::type
event_based(InitFun init, OnExitFun on_exit) {
return {std::move(init), on_exit};
}
} } // namespace cppa::factory
#endif // CPPA_FACTORY_HPP
This diff is collapsed.
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
#include <map> #include <map>
#include "cppa/stackless.hpp" #include "cppa/extend.hpp"
#include "cppa/threadless.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/behavior_stack_based.hpp"
#include "cppa/util/buffer.hpp" #include "cppa/util/buffer.hpp"
...@@ -45,22 +45,27 @@ ...@@ -45,22 +45,27 @@
#include "cppa/io/accept_handle.hpp" #include "cppa/io/accept_handle.hpp"
#include "cppa/io/connection_handle.hpp" #include "cppa/io/connection_handle.hpp"
#include "cppa/detail/fwd.hpp" #include "cppa/policy/not_prioritizing.hpp"
#include "cppa/policy/sequential_invoke.hpp"
namespace cppa { namespace io { namespace cppa {
namespace io {
class broker; class broker;
typedef intrusive_ptr<broker> broker_ptr; typedef intrusive_ptr<broker> broker_ptr;
local_actor_ptr init_and_launch(broker_ptr); broker_ptr init_and_launch(broker_ptr);
/** /**
* @brief A broker mediates between a libcppa-based actor system * @brief A broker mediates between a libcppa-based actor system
* and other components in the network. * and other components in the network.
* @extends local_actor * @extends local_actor
*/ */
class broker : public extend<local_actor>::with<threadless, stackless> { class broker : public extend<local_actor>::
with<behavior_stack_based<behavior>::impl> {
friend class policy::sequential_invoke;
typedef combined_type super; typedef combined_type super;
...@@ -75,20 +80,20 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -75,20 +80,20 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
friend class doorman; friend class doorman;
friend class continuation; friend class continuation;
friend local_actor_ptr init_and_launch(broker_ptr); friend broker_ptr init_and_launch(broker_ptr);
broker() = delete; broker() = delete;
public: public:
~broker();
enum policy_flag { at_least, at_most, exactly }; enum policy_flag { at_least, at_most, exactly };
void enqueue(const message_header& hdr, any_tuple msg); void enqueue(const message_header& hdr, any_tuple msg);
bool initialized() const; bool initialized() const;
void quit(std::uint32_t reason = exit_reason::normal) override;
void receive_policy(const connection_handle& hdl, void receive_policy(const connection_handle& hdl,
broker::policy_flag policy, broker::policy_flag policy,
size_t buffer_size); size_t buffer_size);
...@@ -108,7 +113,7 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -108,7 +113,7 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
return from_impl(std::bind(std::move(fun), return from_impl(std::bind(std::move(fun),
std::placeholders::_1, std::placeholders::_1,
hdl, hdl,
detail::fwd<Ts>(args)...), std::forward<Ts>(args)...),
std::move(in), std::move(in),
std::move(out)); std::move(out));
} }
...@@ -119,19 +124,17 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -119,19 +124,17 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
static broker_ptr from(F fun, acceptor_uptr in, T0&& arg0, Ts&&... args) { static broker_ptr from(F fun, acceptor_uptr in, T0&& arg0, Ts&&... args) {
return from(std::bind(std::move(fun), return from(std::bind(std::move(fun),
std::placeholders::_1, std::placeholders::_1,
detail::fwd<T0>(arg0), std::forward<T0>(arg0),
detail::fwd<Ts>(args)...), std::forward<Ts>(args)...),
std::move(in)); std::move(in));
} }
template<typename F, typename... Ts> template<typename F, typename... Ts>
actor_ptr fork(F fun, actor fork(F fun, connection_handle hdl, Ts&&... args) {
connection_handle hdl,
Ts&&... args) {
return this->fork_impl(std::bind(std::move(fun), return this->fork_impl(std::bind(std::move(fun),
std::placeholders::_1, std::placeholders::_1,
hdl, hdl,
detail::fwd<Ts>(args)...), std::forward<Ts>(args)...),
hdl); hdl);
} }
...@@ -158,10 +161,12 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -158,10 +161,12 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
explicit broker(scribe_pointer); explicit broker(scribe_pointer);
virtual behavior make_behavior() = 0;
private: private:
actor_ptr fork_impl(std::function<void (broker*)> fun, actor fork_impl(std::function<void (broker*)> fun,
connection_handle hdl); connection_handle hdl);
static broker_ptr from_impl(std::function<void (broker*)> fun, static broker_ptr from_impl(std::function<void (broker*)> fun,
input_stream_ptr in, input_stream_ptr in,
...@@ -169,6 +174,8 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -169,6 +174,8 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
void invoke_message(const message_header& hdr, any_tuple msg); void invoke_message(const message_header& hdr, any_tuple msg);
bool invoke_message_from_cache();
void erase_io(int id); void erase_io(int id);
void erase_acceptor(int id); void erase_acceptor(int id);
...@@ -182,10 +189,32 @@ class broker : public extend<local_actor>::with<threadless, stackless> { ...@@ -182,10 +189,32 @@ class broker : public extend<local_actor>::with<threadless, stackless> {
std::map<accept_handle, doorman_pointer> m_accept; std::map<accept_handle, doorman_pointer> m_accept;
std::map<connection_handle, scribe_pointer> m_io; std::map<connection_handle, scribe_pointer> m_io;
policy::not_prioritizing m_priority_policy;
policy::sequential_invoke m_invoke_policy;
}; };
//typedef intrusive_ptr<broker> broker_ptr; class default_broker : public broker {
public:
typedef std::function<void (broker*)> function_type;
default_broker(function_type f, input_stream_ptr in, output_stream_ptr out);
default_broker(function_type f, scribe_pointer ptr);
default_broker(function_type f, acceptor_uptr ptr);
behavior make_behavior() override;
private:
function_type m_fun;
};
} } // namespace cppa::network } // namespace io
} // namespace cppa
#endif // CPPA_BROKER_HPP #endif // CPPA_BROKER_HPP
This diff is collapsed.
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
namespace cppa { namespace io { namespace cppa { namespace io {
class middleman_impl; class middleman_impl;
class peer : public extend<continuable>::with<buffered_writing> { class peer : public extend<continuable>::with<buffered_writing> {
typedef combined_type super; typedef combined_type super;
...@@ -107,6 +107,7 @@ class peer : public extend<continuable>::with<buffered_writing> { ...@@ -107,6 +107,7 @@ class peer : public extend<continuable>::with<buffered_writing> {
default_message_queue_ptr m_queue; default_message_queue_ptr m_queue;
inline default_message_queue& queue() { inline default_message_queue& queue() {
CPPA_REQUIRE(m_queue != nullptr);
return *m_queue; return *m_queue;
} }
...@@ -123,18 +124,18 @@ class peer : public extend<continuable>::with<buffered_writing> { ...@@ -123,18 +124,18 @@ class peer : public extend<continuable>::with<buffered_writing> {
type_lookup_table m_incoming_types; type_lookup_table m_incoming_types;
type_lookup_table m_outgoing_types; type_lookup_table m_outgoing_types;
void monitor(const actor_ptr& sender, const node_id_ptr& node, actor_id aid); void monitor(const actor_addr& sender, const node_id_ptr& node, actor_id aid);
void kill_proxy(const actor_ptr& sender, const node_id_ptr& node, actor_id aid, std::uint32_t reason); void kill_proxy(const actor_addr& sender, const node_id_ptr& node, actor_id aid, std::uint32_t reason);
void link(const actor_ptr& sender, const actor_ptr& ptr); void link(const actor_addr& sender, const actor_addr& ptr);
void unlink(const actor_ptr& sender, const actor_ptr& ptr); void unlink(const actor_addr& sender, const actor_addr& ptr);
void deliver(const message_header& hdr, any_tuple msg); void deliver(const message_header& hdr, any_tuple msg);
inline void enqueue(const any_tuple& msg) { inline void enqueue(const any_tuple& msg) {
enqueue({nullptr, nullptr}, msg); enqueue({invalid_actor_addr, nullptr}, msg);
} }
void enqueue_impl(const message_header& hdr, const any_tuple& msg); void enqueue_impl(const message_header& hdr, const any_tuple& msg);
......
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.
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#ifndef OPTIONAL_VARIANT_HPP #ifndef OPTIONAL_VARIANT_HPP
#define OPTIONAL_VARIANT_HPP #define OPTIONAL_VARIANT_HPP
#include <iosfwd> #include <ostream>
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
......
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.
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.
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