Commit d45b8c6a authored by neverlord's avatar neverlord

Merge branch 'unstable' of github.com:Neverlord/libcppa into unstable

parents 72454443 f4510014
...@@ -22,6 +22,10 @@ else () ...@@ -22,6 +22,10 @@ else ()
set(CMAKE_BUILD_TYPE RelWithDebInfo) set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif () endif ()
if (DISABLE_CONTEXT_SWITCHING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCPPA_DISABLE_CONTEXT_SWITCHING")
endif()
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
...@@ -91,32 +95,33 @@ set(LIBCPPA_SRC ...@@ -91,32 +95,33 @@ set(LIBCPPA_SRC
set(boost_context third_party/boost_context) set(boost_context third_party/boost_context)
# add third party Boost.Context sources # add third party Boost.Context sources if context-switching is enabled
if(CMAKE_SIZEOF_VOID_P EQUAL 4) if(NOT DISABLE_CONTEXT_SWITCHING)
if(APPLE) if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(fcontext_asm ${boost_context}/src/asm/fcontext_i386_sysv_macho_gas.S) if(APPLE)
else() set(fcontext_asm ${boost_context}/src/asm/fcontext_i386_sysv_macho_gas.S)
set(fcontext_asm ${boost_context}/src/asm/fcontext_i386_sysv_elf_gas.S) else()
endif() set(fcontext_asm ${boost_context}/src/asm/fcontext_i386_sysv_elf_gas.S)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) endif()
if(APPLE) elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(fcontext_asm ${boost_context}/src/asm/fcontext_x86_64_sysv_macho_gas.S) if(APPLE)
set(fcontext_asm ${boost_context}/src/asm/fcontext_x86_64_sysv_macho_gas.S)
else()
set(fcontext_asm ${boost_context}/src/asm/fcontext_x86_64_sysv_elf_gas.S)
endif()
else() else()
set(fcontext_asm ${boost_context}/src/asm/fcontext_x86_64_sysv_elf_gas.S) message(FATAL_ERROR "Unsupported platform (neither 32 nor 64 bit)")
endif() endif()
else() set_property(SOURCE ${fcontext_asm} PROPERTY LANGUAGE CXX)
message(FATAL_ERROR "Unsupported platform (neither 32 nor 64 bit)") set(LIBCPPA_SRC
${LIBCPPA_SRC}
${fcontext_asm}
${boost_context}/src/stack_utils_posix.cpp
${boost_context}/src/stack_allocator_posix.cpp
${boost_context}/src/fcontext.cpp
)
endif() endif()
set_property(SOURCE ${fcontext_asm} PROPERTY LANGUAGE CXX)
set(LIBCPPA_SRC
${LIBCPPA_SRC}
${fcontext_asm}
${boost_context}/src/stack_utils_posix.cpp
${boost_context}/src/stack_allocator_posix.cpp
${boost_context}/src/fcontext.cpp
)
find_package(Boost COMPONENTS thread REQUIRED) find_package(Boost COMPONENTS thread REQUIRED)
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
...@@ -127,8 +132,8 @@ add_library(libcppa SHARED ${LIBCPPA_SRC}) ...@@ -127,8 +132,8 @@ add_library(libcppa SHARED ${LIBCPPA_SRC})
target_link_libraries(libcppa ${CMAKE_LD_LIBS} ${Boost_THREAD_LIBRARY}) target_link_libraries(libcppa ${CMAKE_LD_LIBS} ${Boost_THREAD_LIBRARY})
set(LIBCPPA_VERSION_MAJOR 0) set(LIBCPPA_VERSION_MAJOR 0)
set(LIBCPPA_VERSION_MINOR 2) set(LIBCPPA_VERSION_MINOR 3)
set(LIBCPPA_VERSION_PATCH 3) set(LIBCPPA_VERSION_PATCH 0)
set(LIBRARY_VERSION ${LIBCPPA_VERSION_MAJOR}.${LIBCPPA_VERSION_MINOR}.${LIBCPPA_VERSION_PATCH}) set(LIBRARY_VERSION ${LIBCPPA_VERSION_MAJOR}.${LIBCPPA_VERSION_MINOR}.${LIBCPPA_VERSION_PATCH})
set(LIBRARY_SOVERSION ${LIBCPPA_VERSION_MAJOR}) set(LIBRARY_SOVERSION ${LIBCPPA_VERSION_MAJOR})
......
...@@ -17,28 +17,32 @@ usage="\ ...@@ -17,28 +17,32 @@ usage="\
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
Build Options: Build Options:
--builddir=DIR place build files in directory [build] --builddir=DIR place build files in directory [build]
--generator=GENERATOR CMake generator to use (see cmake --help) --generator=GENERATOR CMake generator to use (see cmake --help)
--with-clang=FILE path to clang++ executable --with-clang=FILE path to clang++ executable
--with-gcc=FILE path to g++ executable --with-gcc=FILE path to g++ executable
--bin-dir=DIR executable directory [build/bin] --bin-dir=DIR executable directory [build/bin]
--lib-dir=DIR library directory [build/lib] --lib-dir=DIR library directory [build/lib]
--dual-build build both with gcc and clang --dual-build build both with gcc and clang
Installation Directories: Installation Directories:
--prefix=PREFIX installation directory [/usr/local] --prefix=PREFIX installation directory [/usr/local]
Optional Features: Optional Features:
--enable-debug compile in debugging mode --enable-debug compile in debugging mode
--enable-perftools use Google perftools --enable-perftools use Google perftools
Platform-Dependent Adjustments:
--disable-context-switching compile libcppa without context-switching actors
on platforms where Boost.Context is not available
Required Packages in Non-Standard Locations: Required Packages in Non-Standard Locations:
--with-boost=PATH path to Boost install root --with-boost=PATH path to Boost install root
Influential Environment Variables (only on first invocation Influential Environment Variables (only on first invocation
per build directory): per build directory):
CXX C++ compiler command CXX C++ compiler command
CXXFLAGS C++ compiler flags CXXFLAGS C++ compiler flags
" "
...@@ -111,8 +115,9 @@ configure () ...@@ -111,8 +115,9 @@ configure ()
# Set defaults. # Set defaults.
builddir="$sourcedir/build" builddir="$sourcedir/build"
CMakeCacheEntries="" CMakeCacheEntries=""
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
# Parse arguments. # Parse arguments.
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
...@@ -138,6 +143,9 @@ while [ $# -ne 0 ]; do ...@@ -138,6 +143,9 @@ while [ $# -ne 0 ]; do
--enable-debug) --enable-debug)
append_cache_entry ENABLE_DEBUG BOOL true append_cache_entry ENABLE_DEBUG BOOL true
;; ;;
--disable-context-switching)
append_cache_entry DISABLE_CONTEXT_SWITCHING BOOL true
;;
--with-boost=*) --with-boost=*)
append_cache_entry BOOST_ROOT PATH $optarg append_cache_entry BOOST_ROOT PATH $optarg
;; ;;
...@@ -192,7 +200,7 @@ else ...@@ -192,7 +200,7 @@ else
configure $compiler "" $bindir $libdir $CMakeGenerator configure $compiler "" $bindir $libdir $CMakeGenerator
fi fi
printf "DIRS := %s\n\n" $workdirs > $sourcedir/Makefile printf "DIRS := %s\n\n" "$workdirs" > $sourcedir/Makefile
makefile=$(cat <<'EOT' makefile=$(cat <<'EOT'
all: all:
@for i in $(DIRS); do $(MAKE) -C $$i $@; done @for i in $(DIRS); do $(MAKE) -C $$i $@; done
......
...@@ -31,12 +31,9 @@ ...@@ -31,12 +31,9 @@
#ifndef CPPA_CONTEXT_SWITCHING_ACTOR_HPP #ifndef CPPA_CONTEXT_SWITCHING_ACTOR_HPP
#define CPPA_CONTEXT_SWITCHING_ACTOR_HPP #define CPPA_CONTEXT_SWITCHING_ACTOR_HPP
#include "cppa/config.hpp"
#ifndef CPPA_DISABLE_CONTEXT_SWITCHING
#include <stack> #include <stack>
#include "cppa/config.hpp"
#include "cppa/either.hpp" #include "cppa/either.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
...@@ -122,6 +119,4 @@ class context_switching_actor : public detail::stacked_actor_mixin< ...@@ -122,6 +119,4 @@ class context_switching_actor : public detail::stacked_actor_mixin<
} // namespace cppa } // namespace cppa
#endif // CPPA_DISABLE_CONTEXT_SWITCHING
#endif // CPPA_CONTEXT_SWITCHING_ACTOR_HPP #endif // CPPA_CONTEXT_SWITCHING_ACTOR_HPP
...@@ -81,20 +81,6 @@ class thread_pool_scheduler : public scheduler { ...@@ -81,20 +81,6 @@ class thread_pool_scheduler : public scheduler {
actor_ptr spawn_as_thread(void_function fun, init_callback cb, bool hidden); actor_ptr spawn_as_thread(void_function fun, init_callback cb, bool hidden);
# ifndef CPPA_DISABLE_CONTEXT_SWITCHING
template<typename F>
actor_ptr spawn_impl(void_function fun, scheduling_hint sh, F cb) {
if (sh == scheduled) {
scheduled_actor_ptr ptr{new context_switching_actor(std::move(fun))};
ptr->attach_to_scheduler(this);
cb(ptr.get());
return spawn_impl(std::move(ptr));
}
else {
return spawn_as_thread(std::move(fun), std::move(cb));
}
}
# endif
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -31,20 +31,6 @@ ...@@ -31,20 +31,6 @@
#ifndef CPPA_FIBER_HPP #ifndef CPPA_FIBER_HPP
#define CPPA_FIBER_HPP #define CPPA_FIBER_HPP
#include <memory>
#include "cppa/config.hpp"
#ifdef CPPA_DISABLE_CONTEXT_SWITCHING
namespace cppa { namespace util {
class fiber {
public:
inline static void swap(fiber&, fiber&) { }
};
} } // namespace cppa::util
#else // CPPA_DISABLE_CONTEXT_SWITCHING
namespace cppa { namespace util { namespace cppa { namespace util {
struct fiber_impl; struct fiber_impl;
...@@ -69,6 +55,4 @@ class fiber { ...@@ -69,6 +55,4 @@ class fiber {
} } // namespace cppa::util } } // namespace cppa::util
#endif // CPPA_DISABLE_CONTEXT_SWITCHING
#endif // CPPA_FIBER_HPP #endif // CPPA_FIBER_HPP
...@@ -28,17 +28,31 @@ ...@@ -28,17 +28,31 @@
\******************************************************************************/ \******************************************************************************/
#include <cstdint>
#include <stdexcept>
#include "cppa/util/fiber.hpp"
#ifdef CPPA_DISABLE_CONTEXT_SWITCHING #ifdef CPPA_DISABLE_CONTEXT_SWITCHING
namespace { int keep_compiler_happy() { return 42; } } namespace cppa { namespace util {
fiber::fiber() throw() : m_impl(nullptr) { }
fiber::fiber(void (*)(void*), void*) : m_impl(nullptr) { }
fiber::~fiber() { }
void fiber::swap(fiber&, fiber&) {
throw std::logic_error("libcppa was compiled using "
"CPPA_DISABLE_CONTEXT_SWITCHING");
}
} } // namespace cppa::util
#else // ifdef CPPA_DISABLE_CONTEXT_SWITCHING #else // ifdef CPPA_DISABLE_CONTEXT_SWITCHING
#include <cstdint>
#include <boost/context/all.hpp> #include <boost/context/all.hpp>
#include "cppa/util/fiber.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
void fiber_trampoline(intptr_t iptr); void fiber_trampoline(intptr_t iptr);
......
...@@ -51,6 +51,24 @@ namespace { ...@@ -51,6 +51,24 @@ namespace {
typedef std::unique_lock<std::mutex> guard_type; typedef std::unique_lock<std::mutex> guard_type;
typedef intrusive::single_reader_queue<thread_pool_scheduler::worker> worker_queue; typedef intrusive::single_reader_queue<thread_pool_scheduler::worker> worker_queue;
/*
template<typename F>
actor_ptr spawn_void_fun_impl(thread_pool_scheduler* _this,
void_function fun,
scheduling_hint sh,
F cb ) {
if (sh == scheduled) {
scheduled_actor_ptr ptr{new context_switching_actor(std::move(fun))};
ptr->attach_to_scheduler(_this);
cb(ptr.get());
return _this->spawn_impl(std::move(ptr));
}
else {
return _this->spawn_as_thread(std::move(fun), std::move(cb));
}
}
*/
} // namespace <anonmyous> } // namespace <anonmyous>
struct thread_pool_scheduler::worker { struct thread_pool_scheduler::worker {
...@@ -245,6 +263,7 @@ actor_ptr thread_pool_scheduler::spawn(scheduled_actor* raw, init_callback cb) { ...@@ -245,6 +263,7 @@ actor_ptr thread_pool_scheduler::spawn(scheduled_actor* raw, init_callback cb) {
} }
#ifndef CPPA_DISABLE_CONTEXT_SWITCHING #ifndef CPPA_DISABLE_CONTEXT_SWITCHING
actor_ptr thread_pool_scheduler::spawn(void_function fun, scheduling_hint sh) { actor_ptr thread_pool_scheduler::spawn(void_function fun, scheduling_hint sh) {
if (sh == scheduled) { if (sh == scheduled) {
scheduled_actor_ptr ptr{new context_switching_actor(std::move(fun))}; scheduled_actor_ptr ptr{new context_switching_actor(std::move(fun))};
...@@ -267,17 +286,26 @@ actor_ptr thread_pool_scheduler::spawn(void_function fun, ...@@ -267,17 +286,26 @@ actor_ptr thread_pool_scheduler::spawn(void_function fun,
return spawn_impl(std::move(ptr)); return spawn_impl(std::move(ptr));
} }
else { else {
return spawn_as_thread(std::move(fun), std::move(init_cb), sh == detached_and_hidden); return spawn_as_thread(std::move(fun),
std::move(init_cb),
sh == detached_and_hidden);
} }
} }
#else
actor_ptr thread_pool_scheduler::spawn(void_function what, scheduling_hint) { #else // CPPA_DISABLE_CONTEXT_SWITCHING
return spawn_as_thread(std::move(what), [](local_actor*) { });
actor_ptr thread_pool_scheduler::spawn(void_function what, scheduling_hint sh) {
return spawn_as_thread(std::move(what),
[](local_actor*) { },
sh == detached_and_hidden);
} }
actor_ptr thread_pool_scheduler::spawn(void_function what, actor_ptr thread_pool_scheduler::spawn(void_function what,
scheduling_hint, scheduling_hint sh,
init_callback init_cb) { init_callback init_cb) {
return spawn_as_thread(std::move(what), std::move(init_cb)); return spawn_as_thread(std::move(what),
std::move(init_cb),
sh == detached_and_hidden);
} }
#endif #endif
......
...@@ -604,6 +604,63 @@ size_t test__spawn() { ...@@ -604,6 +604,63 @@ size_t test__spawn() {
await_all_others_done(); await_all_others_done();
CPPA_IF_VERBOSE(cout << "ok" << endl); CPPA_IF_VERBOSE(cout << "ok" << endl);
auto inflater = factory::event_based(
[](std::string*, actor_ptr* receiver) {
self->become(
on_arg_match >> [=](int n, const std::string& s) {
send(*receiver, n * 2, s);
},
on(atom("done")) >> []() {
self->quit();
}
);
}
);
auto joe = inflater.spawn("Joe", self);
auto bob = inflater.spawn("Bob", joe);
send(bob, 1, "hello actor");
receive (
on(4, "hello actor") >> []() {
// done
},
others() >> [] {
cerr << "unexpected: " << to_string(self->last_dequeued()) << endl;
}
);
// kill joe and bob
auto poison_pill = make_any_tuple(atom("done"));
joe << poison_pill;
bob << poison_pill;
await_all_others_done();
std::function<actor_ptr (const std::string&, const actor_ptr&)> spawn_next;
auto kr34t0r = factory::event_based(
// it's safe to pass spawn_next as reference here, because
// - it is guaranteeed to outlive kr34t0r by general scoping rules
// - the lambda is always executed in the current actor's thread
// but using spawn_next in a message handler could
// still cause undefined behavior!
[&spawn_next](std::string* name, actor_ptr* pal) {
if (*name == "Joe" && !*pal) {
*pal = spawn_next("Bob", self);
}
self->become (
others() >> [pal,name]() {
cout << "hello & bye from " << *name << endl;
// forward message and die
*pal << self->last_dequeued();
self->quit();
}
);
}
);
spawn_next = [&kr34t0r](const std::string& name, const actor_ptr& pal) {
return kr34t0r.spawn(name, pal);
};
auto joe_the_second = kr34t0r.spawn("Joe");
send(joe_the_second, atom("done"));
await_all_others_done();
int zombie_init_called = 0; int zombie_init_called = 0;
int zombie_on_exit_called = 0; int zombie_on_exit_called = 0;
factory::event_based([&]() { factory::event_based([&]() {
......
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