Commit 635412a2 authored by Matthias Vallentin's avatar Matthias Vallentin

Merge remote-tracking branch 'origin/unstable' into topic/libprocess

Conflicts:
	benchmarks/Makefile.am
parents 1a2d7619 823b722f
html/ *.beam
.DS_Store *.class
*.o
*.dylib
test
*.png
*.dat *.dat
*.dump
*.dylib
*.ii *.ii
*.s
*.tmp
*.la *.la
*.lo *.lo
*.dump *.o
*.beam *.png
*.class *.s
benchmarks/mailbox_performance *.tmp
benchmarks/actor_creation .DS_Store
benchmarks/mixed_case
benchmarks/matching
theron_mailbox_performance
.libs/
.deps/ .deps/
libcppa.pc .libs/
4threads
8threads
INSTALL
Makefile
Makefile.in Makefile.in
a.out*
aclocal.m4 aclocal.m4
autom4te.cache/ autom4te.cache/
benchmarks/actor_creation
benchmarks/distributed
benchmarks/mailbox_performance
benchmarks/matching
benchmarks/mixed_case
blob/cppatest
callgrind.out*
config.*
configure
cppa.creator.user
depcomp
examples/announce_example_1
examples/announce_example_2
examples/announce_example_3
examples/announce_example_4
examples/announce_example_5
examples/dancing_kirby
examples/dining_philosophers
examples/hello_world_example
examples/math_actor_example
gen_server/parallel_send gen_server/parallel_send
gen_server/sequential_send gen_server/sequential_send
gen_server/test.dSYM/ gen_server/test.dSYM/
depcomp html/
install-sh install-sh
libcppa.Makefile
libcppa.pc
libcppa.so*
libtool libtool
ltmain.sh ltmain.sh
missing
unit_testing/Makefile.in
unit_testing/unit_tests
unit_testing/.deps/
config.*
configure
INSTALL
m4/libtool.m4 m4/libtool.m4
m4/lt*.m4 m4/lt*.m4
a.out* missing
queue_test queue_test
cppa.creator.user test
8threads theron_mailbox_performance
4threads unit_testing/.deps/
libcppa.Makefile unit_testing/Makefile
unit_testing/Makefile.in
unit_testing/unit_tests
variadic_templates_test variadic_templates_test
variadic_templates_test.dSYM/ variadic_templates_test.dSYM/
Makefile
unit_testing/Makefile
libcppa.so*
blob/cppatest
callgrind.out*
examples/announce_example_1
examples/announce_example_2
examples/announce_example_3
examples/announce_example_4
examples/announce_example_5
examples/hello_world_example
examples/math_actor_example
examples/dining_philosophers
examples/dancing_kirby
...@@ -4,7 +4,6 @@ lib_LTLIBRARIES = libcppa.la ...@@ -4,7 +4,6 @@ lib_LTLIBRARIES = libcppa.la
libcppa_la_SOURCES = \ libcppa_la_SOURCES = \
src/abstract_event_based_actor.cpp \ src/abstract_event_based_actor.cpp \
src/abstract_scheduled_actor.cpp \
src/abstract_tuple.cpp \ src/abstract_tuple.cpp \
src/actor.cpp \ src/actor.cpp \
src/actor_count.cpp \ src/actor_count.cpp \
...@@ -40,12 +39,12 @@ libcppa_la_SOURCES = \ ...@@ -40,12 +39,12 @@ libcppa_la_SOURCES = \
src/partial_function.cpp \ src/partial_function.cpp \
src/pattern.cpp \ src/pattern.cpp \
src/post_office.cpp \ src/post_office.cpp \
src/post_office_msg.cpp \
src/primitive_variant.cpp \ src/primitive_variant.cpp \
src/process_information.cpp \ src/process_information.cpp \
src/receive.cpp \ src/receive.cpp \
src/ripemd_160.cpp \ src/ripemd_160.cpp \
src/scheduled_actor.cpp \ src/scheduled_actor.cpp \
src/scheduled_actor_dummy.cpp \
src/scheduler.cpp \ src/scheduler.cpp \
src/self.cpp \ src/self.cpp \
src/serializer.cpp \ src/serializer.cpp \
...@@ -102,6 +101,7 @@ nobase_library_include_HEADERS = \ ...@@ -102,6 +101,7 @@ nobase_library_include_HEADERS = \
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/filter_result.hpp \
cppa/detail/get_behavior.hpp \ cppa/detail/get_behavior.hpp \
cppa/detail/group_manager.hpp \ cppa/detail/group_manager.hpp \
cppa/detail/implicit_conversions.hpp \ cppa/detail/implicit_conversions.hpp \
...@@ -112,18 +112,20 @@ nobase_library_include_HEADERS = \ ...@@ -112,18 +112,20 @@ nobase_library_include_HEADERS = \
cppa/detail/matches.hpp \ cppa/detail/matches.hpp \
cppa/detail/mock_scheduler.hpp \ cppa/detail/mock_scheduler.hpp \
cppa/detail/native_socket.hpp \ cppa/detail/native_socket.hpp \
cppa/detail/nestable_receive_actor.hpp \
cppa/detail/network_manager.hpp \ cppa/detail/network_manager.hpp \
cppa/detail/object_array.hpp \ cppa/detail/object_array.hpp \
cppa/detail/object_impl.hpp \ cppa/detail/object_impl.hpp \
cppa/detail/pair_member.hpp \ cppa/detail/pair_member.hpp \
cppa/detail/post_office.hpp \ cppa/detail/post_office.hpp \
cppa/detail/post_office_msg.hpp \
cppa/detail/primitive_member.hpp \ cppa/detail/primitive_member.hpp \
cppa/detail/projection.hpp \ cppa/detail/projection.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/receive_loop_helper.hpp \
cppa/detail/recursive_queue_node.hpp \
cppa/detail/ref_counted_impl.hpp \ cppa/detail/ref_counted_impl.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/swap_bytes.hpp \ cppa/detail/swap_bytes.hpp \
......
...@@ -104,14 +104,12 @@ object ActorCreation { ...@@ -104,14 +104,12 @@ object ActorCreation {
if (args(0) == "threaded") { if (args(0) == "threaded") {
val newMax = (1 << n) + 100 val newMax = (1 << n) + 100
System.setProperty("actors.maxPoolSize", newMax.toString) System.setProperty("actors.maxPoolSize", newMax.toString)
//actor {
(new ThreadedTestee(self)).start ! Spread(n) (new ThreadedTestee(self)).start ! Spread(n)
receive { receive {
case Result(v) => case Result(v) =>
if (v != (1 << n)) if (v != (1 << n))
Console.println("ERROR: expected " + (1 << n) + ", received " + v) Console.println("ERROR: expected " + (1 << n) + ", received " + v)
} }
//}
} }
else if (args(0) == "threadless") { else if (args(0) == "threadless") {
actor { actor {
......
This diff is collapsed.
...@@ -3,13 +3,14 @@ ACLOCAL_AMFLAGS = -I ../m4 ...@@ -3,13 +3,14 @@ ACLOCAL_AMFLAGS = -I ../m4
AM_CXXFLAGS = -I../ --std=c++0x -pedantic -Wall -Wextra AM_CXXFLAGS = -I../ --std=c++0x -pedantic -Wall -Wextra
noinst_PROGRAMS = actor_creation mailbox_performance mixed_case_libcppa mixed_case_libprocess matching noinst_PROGRAMS = actor_creation mailbox_performance mixed_case_libcppa mixed_case_libprocess matching distributed
actor_creation_SOURCES = actor_creation.cpp actor_creation_SOURCES = actor_creation.cpp
mailbox_performance_SOURCES = mailbox_performance.cpp mailbox_performance_SOURCES = mailbox_performance.cpp
mixed_case_libcppa_SOURCES = mixed_case_libcppa.cpp mixed_case_libcppa_SOURCES = mixed_case_libcppa.cpp
mixed_case_libprocess_SOURCES = mixed_case_libprocess.cpp mixed_case_libprocess_SOURCES = mixed_case_libprocess.cpp
matching_SOURCES = matching.cpp matching_SOURCES = matching.cpp
distributed_SOURCES = distributed.cpp
EXAMPLES_LIBS = -L../.libs/ -lcppa $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) EXAMPLES_LIBS = -L../.libs/ -lcppa $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB)
...@@ -18,3 +19,4 @@ mailbox_performance_LDADD = $(EXAMPLES_LIBS) ...@@ -18,3 +19,4 @@ mailbox_performance_LDADD = $(EXAMPLES_LIBS)
mixed_case_libcppa_LDADD = $(EXAMPLES_LIBS) mixed_case_libcppa_LDADD = $(EXAMPLES_LIBS)
mixed_case_libprocess_LDADD = -L../.libs/ -lglog $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) mixed_case_libprocess_LDADD = -L../.libs/ -lglog $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB)
matching_LDADD = $(EXAMPLES_LIBS) matching_LDADD = $(EXAMPLES_LIBS)
distributed_LDADD = $(EXAMPLES_LIBS)
...@@ -44,32 +44,23 @@ using std::uint32_t; ...@@ -44,32 +44,23 @@ using std::uint32_t;
using namespace cppa; using namespace cppa;
struct testee : fsm_actor<testee> struct testee : fsm_actor<testee> {
{
actor_ptr parent; actor_ptr parent;
behavior init_state; behavior init_state;
testee(const actor_ptr& pptr) : parent(pptr) testee(const actor_ptr& pptr) : parent(pptr) {
{ init_state = (
init_state = on(atom("spread"), 0) >> [=]() {
(
on(atom("spread"), 0) >> [=]()
{
send(parent, atom("result"), (uint32_t) 1); send(parent, atom("result"), (uint32_t) 1);
become_void(); become_void();
}, },
on<atom("spread"), int>() >> [=](int x) on<atom("spread"), int>() >> [=](int x) {
{
any_tuple msg = make_cow_tuple(atom("spread"), x - 1); any_tuple msg = make_cow_tuple(atom("spread"), x - 1);
spawn(new testee(this)) << msg; spawn(new testee(this)) << msg;
spawn(new testee(this)) << msg; spawn(new testee(this)) << msg;
become become (
( on<atom("result"), uint32_t>() >> [=](uint32_t r1) {
on<atom("result"), uint32_t>() >> [=](uint32_t r1) become (
{ on<atom("result"), uint32_t>() >> [=](uint32_t r2) {
become
(
on<atom("result"), uint32_t>() >> [=](uint32_t r2)
{
send(parent, atom("result"), r1 + r2); send(parent, atom("result"), r1 + r2);
become_void(); become_void();
} }
...@@ -81,27 +72,19 @@ struct testee : fsm_actor<testee> ...@@ -81,27 +72,19 @@ struct testee : fsm_actor<testee>
} }
}; };
void stacked_testee(actor_ptr parent) void stacked_testee(actor_ptr parent) {
{ receive (
receive on(atom("spread"), 0) >> [&]() {
(
on(atom("spread"), 0) >> [&]()
{
send(parent, atom("result"), (uint32_t) 1); send(parent, atom("result"), (uint32_t) 1);
}, },
on<atom("spread"), int>() >> [&](int x) on<atom("spread"), int>() >> [&](int x) {
{
any_tuple msg = make_cow_tuple(atom("spread"), x-1); any_tuple msg = make_cow_tuple(atom("spread"), x-1);
spawn(stacked_testee, self) << msg; spawn(stacked_testee, self) << msg;
spawn(stacked_testee, self) << msg; spawn(stacked_testee, self) << msg;
receive receive (
( on<atom("result"), uint32_t>() >> [&](uint32_t v1) {
on<atom("result"), uint32_t>() >> [&](uint32_t v1) receive (
{ on<atom("result"),uint32_t>() >> [&](uint32_t v2) {
receive
(
on<atom("result"),uint32_t>() >> [&](uint32_t v2)
{
send(parent, atom("result"), v1 + v2); send(parent, atom("result"), v1 + v2);
} }
); );
...@@ -111,45 +94,38 @@ void stacked_testee(actor_ptr parent) ...@@ -111,45 +94,38 @@ void stacked_testee(actor_ptr parent)
); );
} }
void usage() void usage() {
{
cout << "usage: actor_creation (stacked|event-based) POW" << endl cout << "usage: actor_creation (stacked|event-based) POW" << endl
<< " creates 2^POW actors" << endl << " creates 2^POW actors" << endl
<< endl; << endl;
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{ if (argc == 3) {
if (argc == 3)
{
int num = rd<int>(argv[2]); int num = rd<int>(argv[2]);
if (strcmp(argv[1], "stacked") == 0) if (strcmp(argv[1], "stacked") == 0) {
{
send(spawn(stacked_testee, self), atom("spread"), num); send(spawn(stacked_testee, self), atom("spread"), num);
} }
else if (strcmp(argv[1], "event-based") == 0) else if (strcmp(argv[1], "event-based") == 0) {
{
send(spawn(new testee(self)), atom("spread"), num); send(spawn(new testee(self)), atom("spread"), num);
} }
else else {
{
usage(); usage();
return 1; return 1;
} }
receive receive (
( on<atom("result"),uint32_t>() >> [=](uint32_t value) {
on<atom("result"),uint32_t>() >> [=](uint32_t value)
{
//cout << "value = " << value << endl //cout << "value = " << value << endl
// << "expected => 2^" << num << " = " // << "expected => 2^" << num << " = "
// << (1 << num) << endl; // << (1 << num) << endl;
assert(value == (((uint32_t) 1) << num)); if (value != (((uint32_t) 1) << num)) {
cerr << "ERROR: received wrong result!\n";
}
} }
); );
await_all_others_done(); await_all_others_done();
} }
else else {
{
usage(); usage();
return 1; return 1;
} }
......
pongServer {
akka {
loglevel = ERROR
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
untrusted-mode = on
remote-daemon-ack-timeout = 300s
netty {
backoff-timeout = 0ms
connection-timeout = 300s
hostname = "mobi10"
port = 2244
}
}
}
}
This diff is collapsed.
-module(distributed).
-export([start/1, ping_loop/2]).
ping_loop(Parent, Pong) ->
receive
{pong, 0} -> Parent ! done;
{pong, X} ->
Pong ! {ping, self(), X - 1},
ping_loop(Parent, Pong);
{kickoff, X} ->
Pong ! {ping, self(), X},
ping_loop(Parent, Pong);
_ -> ping_loop(Parent, Pong)
end.
server_loop(Pongs) ->
receive
{ping, Pid, X} ->
Pid ! {pong, X},
server_loop(Pongs);
{add_pong, Pid, Node} ->
case lists:any(fun({N, _}) -> N == Node end, Pongs) of
true ->
Pid ! {ok, cached},
server_loop(Pongs);
false ->
case rpc:call(Node, erlang, whereis, [pong]) of
{badrpc, Reason} ->
Pid ! {error, Reason},
server_loop(Pongs);
undefined ->
Pid ! {error, 'pong is undefined'},
server_loop(Pongs);
Pong ->
Pid ! {ok, added},
server_loop(Pongs ++ [{Node, Pong}])
end
end;
{purge} -> server_loop([]);
{get_pongs, Pid} ->
Pid ! Pongs,
server_loop(Pongs);
{kickoff, Pid, NumPings} ->
lists:foreach(fun({_, P}) -> spawn(distributed, ping_loop, [Pid, P]) ! {kickoff, NumPings} end, Pongs),
server_loop(Pongs);
_ -> server_loop(Pongs)
end.
server_mode() ->
register(pong, self()),
server_loop([]).
add_pong_fun(_, _, []) -> true;
add_pong_fun(Pong, Node, [Node|T]) -> add_pong_fun(Pong, Node, T);
add_pong_fun(Pong, Node, [H|T]) ->
Pong ! {add_pong, self(), H},
receive
{ok, _} -> add_pong_fun(Pong, Node, T);
{error, Reason} -> error(Reason)
after 10000 -> error(timeout)
end.
client_mode_receive_done_msgs(0) -> true;
client_mode_receive_done_msgs(Left) ->
receive done -> client_mode_receive_done_msgs(Left - 1) end.
% receive a {done} message for each node
client_mode([], [], [], _) -> error("no node, no fun");
client_mode([], [], Nodes, _) ->
client_mode_receive_done_msgs(length(Nodes) * (length(Nodes) - 1));
% send kickoff messages
client_mode([Pong|Pongs], [], Nodes, NumPings) ->
Pong ! {kickoff, self(), NumPings},
client_mode(Pongs, [], Nodes, NumPings);
client_mode(Pongs, [H|T], Nodes, NumPings) ->
case rpc:call(H, erlang, whereis, [pong]) of
{badrpc, Reason} ->
io:format("cannot connect to ~s~n", [atom_to_list(H)]),
error(Reason);
undefined ->
io:format("no 'pong' defined on node ~s~n", [atom_to_list(H)]);
P ->
add_pong_fun(P, H, Nodes),
client_mode(Pongs ++ [P], T, Nodes, NumPings)
end.
run(_, undefined, []) -> error("NumPings is undefined");
run(Hosts, _, []) when length(Hosts) < 2 -> error("less than two nodes specified");
run(Hosts, NumPings, []) -> client_mode([], Hosts, Hosts, NumPings);
run(Hosts, NumPings, [H|T]) ->
Arg = atom_to_list(H),
case lists:prefix("num_pings=", Arg) of
true when NumPings /= undefined -> error("NumPings already set");
true -> run(Hosts, list_to_integer(lists:sublist(Arg, 11, length(Arg))), T);
false -> run(Hosts ++ [H], NumPings, T)
end.
start(X) ->
case X of
['mode=server'|[]] -> server_mode();
['mode=server'|_] -> io:format("too much arguments~n", []);
['mode=benchmark'|T] -> run([], undefined, T);
_ -> io:format("invalid arguments~n", [])
end.
#!/bin/bash #!/bin/bash
echo "erl -noshell -noinput +P 20000000 -s $@ -s init stop" | ./exec.sh echo "erl -noshell -noinput +P 20000000 -setcookie abc123 -sname benchmark -s $@ -s init stop" | ./exec.sh
...@@ -45,19 +45,14 @@ using std::int64_t; ...@@ -45,19 +45,14 @@ using std::int64_t;
using namespace cppa; using namespace cppa;
struct fsm_receiver : fsm_actor<fsm_receiver> struct fsm_receiver : fsm_actor<fsm_receiver> {
{
int64_t m_value; int64_t m_value;
behavior init_state; behavior init_state;
fsm_receiver(int64_t max) : m_value(0) fsm_receiver(int64_t max) : m_value(0) {
{ init_state = (
init_state = on(atom("msg")) >> [=]() {
(
on(atom("msg")) >> [=]()
{
++m_value; ++m_value;
if (m_value == max) if (m_value == max) {
{
become_void(); become_void();
} }
} }
...@@ -65,63 +60,49 @@ struct fsm_receiver : fsm_actor<fsm_receiver> ...@@ -65,63 +60,49 @@ struct fsm_receiver : fsm_actor<fsm_receiver>
} }
}; };
void receiver(int64_t max) void receiver(int64_t max) {
{
int64_t value; int64_t value;
receive_while(gref(value) < max) receive_while(gref(value) < max) (
//receive_while([&]() { return value < max; }) on(atom("msg")) >> [&]() {
(
on(atom("msg")) >> [&]()
{
++value; ++value;
} }
); );
} }
void sender(actor_ptr whom, int64_t count) void sender(actor_ptr whom, int64_t count) {
{
any_tuple msg = make_cow_tuple(atom("msg")); any_tuple msg = make_cow_tuple(atom("msg"));
for (int64_t i = 0; i < count; ++i) for (int64_t i = 0; i < count; ++i) {
{
whom->enqueue(nullptr, msg); whom->enqueue(nullptr, msg);
} }
} }
void usage() void usage() {
{
cout << "usage: mailbox_performance " cout << "usage: mailbox_performance "
"(stacked|event-based) (sending threads) (msg per thread)" << endl "(stacked|event-based) (sending threads) (msg per thread)" << endl
<< endl; << endl;
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{ if (argc == 4) {
if (argc == 4)
{
int64_t num_sender = rd<int64_t>(argv[2]); int64_t num_sender = rd<int64_t>(argv[2]);
int64_t num_msgs = rd<int64_t>(argv[3]); int64_t num_msgs = rd<int64_t>(argv[3]);
actor_ptr testee; actor_ptr testee;
if (strcmp(argv[1], "stacked") == 0) if (strcmp(argv[1], "stacked") == 0) {
{
testee = spawn(receiver, num_sender * num_msgs); testee = spawn(receiver, num_sender * num_msgs);
} }
else if (strcmp(argv[1], "event-based") == 0) else if (strcmp(argv[1], "event-based") == 0) {
{
testee = spawn(new fsm_receiver(num_sender * num_msgs)); testee = spawn(new fsm_receiver(num_sender * num_msgs));
} }
else else {
{
usage(); usage();
return 1; return 1;
} }
for (int64_t i = 0; i < num_sender; ++i) for (int64_t i = 0; i < num_sender; ++i) {
{
detail::thread(sender, testee, num_msgs).detach(); detail::thread(sender, testee, num_msgs).detach();
} }
await_all_others_done(); await_all_others_done();
} }
else else {
{
usage(); usage();
return 1; return 1;
} }
......
...@@ -53,12 +53,10 @@ using std::int64_t; ...@@ -53,12 +53,10 @@ using std::int64_t;
using namespace cppa; using namespace cppa;
template<typename T> template<typename T>
T rd(char const* cstr) T rd(char const* cstr) {
{
char* endptr = nullptr; char* endptr = nullptr;
T result = static_cast<T>(strtol(cstr, &endptr, 10)); T result = static_cast<T>(strtol(cstr, &endptr, 10));
if (endptr == nullptr || *endptr != '\0') if (endptr == nullptr || *endptr != '\0') {
{
std::string errstr; std::string errstr;
errstr += "\""; errstr += "\"";
errstr += cstr; errstr += cstr;
...@@ -68,29 +66,71 @@ T rd(char const* cstr) ...@@ -68,29 +66,71 @@ T rd(char const* cstr)
return result; return result;
} }
int main(int argc, char** argv) void usage() {
{ cerr << "usage: matching (cow_tuple|object_array) {NUM_LOOPS}" << endl;
exit(1);
}
int main(int argc, char** argv) {
announce<list<int>>(); announce<list<int>>();
if (argc != 2) if (argc != 3) usage();
{ auto num_loops = rd<int64_t>(argv[2]);
cerr << "usage: matching {NUM_LOOPS}" << endl; any_tuple m1;
return 1; any_tuple m2;
any_tuple m3;
any_tuple m4;
any_tuple m5;
any_tuple m6;
if (strcmp(argv[1], "cow_tuple") == 0) {
m1 = make_cow_tuple(atom("msg1"), 0);
m2 = make_cow_tuple(atom("msg2"), 0.0);
m3 = make_cow_tuple(atom("msg3"), list<int>{0});
m4 = make_cow_tuple(atom("msg4"), 0, "0");
m5 = make_cow_tuple(atom("msg5"), 0, 0, 0);
m6 = make_cow_tuple(atom("msg6"), 0, 0.0, "0");
}
else if (strcmp(argv[1], "object_array") == 0) {
auto m1o = new detail::object_array;
m1o->push_back(object::from(atom("msg1")));
m1o->push_back(object::from(0));
m1 = any_tuple{m1o};
auto m2o = new detail::object_array;
m2o->push_back(object::from(atom("msg2")));
m2o->push_back(object::from(0.0));
m2 = any_tuple{m2o};
auto m3o = new detail::object_array;
m3o->push_back(object::from(atom("msg3")));
m3o->push_back(object::from(list<int>{0}));
m3 = any_tuple{m3o};
auto m4o = new detail::object_array;
m4o->push_back(object::from(atom("msg4")));
m4o->push_back(object::from(0));
m4o->push_back(object::from(std::string("0")));
m4 = any_tuple{m4o};
auto m5o = new detail::object_array;
m5o->push_back(object::from(atom("msg5")));
m5o->push_back(object::from(0));
m5o->push_back(object::from(0));
m5o->push_back(object::from(0));
m5 = any_tuple{m5o};
auto m6o = new detail::object_array;
m6o->push_back(object::from(atom("msg6")));
m6o->push_back(object::from(0));
m6o->push_back(object::from(0.0));
m6o->push_back(object::from(std::string("0")));
m6 = any_tuple{m6o};
}
else {
usage();
} }
auto num_loops = rd<int64_t>(argv[1]);
any_tuple m1 = make_cow_tuple(atom("msg1"), 0);
any_tuple m2 = make_cow_tuple(atom("msg2"), 0.0);
any_tuple m3 = cppa::make_cow_tuple(atom("msg3"), list<int>{0});
any_tuple m4 = make_cow_tuple(atom("msg4"), 0, "0");
any_tuple m5 = make_cow_tuple(atom("msg5"), 0, 0, 0);
any_tuple m6 = make_cow_tuple(atom("msg6"), 0, 0.0, "0");
int64_t m1matched = 0; int64_t m1matched = 0;
int64_t m2matched = 0; int64_t m2matched = 0;
int64_t m3matched = 0; int64_t m3matched = 0;
int64_t m4matched = 0; int64_t m4matched = 0;
int64_t m5matched = 0; int64_t m5matched = 0;
int64_t m6matched = 0; int64_t m6matched = 0;
auto part_fun = auto part_fun = (
(
on<atom("msg1"), int>() >> [&]() { ++m1matched; }, on<atom("msg1"), int>() >> [&]() { ++m1matched; },
on<atom("msg2"), double>() >> [&]() { ++m2matched; }, on<atom("msg2"), double>() >> [&]() { ++m2matched; },
on<atom("msg3"), list<int> >() >> [&]() { ++m3matched; }, on<atom("msg3"), list<int> >() >> [&]() { ++m3matched; },
...@@ -98,8 +138,7 @@ int main(int argc, char** argv) ...@@ -98,8 +138,7 @@ int main(int argc, char** argv)
on<atom("msg5"), int, int, int>() >> [&]() { ++m5matched; }, on<atom("msg5"), int, int, int>() >> [&]() { ++m5matched; },
on<atom("msg6"), int, double, string>() >> [&]() { ++m6matched; } on<atom("msg6"), int, double, string>() >> [&]() { ++m6matched; }
); );
for (int64_t i = 0; i < num_loops; ++i) for (int64_t i = 0; i < num_loops; ++i) {
{
part_fun(m1); part_fun(m1);
part_fun(m2); part_fun(m2);
part_fun(m3); part_fun(m3);
...@@ -107,4 +146,10 @@ int main(int argc, char** argv) ...@@ -107,4 +146,10 @@ int main(int argc, char** argv)
part_fun(m5); part_fun(m5);
part_fun(m6); part_fun(m6);
} }
assert(m1matched == num_loops);
assert(m2matched == num_loops);
assert(m3matched == num_loops);
assert(m4matched == num_loops);
assert(m5matched == num_loops);
assert(m6matched == num_loops);
} }
This diff is collapsed.
#!/bin/bash #!/bin/bash
if [[ $# -eq 0 ]] ; then if [[ $# -eq 0 ]] ; then
for i in *.scala; do for i in *.scala; do
echo "scalac -cp ../../akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar \"$i\"" echo "compile \"$i\""
scalac -cp ../../akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar "$i" scalac -unchecked -cp $AKKA_LIBS "$i"
done done
elif [[ $# -eq 1 ]] ; then elif [[ $# -eq 1 ]] ; then
echo "scalac -cp ../../akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar \"$1.scala\"" echo "compile \"$1.scala\""
scalac -cp ../../akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar "$1.scala" scalac -unchecked -cp $AKKA_LIBS "$1.scala"
fi fi
echo done echo done
#!/bin/bash #!/bin/bash
#export JAVA_OPTS="-Xmx1024" #export JAVA_OPTS="-Xmx1024"
#echo "scala -cp /home/neverlord/akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar $@" | ./exec.sh #echo "scala -cp /home/neverlord/akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar $@" | ./exec.sh
echo "scala -cp /home/neverlord/akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar $@" | ./exec.sh JARS=/home/neverlord/akka-microkernel-1.2/lib/akka/activation-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-actor-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-actor-tests-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-amqp-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-beanstalk-mailbox-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-camel-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-camel-typed-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-dispatcher-extras-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-file-mailbox-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-http-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-kernel-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-mailboxes-common-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-redis-mailbox-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-remote-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-scalaz-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-slf4j-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-spring-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-stm-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-testkit-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/akka-typed-actor-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/amqp-client-2.5.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/aopalliance-1.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/asm-3.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/aspectwerkz-2.2.3.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/beanstalk_client-1.4.5.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/camel-core-2.7.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-cli-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-codec-1.4.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-io-2.0.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-logging-1.1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-management-1.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/commons-pool-1.5.5.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/dispatch-json_2.9.0-0.8.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/guice-all-2.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/h2-lzf-1.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/hawtdispatch-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/hawtdispatch-scala-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jackson-core-asl-1.8.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jackson-mapper-asl-1.8.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jaxb-api-2.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jaxb-impl-2.1.12.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jersey-core-1.3.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jersey-json-1.3.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jersey-scala-1.3.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jersey-server-1.3.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jettison-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-continuation-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-http-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-io-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-security-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-server-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-servlet-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-util-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jetty-xml-7.4.0.v20110414.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jsr250-api-1.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jsr311-api-1.1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/jsr311-api-1.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/junit-4.8.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/log4j-1.2.16.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/multiverse-alpha-0.6.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/netty-3.2.5.Final.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/objenesis-1.2.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/protobuf-java-2.4.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/redisclient_2.9.0-2.3.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/scalaz-core_2.9.0-1-6.0.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/servlet-api-2.5.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/sjson_2.9.0-0.11.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/slf4j-api-1.5.8.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/slf4j-api-1.6.0.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/slf4j-log4j12-1.5.8.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-aop-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-asm-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-beans-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-context-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-core-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/spring-expression-3.0.5.RELEASE.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/stax-api-1.0.1.jar:/home/neverlord/akka-microkernel-1.2/lib/akka/stax-api-1.0-2.jar
echo "scala -cp $JARS $@" | ./exec.sh
...@@ -18,41 +18,33 @@ struct result { uint32_t value; }; ...@@ -18,41 +18,33 @@ struct result { uint32_t value; };
using namespace Theron; using namespace Theron;
struct testee : Actor struct testee : Actor {
{
Address m_parent; Address m_parent;
bool m_first_result_received; bool m_first_result_received;
uint32_t m_first_result; uint32_t m_first_result;
std::vector<ActorRef> m_children; std::vector<ActorRef> m_children;
void spread_handler(const spread& arg, const Address) void spread_handler(const spread& arg, const Address) {
{ if (arg.value == 0) {
if (arg.value == 0)
{
Send(result{1}, m_parent); Send(result{1}, m_parent);
} }
else else {
{
spread msg = {arg.value-1}; spread msg = {arg.value-1};
Parameters params = {GetAddress()}; Parameters params = {GetAddress()};
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i) {
{
m_children.push_back(GetFramework().CreateActor<testee>(params)); m_children.push_back(GetFramework().CreateActor<testee>(params));
m_children.back().Push(msg, GetAddress()); m_children.back().Push(msg, GetAddress());
} }
} }
} }
void result_handler(const result& arg, const Address) void result_handler(const result& arg, const Address) {
{ if (!m_first_result_received) {
if (!m_first_result_received)
{
m_first_result_received = true; m_first_result_received = true;
m_first_result = arg.value; m_first_result = arg.value;
} }
else else {
{
m_children.clear(); m_children.clear();
Send(result{m_first_result + arg.value}, m_parent); Send(result{m_first_result + arg.value}, m_parent);
} }
...@@ -60,25 +52,21 @@ struct testee : Actor ...@@ -60,25 +52,21 @@ struct testee : Actor
typedef struct { Address arg0; } Parameters; typedef struct { Address arg0; } Parameters;
testee(const Parameters& p) : m_parent(p.arg0), m_first_result_received(false) testee(const Parameters& p) : m_parent(p.arg0), m_first_result_received(false) {
{
RegisterHandler(this, &testee::spread_handler); RegisterHandler(this, &testee::spread_handler);
RegisterHandler(this, &testee::result_handler); RegisterHandler(this, &testee::result_handler);
} }
}; };
void usage() void usage() {
{
cout << "usage: theron_actor_creation _ POW" << endl cout << "usage: theron_actor_creation _ POW" << endl
<< " creates 2^POW actors" << endl << " creates 2^POW actors" << endl
<< endl; << endl;
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{ if (argc != 3) {
if (argc != 3)
{
usage(); usage();
return 1; return 1;
} }
......
...@@ -18,47 +18,39 @@ using namespace Theron; ...@@ -18,47 +18,39 @@ using namespace Theron;
int64_t t_max = 0; int64_t t_max = 0;
struct receiver : Actor struct receiver : Actor {
{
int64_t m_num; int64_t m_num;
void handler(const int64_t&, const Address from) void handler(const int64_t&, const Address from) {
{
if (++m_num == t_max) if (++m_num == t_max)
Send(t_max, from); Send(t_max, from);
} }
receiver() : m_num(0) receiver() : m_num(0) {
{
RegisterHandler(this, &receiver::handler); RegisterHandler(this, &receiver::handler);
} }
}; };
void send_sender(Framework& f, ActorRef ref, Address waiter, int64_t num) void send_sender(Framework& f, ActorRef ref, Address waiter, int64_t num) {
{
auto addr = ref.GetAddress(); auto addr = ref.GetAddress();
int64_t msg; int64_t msg;
for (int64_t i = 0; i < num; ++i) f.Send(msg, waiter, addr); for (int64_t i = 0; i < num; ++i) f.Send(msg, waiter, addr);
} }
void push_sender(Framework& f, ActorRef ref, Address waiter, int64_t num) void push_sender(Framework& f, ActorRef ref, Address waiter, int64_t num) {
{
int64_t msg; int64_t msg;
for (int64_t i = 0; i < num; ++i) ref.Push(msg, waiter); for (int64_t i = 0; i < num; ++i) ref.Push(msg, waiter);
} }
void usage() void usage() {
{
cout << "usage ('push'|'send') (num_threads) (num_messages)" << endl; cout << "usage ('push'|'send') (num_threads) (num_messages)" << endl;
exit(1); exit(1);
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{ if (argc != 4) {
if (argc != 4)
{
usage(); usage();
} }
enum { invalid_impl, push_impl, send_impl } impl = invalid_impl; enum { invalid_impl, push_impl, send_impl } impl = invalid_impl;
...@@ -74,8 +66,7 @@ int main(int argc, char** argv) ...@@ -74,8 +66,7 @@ int main(int argc, char** argv)
ActorRef aref(framework.CreateActor<receiver>()); ActorRef aref(framework.CreateActor<receiver>());
std::list<std::thread> threads; std::list<std::thread> threads;
auto impl_fun = (impl == push_impl) ? send_sender : push_sender; auto impl_fun = (impl == push_impl) ? send_sender : push_sender;
for (int64_t i = 0; i < num_sender; ++i) for (int64_t i = 0; i < num_sender; ++i) {
{
threads.push_back(std::thread(impl_fun, std::ref(framework), aref, receiverAddr, num_msgs)); threads.push_back(std::thread(impl_fun, std::ref(framework), aref, receiverAddr, num_msgs));
} }
r.Wait(); r.Wait();
......
...@@ -30,40 +30,32 @@ struct master_done { }; ...@@ -30,40 +30,32 @@ struct master_done { };
struct worker_done { }; struct worker_done { };
struct worker : Actor struct worker : Actor {
{ void handle_calc(const calc_msg& msg, Address from) {
void handle_calc(const calc_msg& msg, Address from)
{
factorize(msg.value); factorize(msg.value);
} }
void handle_master_done(const master_done&, Address from) void handle_master_done(const master_done&, Address from) {
{
Send(worker_done(), from); Send(worker_done(), from);
} }
worker() worker() {
{
RegisterHandler(this, &worker::handle_calc); RegisterHandler(this, &worker::handle_calc);
RegisterHandler(this, &worker::handle_master_done); RegisterHandler(this, &worker::handle_master_done);
} }
}; };
struct chain_link : Actor struct chain_link : Actor {
{
Address next; Address next;
void handle_token(const token_msg& msg, Address) void handle_token(const token_msg& msg, Address) {
{
Send(msg, next); Send(msg, next);
} }
typedef struct { Address next; } Parameters; typedef struct { Address next; } Parameters;
chain_link(const Parameters& p) : next(p.next) chain_link(const Parameters& p) : next(p.next) {
{
RegisterHandler(this, &chain_link::handle_token); RegisterHandler(this, &chain_link::handle_token);
} }
}; };
struct master : Actor struct master : Actor {
{
Address mc; Address mc;
int iteration; int iteration;
int max_iterations; int max_iterations;
...@@ -72,20 +64,17 @@ struct master : Actor ...@@ -72,20 +64,17 @@ struct master : Actor
int ring_size; int ring_size;
int initial_token_value; int initial_token_value;
std::vector<ActorRef> m_children; std::vector<ActorRef> m_children;
void new_ring() void new_ring() {
{
m_children.clear(); m_children.clear();
w.Push(calc_msg{s_task_n}, GetAddress()); w.Push(calc_msg{s_task_n}, GetAddress());
next = GetAddress(); next = GetAddress();
for (int i = 1; i < ring_size; ++i) for (int i = 1; i < ring_size; ++i) {
{
m_children.push_back(GetFramework().CreateActor<chain_link>(chain_link::Parameters{next})); m_children.push_back(GetFramework().CreateActor<chain_link>(chain_link::Parameters{next}));
next = m_children.back().GetAddress(); next = m_children.back().GetAddress();
} }
Send(token_msg{initial_token_value}, next); Send(token_msg{initial_token_value}, next);
} }
void handle_init(const init_msg& msg, Address) void handle_init(const init_msg& msg, Address) {
{
w = GetFramework().CreateActor<worker>(); w = GetFramework().CreateActor<worker>();
iteration = 0; iteration = 0;
ring_size = msg.ring_size; ring_size = msg.ring_size;
...@@ -93,40 +82,32 @@ struct master : Actor ...@@ -93,40 +82,32 @@ struct master : Actor
max_iterations = msg.iterations; max_iterations = msg.iterations;
new_ring(); new_ring();
} }
void handle_token(const token_msg& msg, Address) void handle_token(const token_msg& msg, Address) {
{ if (msg.value == 0) {
if (msg.value == 0) if (++iteration < max_iterations) {
{
if (++iteration < max_iterations)
{
new_ring(); new_ring();
} }
else else {
{
w.Push(master_done(), GetAddress()); w.Push(master_done(), GetAddress());
} }
} }
else else {
{
Send(token_msg{msg.value - 1}, next); Send(token_msg{msg.value - 1}, next);
} }
} }
void handle_worker_done(const worker_done&, Address) void handle_worker_done(const worker_done&, Address) {
{
Send(master_done(), mc); Send(master_done(), mc);
w = ActorRef::Null(); w = ActorRef::Null();
} }
typedef struct { Address mc; } Parameters; typedef struct { Address mc; } Parameters;
master(const Parameters& p) : mc(p.mc), iteration(0) master(const Parameters& p) : mc(p.mc), iteration(0) {
{
RegisterHandler(this, &master::handle_init); RegisterHandler(this, &master::handle_init);
RegisterHandler(this, &master::handle_token); RegisterHandler(this, &master::handle_token);
RegisterHandler(this, &master::handle_worker_done); RegisterHandler(this, &master::handle_worker_done);
} }
}; };
void usage() void usage() {
{
cout << "usage: mailbox_performance " cout << "usage: mailbox_performance "
"'send' (num rings) (ring size) " "'send' (num rings) (ring size) "
"(initial token value) (repetitions)" "(initial token value) (repetitions)"
...@@ -135,8 +116,7 @@ void usage() ...@@ -135,8 +116,7 @@ void usage()
exit(1); exit(1);
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{
if (argc != 6) usage(); if (argc != 6) usage();
if (strcmp("send", argv[1]) != 0) usage(); if (strcmp("send", argv[1]) != 0) usage();
int num_rings = rd<int>(argv[2]); int num_rings = rd<int>(argv[2]);
...@@ -146,12 +126,10 @@ int main(int argc, char** argv) ...@@ -146,12 +126,10 @@ int main(int argc, char** argv)
Receiver r; Receiver r;
Framework framework(num_cores()); Framework framework(num_cores());
std::vector<ActorRef> masters; std::vector<ActorRef> masters;
for (int i = 0; i < num_rings; ++i) for (int i = 0; i < num_rings; ++i) {
{
masters.push_back(framework.CreateActor<master>(master::Parameters{r.GetAddress()})); masters.push_back(framework.CreateActor<master>(master::Parameters{r.GetAddress()}));
} }
for (ActorRef& m : masters) for (ActorRef& m : masters) {
{
m.Push(init_msg{ring_size, inital_token_value, repetitions}, r.GetAddress()); m.Push(init_msg{ring_size, inital_token_value, repetitions}, r.GetAddress());
} }
for (int i = 0; i < num_rings; ++i) r.Wait(); for (int i = 0; i < num_rings; ++i) r.Wait();
......
...@@ -32,18 +32,35 @@ ...@@ -32,18 +32,35 @@
#define UTILITY_HPP #define UTILITY_HPP
#include <vector> #include <vector>
#include <string>
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <algorithm> #include <algorithm>
#include "boost/thread.hpp" inline std::vector<std::string> split(std::string const& str, char delim) {
std::vector<std::string> result;
std::stringstream strs{str};
std::string tmp;
while (std::getline(strs, tmp, delim)) result.push_back(tmp);
return result;
}
inline std::string join(std::vector<std::string> const& vec,
std::string const& delim = "") {
if (vec.empty()) return "";
auto result = vec.front();
for (auto i = vec.begin() + 1; i != vec.end(); ++i) {
result += delim;
result += *i;
}
return result;
}
template<typename T> template<typename T>
T rd(char const* cstr) T rd(char const* cstr) {
{
char* endptr = nullptr; char* endptr = nullptr;
T result = static_cast<T>(strtol(cstr, &endptr, 10)); T result = static_cast<T>(strtol(cstr, &endptr, 10));
if (endptr == nullptr || *endptr != '\0') if (endptr == nullptr || *endptr != '\0') {
{
std::string errstr; std::string errstr;
errstr += "\""; errstr += "\"";
errstr += cstr; errstr += cstr;
...@@ -53,18 +70,10 @@ T rd(char const* cstr) ...@@ -53,18 +70,10 @@ T rd(char const* cstr)
return result; return result;
} }
#ifdef __APPLE__ int num_cores() {
int num_cores()
{
return static_cast<int>(boost::thread::hardware_concurrency());
}
#else
int num_cores()
{
char cbuf[100]; char cbuf[100];
FILE* cmd = popen("/bin/cat /proc/cpuinfo | /bin/grep processor | /usr/bin/wc -l", "r"); FILE* cmd = popen("/bin/cat /proc/cpuinfo | /bin/grep processor | /usr/bin/wc -l", "r");
if (fgets(cbuf, 100, cmd) == 0) if (fgets(cbuf, 100, cmd) == 0) {
{
throw std::runtime_error("cannot determine number of cores"); throw std::runtime_error("cannot determine number of cores");
} }
pclose(cmd); pclose(cmd);
...@@ -73,26 +82,20 @@ int num_cores() ...@@ -73,26 +82,20 @@ int num_cores()
*i = '\0'; *i = '\0';
return rd<int>(cbuf); return rd<int>(cbuf);
} }
#endif
std::vector<uint64_t> factorize(uint64_t n) std::vector<uint64_t> factorize(uint64_t n) {
{
std::vector<uint64_t> result; std::vector<uint64_t> result;
if (n <= 3) if (n <= 3) {
{
result.push_back(n); result.push_back(n);
return std::move(result); return std::move(result);
} }
uint64_t d = 2; uint64_t d = 2;
while(d < n) while(d < n) {
{ if((n % d) == 0) {
if((n % d) == 0)
{
result.push_back(d); result.push_back(d);
n /= d; n /= d;
} }
else else {
{
d = (d == 2) ? 3 : (d + 2); d = (d == 2) ? 3 : (d + 2);
} }
} }
......
...@@ -4,16 +4,13 @@ ...@@ -4,16 +4,13 @@
using std::cout; using std::cout;
using std::endl; using std::endl;
struct pseudo_worker struct pseudo_worker {
{
int m_value; int m_value;
pseudo_worker() : m_value(0) { } pseudo_worker() : m_value(0) { }
void operator()() void operator()() {
{ for (;;) {
for (;;)
{
++m_value; ++m_value;
cout << "value = " << m_value << endl; cout << "value = " << m_value << endl;
cppa_fibre_yield(0); cppa_fibre_yield(0);
...@@ -21,22 +18,18 @@ struct pseudo_worker ...@@ -21,22 +18,18 @@ struct pseudo_worker
} }
}; };
void coroutine() void coroutine() {
{ auto pw = reinterpret_cast<pseudo_worker*>(cppa_fibre_init_switch_arg()); (*pw)();
auto pw = reinterpret_cast<pseudo_worker*>(cppa_fibre_init_switch_arg());
(*pw)();
} }
int main() int main() {
{
pseudo_worker pw; pseudo_worker pw;
cppa_fibre fself; cppa_fibre fself;
cppa_fibre fcoroutine; cppa_fibre fcoroutine;
cppa_fibre_ctor(&fself); cppa_fibre_ctor(&fself);
cppa_fibre_ctor2(&fcoroutine, coroutine, &pw); cppa_fibre_ctor2(&fcoroutine, coroutine, &pw);
cppa_fibre_initialize(&fcoroutine); cppa_fibre_initialize(&fcoroutine);
for (int i = 1; i < 11; ++i) for (int i = 1; i < 11; ++i) {
{
cout << "i = " << i << endl; cout << "i = " << i << endl;
cppa_fibre_switch(&fself, &fcoroutine); cppa_fibre_switch(&fself, &fcoroutine);
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -47,11 +47,9 @@ namespace cppa { ...@@ -47,11 +47,9 @@ namespace cppa {
/** /**
* @brief Base class for all event-based actor implementations. * @brief Base class for all event-based actor implementations.
*/ */
class abstract_event_based_actor : public detail::abstract_scheduled_actor class abstract_event_based_actor : public detail::abstract_scheduled_actor {
{
typedef detail::abstract_scheduled_actor super; typedef detail::abstract_scheduled_actor super;
typedef super::queue_node queue_node;
public: public:
...@@ -59,7 +57,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -59,7 +57,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
void dequeue(partial_function&); //override void dequeue(partial_function&); //override
void resume(util::fiber*, resume_callback* callback); //override void resume(util::fiber*, scheduler::callback* cb); //override
/** /**
* @brief Initializes the actor by defining an initial behavior. * @brief Initializes the actor by defining an initial behavior.
...@@ -71,16 +69,18 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -71,16 +69,18 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
*/ */
virtual void on_exit(); virtual void on_exit();
inline abstract_event_based_actor* attach_to_scheduler(scheduler* sched)
{
CPPA_REQUIRE(sched != nullptr);
m_scheduler = sched;
init();
return this;
}
protected: protected:
std::vector<std::unique_ptr<detail::recursive_queue_node> > m_cache;
enum handle_message_result {
drop_msg,
msg_handled,
cache_msg
};
auto handle_message(mailbox_element& node) -> handle_message_result;
abstract_event_based_actor(); abstract_event_based_actor();
// ownership flag + pointer // ownership flag + pointer
...@@ -89,9 +89,6 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -89,9 +89,6 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
std::vector<stack_element> m_loop_stack; std::vector<stack_element> m_loop_stack;
// current position in mailbox
mailbox_cache_type::iterator m_mailbox_pos;
// provoke compiler errors for usage of receive() and related functions // provoke compiler errors for usage of receive() and related functions
/** /**
...@@ -99,8 +96,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -99,8 +96,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
* does not accidently uses receive() instead of become(). * does not accidently uses receive() instead of become().
*/ */
template<typename... Args> template<typename... Args>
void receive(Args&&...) void receive(Args&&...) {
{
static_assert((sizeof...(Args) + 1) < 1, static_assert((sizeof...(Args) + 1) < 1,
"You shall not use receive in an event-based actor. " "You shall not use receive in an event-based actor. "
"Use become() instead."); "Use become() instead.");
...@@ -110,8 +106,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -110,8 +106,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Args>
void receive_loop(Args&&... args) void receive_loop(Args&&... args) {
{
receive(std::forward<Args>(args)...); receive(std::forward<Args>(args)...);
} }
...@@ -119,8 +114,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -119,8 +114,7 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Args>
void receive_while(Args&&... args) void receive_while(Args&&... args) {
{
receive(std::forward<Args>(args)...); receive(std::forward<Args>(args)...);
} }
...@@ -128,16 +122,10 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -128,16 +122,10 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Args>
void do_receive(Args&&... args) void do_receive(Args&&... args) {
{
receive(std::forward<Args>(args)...); receive(std::forward<Args>(args)...);
} }
private:
bool handle_message(queue_node& iter);
bool invoke_from_cache();
}; };
} // namespace cppa } // namespace cppa
......
...@@ -52,13 +52,19 @@ typedef std::uint32_t actor_id; ...@@ -52,13 +52,19 @@ typedef std::uint32_t actor_id;
/** /**
* @brief Base class for all actor implementations. * @brief Base class for all actor implementations.
*/ */
class actor : public channel class actor : public channel {
{
public: public:
~actor(); ~actor();
/**
* @brief Enqueues @p msg to the actor's mailbox and returns true if
* this actor is an scheduled actor that successfully changed
* its state to @p pending.
*/
virtual bool pending_enqueue(actor* sender, any_tuple msg);
/** /**
* @brief Attaches @p ptr to this actor. * @brief Attaches @p ptr to this actor.
* *
...@@ -150,7 +156,7 @@ class actor : public channel ...@@ -150,7 +156,7 @@ class actor : public channel
void link_to(intrusive_ptr<actor>&& other); void link_to(intrusive_ptr<actor>&& other);
/** /**
* @copydoc unlink_from(intrusive_ptr<actor>&) * @copydoc :unlink_from(intrusive_ptr<actor>&)
*/ */
void unlink_from(intrusive_ptr<actor>&& other); void unlink_from(intrusive_ptr<actor>&& other);
...@@ -217,23 +223,19 @@ typedef intrusive_ptr<actor> actor_ptr; ...@@ -217,23 +223,19 @@ typedef intrusive_ptr<actor> actor_ptr;
* inline and template member function implementations * * inline and template member function implementations *
******************************************************************************/ ******************************************************************************/
inline const process_information& actor::parent_process() const inline const process_information& actor::parent_process() const {
{
return *m_parent_process; return *m_parent_process;
} }
inline process_information_ptr actor::parent_process_ptr() const inline process_information_ptr actor::parent_process_ptr() const {
{
return m_parent_process; return m_parent_process;
} }
inline std::uint32_t actor::id() const inline std::uint32_t actor::id() const {
{
return m_id; return m_id;
} }
inline bool actor::is_proxy() const inline bool actor::is_proxy() const {
{
return m_is_proxy; return m_is_proxy;
} }
...@@ -241,39 +243,33 @@ template<typename T> ...@@ -241,39 +243,33 @@ template<typename T>
bool actor::attach(std::unique_ptr<T>&& ptr, bool actor::attach(std::unique_ptr<T>&& ptr,
typename std::enable_if< typename std::enable_if<
std::is_base_of<attachable,T>::value std::is_base_of<attachable,T>::value
>::type*) >::type*) {
{
return attach(static_cast<attachable*>(ptr.release())); return attach(static_cast<attachable*>(ptr.release()));
} }
template<class F> template<class F>
class functor_attachable : public attachable class functor_attachable : public attachable {
{
F m_functor; F m_functor;
public: public:
template<class FArg> template<class FArg>
functor_attachable(FArg&& arg) : m_functor(std::forward<FArg>(arg)) functor_attachable(FArg&& arg) : m_functor(std::forward<FArg>(arg)) {
{
} }
void actor_exited(std::uint32_t reason) void actor_exited(std::uint32_t reason) {
{
m_functor(reason); m_functor(reason);
} }
bool matches(const attachable::token&) bool matches(const attachable::token&) {
{
return false; return false;
} }
}; };
template<typename F> template<typename F>
bool actor::attach_functor(F&& ftor) bool actor::attach_functor(F&& ftor) {
{
typedef typename util::rm_ref<F>::type f_type; typedef typename util::rm_ref<F>::type f_type;
return attach(new functor_attachable<f_type>(std::forward<F>(ftor))); return attach(new functor_attachable<f_type>(std::forward<F>(ftor)));
} }
......
...@@ -45,8 +45,7 @@ class actor_proxy : public actor { }; ...@@ -45,8 +45,7 @@ class actor_proxy : public actor { };
#else // CPPA_DOCUMENTATION #else // CPPA_DOCUMENTATION
class actor_proxy : public abstract_actor<actor> class actor_proxy : public abstract_actor<actor> {
{
typedef abstract_actor<actor> super; typedef abstract_actor<actor> super;
...@@ -54,19 +53,17 @@ class actor_proxy : public abstract_actor<actor> ...@@ -54,19 +53,17 @@ class actor_proxy : public abstract_actor<actor>
actor_proxy(std::uint32_t mid, const process_information_ptr& parent); actor_proxy(std::uint32_t mid, const process_information_ptr& parent);
void enqueue(actor* sender, any_tuple&& msg); void enqueue(actor* sender, any_tuple msg);
void enqueue(actor* sender, const any_tuple& msg);
void link_to(intrusive_ptr<actor>& other); void link_to(intrusive_ptr<actor>& other);
// do not cause to send this actor an ":Unlink" message // do not cause to send this actor an "UNLINK" message
// to the "original" remote actor // to the "original" remote actor
void local_link_to(intrusive_ptr<actor>& other); void local_link_to(intrusive_ptr<actor>& other);
void unlink_from(intrusive_ptr<actor>& other); void unlink_from(intrusive_ptr<actor>& other);
// do not cause to send this actor an ":Unlink" message // do not cause to send this actor an "UNLINK" message
// to the "original" remote actor // to the "original" remote actor
void local_unlink_from(intrusive_ptr<actor>& other); void local_unlink_from(intrusive_ptr<actor>& other);
...@@ -76,8 +73,7 @@ class actor_proxy : public abstract_actor<actor> ...@@ -76,8 +73,7 @@ class actor_proxy : public abstract_actor<actor>
public: public:
void forward_message(const process_information_ptr&, void forward_message(const process_information_ptr&, actor*, any_tuple&&);
actor*, const any_tuple&);
}; };
......
...@@ -110,16 +110,14 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype); ...@@ -110,16 +110,14 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype);
*/ */
template<class C, class Parent, typename... Args> template<class C, class Parent, typename... Args>
std::pair<C Parent::*, util::abstract_uniform_type_info<C>*> std::pair<C Parent::*, util::abstract_uniform_type_info<C>*>
compound_member(C Parent::*c_ptr, const Args&... args) compound_member(C Parent::*c_ptr, const Args&... args) {
{
return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) }; return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) };
} }
// deals with getter returning a mutable reference // deals with getter returning a mutable reference
template<class C, class Parent, typename... Args> template<class C, class Parent, typename... Args>
std::pair<C& (Parent::*)(), util::abstract_uniform_type_info<C>*> std::pair<C& (Parent::*)(), util::abstract_uniform_type_info<C>*>
compound_member(C& (Parent::*c_ptr)(), const Args&... args) compound_member(C& (Parent::*c_ptr)(), const Args&... args) {
{
return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) }; return { c_ptr, new detail::default_uniform_type_info_impl<C>(args...) };
} }
...@@ -129,8 +127,7 @@ template<class Parent, typename GRes, ...@@ -129,8 +127,7 @@ template<class Parent, typename GRes,
std::pair<std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>, std::pair<std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>,
util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*> util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*>
compound_member(const std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>& gspair, compound_member(const std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>& gspair,
const Args&... args) const Args&... args) {
{
return { gspair, new detail::default_uniform_type_info_impl<typename util::rm_ref<GRes>::type>(args...) }; return { gspair, new detail::default_uniform_type_info_impl<typename util::rm_ref<GRes>::type>(args...) };
} }
...@@ -142,8 +139,7 @@ compound_member(const std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg) ...@@ -142,8 +139,7 @@ compound_member(const std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)
* otherwise @c false. * otherwise @c false.
*/ */
template<typename T, typename... Args> template<typename T, typename... Args>
inline bool announce(const Args&... args) inline bool announce(const Args&... args) {
{
return announce(typeid(T), return announce(typeid(T),
new detail::default_uniform_type_info_impl<T>(args...)); new detail::default_uniform_type_info_impl<T>(args...));
} }
......
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
#include <type_traits> #include <type_traits>
#include "cppa/cow_tuple.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp" #include "cppa/cow_ptr.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
#include "cppa/util/is_iterable.hpp" #include "cppa/util/is_iterable.hpp"
...@@ -51,8 +51,7 @@ namespace cppa { ...@@ -51,8 +51,7 @@ namespace cppa {
* @brief Describes a fixed-length copy-on-write tuple * @brief Describes a fixed-length copy-on-write tuple
* with elements of any type. * with elements of any type.
*/ */
class any_tuple class any_tuple {
{
public: public:
...@@ -129,15 +128,13 @@ class any_tuple ...@@ -129,15 +128,13 @@ class any_tuple
inline bool empty() const { return size() == 0; } inline bool empty() const { return size() == 0; }
template<typename T> template<typename T>
inline const T& get_as(size_t p) const inline const T& get_as(size_t p) const {
{
CPPA_REQUIRE(*(type_at(p)) == typeid(T)); CPPA_REQUIRE(*(type_at(p)) == typeid(T));
return *reinterpret_cast<T const*>(at(p)); return *reinterpret_cast<T const*>(at(p));
} }
template<typename T> template<typename T>
inline T& get_as_mutable(size_t p) inline T& get_as_mutable(size_t p) {
{
CPPA_REQUIRE(*(type_at(p)) == typeid(T)); CPPA_REQUIRE(*(type_at(p)) == typeid(T));
return *reinterpret_cast<T*>(mutable_at(p)); return *reinterpret_cast<T*>(mutable_at(p));
} }
...@@ -150,13 +147,11 @@ class any_tuple ...@@ -150,13 +147,11 @@ class any_tuple
inline const cow_ptr<detail::abstract_tuple>& vals() const { return m_vals; } inline const cow_ptr<detail::abstract_tuple>& vals() const { return m_vals; }
inline const cow_ptr<detail::abstract_tuple>& cvals() const { return m_vals; } inline const cow_ptr<detail::abstract_tuple>& cvals() const { return m_vals; }
inline std::type_info const* type_token() const inline std::type_info const* type_token() const {
{
return m_vals->type_token(); return m_vals->type_token();
} }
inline detail::tuple_impl_info impl_type() const inline detail::tuple_impl_info impl_type() const {
{
return m_vals->impl_type(); return m_vals->impl_type();
} }
...@@ -166,8 +161,7 @@ class any_tuple ...@@ -166,8 +161,7 @@ class any_tuple
util::is_iterable< util::is_iterable<
typename util::rm_ref<T>::type typename util::rm_ref<T>::type
>::value >::value
>::type* = 0) >::type* = 0) {
{
static constexpr bool can_optimize = std::is_reference<T>::value static constexpr bool can_optimize = std::is_reference<T>::value
&& !std::is_const<T>::value; && !std::is_const<T>::value;
std::integral_constant<bool, can_optimize> token; std::integral_constant<bool, can_optimize> token;
...@@ -180,8 +174,7 @@ class any_tuple ...@@ -180,8 +174,7 @@ class any_tuple
util::is_iterable< util::is_iterable<
typename util::rm_ref<T>::type typename util::rm_ref<T>::type
>::value == false >::value == false
>::type* = 0) >::type* = 0) {
{
typedef typename util::rm_ref<T>::type vtype; typedef typename util::rm_ref<T>::type vtype;
typedef typename detail::implicit_conversions<vtype>::type converted; typedef typename detail::implicit_conversions<vtype>::type converted;
static_assert(util::is_legal_tuple_type<converted>::value, static_assert(util::is_legal_tuple_type<converted>::value,
...@@ -194,8 +187,7 @@ class any_tuple ...@@ -194,8 +187,7 @@ class any_tuple
return any_tuple{simple_view(std::forward<T>(value), token)}; return any_tuple{simple_view(std::forward<T>(value), token)};
} }
void force_detach() void force_detach() {
{
m_vals.detach(); m_vals.detach();
} }
...@@ -211,22 +203,19 @@ class any_tuple ...@@ -211,22 +203,19 @@ class any_tuple
template<typename T> template<typename T>
static inline tup_ptr simple_view(T& value, static inline tup_ptr simple_view(T& value,
std::integral_constant<bool, true>) std::integral_constant<bool, true>) {
{
return new detail::tuple_view<T>(&value); return new detail::tuple_view<T>(&value);
} }
template<typename First, typename Second> template<typename First, typename Second>
static inline tup_ptr simple_view(std::pair<First, Second>& p, static inline tup_ptr simple_view(std::pair<First, Second>& p,
std::integral_constant<bool, true>) std::integral_constant<bool, true>) {
{
return new detail::tuple_view<First, Second>(&p.first, &p.second); return new detail::tuple_view<First, Second>(&p.first, &p.second);
} }
template<typename T> template<typename T>
static inline tup_ptr simple_view(T&& value, static inline tup_ptr simple_view(T&& value,
std::integral_constant<bool, false>) std::integral_constant<bool, false>) {
{
typedef typename util::rm_ref<T>::type vtype; typedef typename util::rm_ref<T>::type vtype;
typedef typename detail::implicit_conversions<vtype>::type converted; typedef typename detail::implicit_conversions<vtype>::type converted;
return new detail::tuple_vals<converted>(std::forward<T>(value)); return new detail::tuple_vals<converted>(std::forward<T>(value));
...@@ -234,23 +223,20 @@ class any_tuple ...@@ -234,23 +223,20 @@ class any_tuple
template<typename First, typename Second> template<typename First, typename Second>
static inline any_tuple view(std::pair<First, Second> p, static inline any_tuple view(std::pair<First, Second> p,
std::integral_constant<bool, false>) std::integral_constant<bool, false>) {
{
return new detail::tuple_vals<First, Second>(std::move(p.first), return new detail::tuple_vals<First, Second>(std::move(p.first),
std::move(p.second)); std::move(p.second));
} }
template<typename T> template<typename T>
static inline detail::abstract_tuple* container_view(T& value, static inline detail::abstract_tuple* container_view(T& value,
std::integral_constant<bool, true>) std::integral_constant<bool, true>) {
{
return new detail::container_tuple_view<T>(&value); return new detail::container_tuple_view<T>(&value);
} }
template<typename T> template<typename T>
static inline detail::abstract_tuple* container_view(T&& value, static inline detail::abstract_tuple* container_view(T&& value,
std::integral_constant<bool, false>) std::integral_constant<bool, false>) {
{
typedef typename util::rm_ref<T>::type ctype; typedef typename util::rm_ref<T>::type ctype;
return new detail::container_tuple_view<T>(new ctype(std::forward<T>(value)), true); return new detail::container_tuple_view<T>(new ctype(std::forward<T>(value)), true);
} }
...@@ -260,19 +246,22 @@ class any_tuple ...@@ -260,19 +246,22 @@ class any_tuple
/** /**
* @relates any_tuple * @relates any_tuple
*/ */
inline bool operator==(const any_tuple& lhs, const any_tuple& rhs) inline bool operator==(const any_tuple& lhs, const any_tuple& rhs) {
{
return lhs.equals(rhs); return lhs.equals(rhs);
} }
/** /**
* @relates any_tuple * @relates any_tuple
*/ */
inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) {
{
return !(lhs == rhs); return !(lhs == rhs);
} }
template<typename... Args>
inline any_tuple make_any_tuple(Args&&... args) {
return make_cow_tuple(std::forward<Args>(args)...);
}
} // namespace cppa } // namespace cppa
#endif // ANY_TUPLE_HPP #endif // ANY_TUPLE_HPP
...@@ -40,19 +40,16 @@ namespace cppa { ...@@ -40,19 +40,16 @@ namespace cppa {
*/ */
struct anything { }; struct anything { };
inline bool operator==(const anything&, const anything&) inline bool operator==(const anything&, const anything&) {
{
return true; return true;
} }
inline bool operator!=(const anything&, const anything&) inline bool operator!=(const anything&, const anything&) {
{
return false; return false;
} }
template<typename T> template<typename T>
struct is_anything struct is_anything {
{
static constexpr bool value = std::is_same<T, anything>::value; static constexpr bool value = std::is_same<T, anything>::value;
}; };
......
...@@ -45,8 +45,7 @@ std::string to_string(const atom_value& a); ...@@ -45,8 +45,7 @@ std::string to_string(const atom_value& a);
* @brief Creates an atom from given string literal. * @brief Creates an atom from given string literal.
*/ */
template<size_t Size> template<size_t Size>
constexpr atom_value atom(char const (&str) [Size]) constexpr atom_value atom(char const (&str) [Size]) {
{
// last character is the NULL terminator // last character is the NULL terminator
static_assert(Size <= 11, "only 10 characters are allowed"); static_assert(Size <= 11, "only 10 characters are allowed");
return static_cast<atom_value>(detail::atom_val(str, 0xF)); return static_cast<atom_value>(detail::atom_val(str, 0xF));
......
...@@ -39,8 +39,7 @@ namespace cppa { ...@@ -39,8 +39,7 @@ namespace cppa {
/** /**
* @brief Callback utility class. * @brief Callback utility class.
*/ */
class attachable class attachable {
{
attachable(const attachable&) = delete; attachable(const attachable&) = delete;
attachable& operator=(const attachable&) = delete; attachable& operator=(const attachable&) = delete;
...@@ -54,8 +53,7 @@ class attachable ...@@ -54,8 +53,7 @@ class attachable
/** /**
* @brief Represents a pointer to a value with its RTTI. * @brief Represents a pointer to a value with its RTTI.
*/ */
struct token struct token {
{
/** /**
* @brief Denotes the type of @c ptr. * @brief Denotes the type of @c ptr.
*/ */
...@@ -65,8 +63,7 @@ class attachable ...@@ -65,8 +63,7 @@ class attachable
*/ */
void const* ptr; void const* ptr;
inline token(const std::type_info& msubtype, void const* mptr) inline token(const std::type_info& msubtype, void const* mptr)
: subtype(msubtype), ptr(mptr) : subtype(msubtype), ptr(mptr) {
{
} }
}; };
......
...@@ -49,8 +49,7 @@ namespace cppa { ...@@ -49,8 +49,7 @@ namespace cppa {
/** /**
* @brief Describes the behavior of an actor. * @brief Describes the behavior of an actor.
*/ */
class behavior class behavior {
{
friend behavior operator,(partial_function&& lhs, behavior&& rhs); friend behavior operator,(partial_function&& lhs, behavior&& rhs);
...@@ -62,41 +61,42 @@ class behavior ...@@ -62,41 +61,42 @@ class behavior
behavior() = default; behavior() = default;
behavior(behavior&&) = default; behavior(behavior&&) = default;
inline behavior(partial_function&& fun) : m_fun(std::move(fun)) inline behavior(partial_function&& fun) : m_fun(std::move(fun)) {
{
} }
template<typename... Cases> template<typename... Cases>
behavior(const match_expr<Cases...>& me) : m_fun(me) { } behavior(const match_expr<Cases...>& me) : m_fun(me) { }
inline behavior(util::duration tout, std::function<void()>&& handler) inline behavior(util::duration tout, std::function<void()>&& handler)
: m_timeout(tout), m_timeout_handler(std::move(handler)) : m_timeout(tout), m_timeout_handler(std::move(handler)) {
{
} }
behavior& operator=(behavior&&) = default; behavior& operator=(behavior&&) = default;
//behavior& operator=(partial_function&& pfun) inline void handle_timeout() const {
//{
// m_fun = std::move(pfun);
// return *this;
//}
inline void handle_timeout() const
{
m_timeout_handler(); m_timeout_handler();
} }
inline const util::duration& timeout() const inline const util::duration& timeout() const {
{
return m_timeout; return m_timeout;
} }
inline partial_function& get_partial_function() inline partial_function& get_partial_function() {
{
return m_fun; return m_fun;
} }
inline bool operator()(any_tuple& value) {
return m_fun(value);
}
inline bool operator()(any_tuple const& value) {
return m_fun(value);
}
inline bool operator()(any_tuple&& value) {
return m_fun(std::move(value));
}
private: private:
// terminates recursion // terminates recursion
...@@ -110,21 +110,18 @@ class behavior ...@@ -110,21 +110,18 @@ class behavior
template<typename... Lhs> template<typename... Lhs>
behavior operator,(const match_expr<Lhs...>& lhs, behavior operator,(const match_expr<Lhs...>& lhs,
behavior&& rhs) behavior&& rhs) {
{
rhs.get_partial_function() = lhs; rhs.get_partial_function() = lhs;
return std::move(rhs); return std::move(rhs);
} }
template<typename Arg0> template<typename Arg0>
behavior bhvr_collapse(Arg0&& arg) behavior bhvr_collapse(Arg0&& arg) {
{
return {std::forward<Arg0>(arg)}; return {std::forward<Arg0>(arg)};
} }
template<typename Arg0, typename Arg1, typename... Args> template<typename Arg0, typename Arg1, typename... Args>
behavior bhvr_collapse(Arg0&& arg0, Arg1&& arg1, Args&&... args) behavior bhvr_collapse(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
{
return bhvr_collapse((std::forward<Arg0>(arg0), std::forward<Arg1>(arg1)), return bhvr_collapse((std::forward<Arg0>(arg0), std::forward<Arg1>(arg1)),
std::forward<Args>(args)...); std::forward<Args>(args)...);
} }
...@@ -134,8 +131,7 @@ typename std::enable_if< ...@@ -134,8 +131,7 @@ typename std::enable_if<
util::disjunction<std::is_same<behavior, Args>...>::value, util::disjunction<std::is_same<behavior, Args>...>::value,
behavior behavior
>::type >::type
match_expr_concat(Args&&... args) match_expr_concat(Args&&... args) {
{
return bhvr_collapse(std::forward<Args>(args)...); return bhvr_collapse(std::forward<Args>(args)...);
} }
...@@ -149,26 +145,22 @@ typename std::enable_if< ...@@ -149,26 +145,22 @@ typename std::enable_if<
>::value == false, >::value == false,
partial_function partial_function
>::type >::type
match_expr_concat(Args&&... args) match_expr_concat(Args&&... args) {
{
return mexpr_concat_convert(std::forward<Args>(args)...); return mexpr_concat_convert(std::forward<Args>(args)...);
} }
inline partial_function match_expr_concat(partial_function&& pfun) inline partial_function match_expr_concat(partial_function&& pfun) {
{
return std::move(pfun); return std::move(pfun);
} }
inline behavior match_expr_concat(behavior&& bhvr) inline behavior match_expr_concat(behavior&& bhvr) {
{
return std::move(bhvr); return std::move(bhvr);
} }
namespace detail { namespace detail {
template<typename... Ts> template<typename... Ts>
struct select_bhvr struct select_bhvr {
{
static constexpr bool timed = static constexpr bool timed =
util::disjunction<std::is_same<behavior, Ts>...>::value; util::disjunction<std::is_same<behavior, Ts>...>::value;
typedef typename util::if_else_c<timed, typedef typename util::if_else_c<timed,
......
...@@ -39,8 +39,7 @@ namespace cppa { ...@@ -39,8 +39,7 @@ namespace cppa {
* @brief Implements the deserializer interface with * @brief Implements the deserializer interface with
* a binary serialization protocol. * a binary serialization protocol.
*/ */
class binary_deserializer : public deserializer class binary_deserializer : public deserializer {
{
char const* pos; char const* pos;
char const* end; char const* end;
......
...@@ -42,8 +42,7 @@ namespace detail { class binary_writer; } ...@@ -42,8 +42,7 @@ namespace detail { class binary_writer; }
* @brief Implements the serializer interface with * @brief Implements the serializer interface with
* a binary serialization protocol. * a binary serialization protocol.
*/ */
class binary_serializer : public serializer class binary_serializer : public serializer {
{
friend class detail::binary_writer; friend class detail::binary_writer;
...@@ -72,12 +71,6 @@ class binary_serializer : public serializer ...@@ -72,12 +71,6 @@ class binary_serializer : public serializer
void write_tuple(size_t size, primitive_variant const* values); void write_tuple(size_t size, primitive_variant const* values);
/**
* @brief Takes the internal buffer and returns it.
*
*/
std::pair<size_t, char*> take_buffer();
/** /**
* @brief Returns the number of written bytes. * @brief Returns the number of written bytes.
*/ */
...@@ -88,6 +81,10 @@ class binary_serializer : public serializer ...@@ -88,6 +81,10 @@ class binary_serializer : public serializer
*/ */
char const* data() const; char const* data() const;
size_t sendable_size() const;
char const* sendable_data();
/** /**
* @brief Resets the internal buffer. * @brief Resets the internal buffer.
*/ */
......
...@@ -47,8 +47,7 @@ class any_tuple; ...@@ -47,8 +47,7 @@ class any_tuple;
* This interface describes an entity that can receive messages * This interface describes an entity that can receive messages
* and is implemented by {@link actor} and {@link group}. * and is implemented by {@link actor} and {@link group}.
*/ */
class channel : public ref_counted class channel : public ref_counted {
{
friend class actor; friend class actor;
friend class group; friend class group;
...@@ -60,9 +59,7 @@ class channel : public ref_counted ...@@ -60,9 +59,7 @@ class channel : public ref_counted
/** /**
* @brief Enqueues @p msg to the list of received messages. * @brief Enqueues @p msg to the list of received messages.
*/ */
virtual void enqueue(actor* sender, const any_tuple& msg) = 0; virtual void enqueue(actor* sender, any_tuple msg) = 0;
virtual void enqueue(actor* sender, any_tuple&& msg) = 0;
private: private:
......
...@@ -63,12 +63,13 @@ ...@@ -63,12 +63,13 @@
#elif defined(CPPA_GCC) #elif defined(CPPA_GCC)
# define CPPA_MEMORY_BARRIER() __sync_synchronize() # define CPPA_MEMORY_BARRIER() __sync_synchronize()
#else #else
# error Plattform and/or compiler not supportet # error Plattform and/or compiler not supported
#endif #endif
#ifdef CPPA_DEBUG
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#ifdef CPPA_DEBUG
#include <execinfo.h> #include <execinfo.h>
#define CPPA_REQUIRE__(stmt, file, line) \ #define CPPA_REQUIRE__(stmt, file, line) \
...@@ -87,4 +88,11 @@ ...@@ -87,4 +88,11 @@
#define CPPA_REQUIRE(unused) ((void) 0) #define CPPA_REQUIRE(unused) ((void) 0)
#endif // CPPA_DEBUG #endif // CPPA_DEBUG
#define CPPA_CRITICAL__(error, file, line) { \
printf("%s:%u: critical error: '%s'\n", file, line, error); \
exit(7); \
} ((void) 0)
#define CPPA_CRITICAL(error) CPPA_CRITICAL__(error, __FILE__, __LINE__)
#endif // CPPA_CONFIG_HPP #endif // CPPA_CONFIG_HPP
...@@ -46,8 +46,7 @@ namespace cppa { ...@@ -46,8 +46,7 @@ namespace cppa {
* {@link ref_counted}. * {@link ref_counted}.
*/ */
template<typename T> template<typename T>
class cow_ptr class cow_ptr {
{
public: public:
...@@ -63,35 +62,29 @@ class cow_ptr ...@@ -63,35 +62,29 @@ class cow_ptr
template<typename Y> template<typename Y>
cow_ptr(const cow_ptr<Y>& other) : m_ptr(const_cast<Y*>(other.get())) { } cow_ptr(const cow_ptr<Y>& other) : m_ptr(const_cast<Y*>(other.get())) { }
inline void swap(cow_ptr& other) inline void swap(cow_ptr& other) {
{
m_ptr.swap(other.m_ptr); m_ptr.swap(other.m_ptr);
} }
cow_ptr& operator=(cow_ptr&& other) cow_ptr& operator=(cow_ptr&& other) {
{
swap(other); swap(other);
return *this; return *this;
} }
cow_ptr& operator=(const cow_ptr& other) cow_ptr& operator=(const cow_ptr& other) {
{
cow_ptr tmp{other}; cow_ptr tmp{other};
swap(tmp); swap(tmp);
return *this; return *this;
} }
template<typename Y> template<typename Y>
cow_ptr& operator=(const cow_ptr<Y>& other) cow_ptr& operator=(const cow_ptr<Y>& other) {
{
cow_ptr tmp{other}; cow_ptr tmp{other};
swap(tmp); swap(tmp);
return *this; return *this;
} }
void detach() void detach() { (void) detached_ptr();
{
(void) detached_ptr();
} }
inline void reset(T* value = nullptr) { m_ptr.reset(value); } inline void reset(T* value = nullptr) { m_ptr.reset(value); }
...@@ -114,11 +107,9 @@ class cow_ptr ...@@ -114,11 +107,9 @@ class cow_ptr
intrusive_ptr<T> m_ptr; intrusive_ptr<T> m_ptr;
T* detached_ptr() T* detached_ptr() {
{
T* ptr = m_ptr.get(); T* ptr = m_ptr.get();
if (!ptr->unique()) if (!ptr->unique()) {
{
//T* new_ptr = detail::copy_of(ptr, copy_of_token()); //T* new_ptr = detail::copy_of(ptr, copy_of_token());
T* new_ptr = ptr->copy(); T* new_ptr = ptr->copy();
cow_ptr tmp(new_ptr); cow_ptr tmp(new_ptr);
......
...@@ -63,8 +63,7 @@ class local_actor; ...@@ -63,8 +63,7 @@ class local_actor;
* @brief A fixed-length copy-on-write cow_tuple. * @brief A fixed-length copy-on-write cow_tuple.
*/ */
template<typename... ElementTypes> template<typename... ElementTypes>
class cow_tuple class cow_tuple {
{
static_assert(sizeof...(ElementTypes) > 0, "tuple is empty"); static_assert(sizeof...(ElementTypes) > 0, "tuple is empty");
...@@ -94,24 +93,21 @@ class cow_tuple ...@@ -94,24 +93,21 @@ class cow_tuple
/** /**
* @brief Initializes each element with its default constructor. * @brief Initializes each element with its default constructor.
*/ */
cow_tuple() : m_vals(new data_type) cow_tuple() : m_vals(new data_type) {
{
} }
/** /**
* @brief Initializes the cow_tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
cow_tuple(const ElementTypes&... args) : m_vals(new data_type(args...)) cow_tuple(const ElementTypes&... args) : m_vals(new data_type(args...)) {
{
} }
/** /**
* @brief Initializes the cow_tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
cow_tuple(ElementTypes&&... args) : m_vals(new data_type(std::move(args)...)) cow_tuple(ElementTypes&&... args) : m_vals(new data_type(std::move(args)...)) {
{
} }
cow_tuple(cow_tuple&&) = default; cow_tuple(cow_tuple&&) = default;
...@@ -119,19 +115,16 @@ class cow_tuple ...@@ -119,19 +115,16 @@ class cow_tuple
cow_tuple& operator=(cow_tuple&&) = default; cow_tuple& operator=(cow_tuple&&) = default;
cow_tuple& operator=(const cow_tuple&) = default; cow_tuple& operator=(const cow_tuple&) = default;
inline static cow_tuple from(cow_ptr_type ptr) inline static cow_tuple from(cow_ptr_type ptr) {
{
return {priv_ctor{}, std::move(ptr)}; return {priv_ctor{}, std::move(ptr)};
} }
inline static cow_tuple from(cow_ptr_type ptr, inline static cow_tuple from(cow_ptr_type ptr,
const util::fixed_vector<size_t, num_elements>& mv) const util::fixed_vector<size_t, num_elements>& mv) {
{
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
} }
inline static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) inline static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
{
CPPA_REQUIRE(offset > 0); CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
} }
...@@ -139,24 +132,21 @@ class cow_tuple ...@@ -139,24 +132,21 @@ class cow_tuple
/** /**
* @brief Gets the size of this cow_tuple. * @brief Gets the size of this cow_tuple.
*/ */
inline size_t size() const inline size_t size() const {
{
return sizeof...(ElementTypes); return sizeof...(ElementTypes);
} }
/** /**
* @brief Gets a const pointer to the element at position @p p. * @brief Gets a const pointer to the element at position @p p.
*/ */
inline void const* at(size_t p) const inline void const* at(size_t p) const {
{
return m_vals->at(p); return m_vals->at(p);
} }
/** /**
* @brief Gets a mutable pointer to the element at position @p p. * @brief Gets a mutable pointer to the element at position @p p.
*/ */
inline void* mutable_at(size_t p) inline void* mutable_at(size_t p) {
{
return m_vals->mutable_at(p); return m_vals->mutable_at(p);
} }
...@@ -164,13 +154,11 @@ class cow_tuple ...@@ -164,13 +154,11 @@ class cow_tuple
* @brief Gets {@link uniform_type_info uniform type information} * @brief Gets {@link uniform_type_info uniform type information}
* of the element at position @p p. * of the element at position @p p.
*/ */
inline uniform_type_info const* type_at(size_t p) const inline uniform_type_info const* type_at(size_t p) const {
{
return m_vals->type_at(p); return m_vals->type_at(p);
} }
inline const cow_ptr<detail::abstract_tuple>& vals() const inline const cow_ptr<detail::abstract_tuple>& vals() const {
{
return m_vals; return m_vals;
} }
...@@ -180,8 +168,7 @@ template<typename TypeList> ...@@ -180,8 +168,7 @@ template<typename TypeList>
struct cow_tuple_from_type_list; struct cow_tuple_from_type_list;
template<typename... Types> template<typename... Types>
struct cow_tuple_from_type_list< util::type_list<Types...> > struct cow_tuple_from_type_list< util::type_list<Types...> > {
{
typedef cow_tuple<Types...> type; typedef cow_tuple<Types...> type;
}; };
...@@ -223,23 +210,20 @@ cow_tuple<Args...> make_cow_tuple(Args&&... args); ...@@ -223,23 +210,20 @@ cow_tuple<Args...> make_cow_tuple(Args&&... args);
#else #else
template<size_t N, typename... Types> template<size_t N, typename... Types>
const typename util::at<N, Types...>::type& get(const cow_tuple<Types...>& tup) const typename util::at<N, Types...>::type& get(const cow_tuple<Types...>& tup) {
{
typedef typename util::at<N, Types...>::type result_type; typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type const*>(tup.at(N)); return *reinterpret_cast<result_type const*>(tup.at(N));
} }
template<size_t N, typename... Types> template<size_t N, typename... Types>
typename util::at<N, Types...>::type& get_ref(cow_tuple<Types...>& tup) typename util::at<N, Types...>::type& get_ref(cow_tuple<Types...>& tup) {
{
typedef typename util::at<N, Types...>::type result_type; typedef typename util::at<N, Types...>::type result_type;
return *reinterpret_cast<result_type*>(tup.mutable_at(N)); return *reinterpret_cast<result_type*>(tup.mutable_at(N));
} }
template<typename... Args> template<typename... Args>
cow_tuple<typename detail::strip_and_convert<Args>::type...> cow_tuple<typename detail::strip_and_convert<Args>::type...>
make_cow_tuple(Args&&... args) make_cow_tuple(Args&&... args) {
{
return {std::forward<Args>(args)...}; return {std::forward<Args>(args)...};
} }
...@@ -254,8 +238,7 @@ make_cow_tuple(Args&&... args) ...@@ -254,8 +238,7 @@ make_cow_tuple(Args&&... args)
*/ */
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(const cow_tuple<LhsTypes...>& lhs, inline bool operator==(const cow_tuple<LhsTypes...>& lhs,
const cow_tuple<RhsTypes...>& rhs) const cow_tuple<RhsTypes...>& rhs) {
{
return util::compare_tuples(lhs, rhs); return util::compare_tuples(lhs, rhs);
} }
...@@ -268,8 +251,7 @@ inline bool operator==(const cow_tuple<LhsTypes...>& lhs, ...@@ -268,8 +251,7 @@ inline bool operator==(const cow_tuple<LhsTypes...>& lhs,
*/ */
template<typename... LhsTypes, typename... RhsTypes> template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(const cow_tuple<LhsTypes...>& lhs, inline bool operator!=(const cow_tuple<LhsTypes...>& lhs,
const cow_tuple<RhsTypes...>& rhs) const cow_tuple<RhsTypes...>& rhs) {
{
return !(lhs == rhs); return !(lhs == rhs);
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <tuple> #include <tuple>
#include <cstdint> #include <cstdint>
#include <functional>
#include <type_traits> #include <type_traits>
#include "cppa/on.hpp" #include "cppa/on.hpp"
...@@ -454,7 +455,7 @@ void unlink(actor_ptr& lhs, actor_ptr& rhs); ...@@ -454,7 +455,7 @@ void unlink(actor_ptr& lhs, actor_ptr& rhs);
* @ingroup ActorManagement * @ingroup ActorManagement
* @brief Adds a unidirectional @p monitor to @p whom. * @brief Adds a unidirectional @p monitor to @p whom.
* @note Each calls to @p monitor creates a new, independent monitor. * @note Each calls to @p monitor creates a new, independent monitor.
* @pre The calling actor receives a ":Down" message from @p whom when * @pre The calling actor receives a "DOWN" message from @p whom when
* it terminates. * it terminates.
*/ */
void monitor(actor_ptr& whom); void monitor(actor_ptr& whom);
...@@ -472,9 +473,8 @@ void demonitor(actor_ptr& whom); ...@@ -472,9 +473,8 @@ void demonitor(actor_ptr& whom);
* @brief Spans a new context-switching actor. * @brief Spans a new context-switching actor.
* @returns A pointer to the spawned {@link actor Actor}. * @returns A pointer to the spawned {@link actor Actor}.
*/ */
inline actor_ptr spawn(scheduled_actor* what) inline actor_ptr spawn(scheduled_actor* what) {
{ return get_scheduler()->spawn(what);
return get_scheduler()->spawn(what, scheduled);
} }
/** /**
...@@ -484,9 +484,8 @@ inline actor_ptr spawn(scheduled_actor* what) ...@@ -484,9 +484,8 @@ inline actor_ptr spawn(scheduled_actor* what)
* @returns A pointer to the spawned {@link actor Actor}. * @returns A pointer to the spawned {@link actor Actor}.
*/ */
template<scheduling_hint Hint> template<scheduling_hint Hint>
inline actor_ptr spawn(scheduled_actor* what) inline actor_ptr spawn(std::function<void()> what) {
{ return get_scheduler()->spawn(std::move(what), Hint);
return get_scheduler()->spawn(what, Hint);
} }
/** /**
...@@ -494,19 +493,45 @@ inline actor_ptr spawn(scheduled_actor* what) ...@@ -494,19 +493,45 @@ inline actor_ptr spawn(scheduled_actor* what)
* @brief Spans a new event-based actor. * @brief Spans a new event-based actor.
* @returns A pointer to the spawned {@link actor Actor}. * @returns A pointer to the spawned {@link actor Actor}.
*/ */
inline actor_ptr spawn(abstract_event_based_actor* what) inline actor_ptr spawn(std::function<void()> what) {
{ return get_scheduler()->spawn(std::move(what), scheduled);
return get_scheduler()->spawn(what);
} }
/** template<typename T>
struct spawn_fwd_ {
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
static inline T const& _(T const& arg) { return arg; }
};
template<>
struct spawn_fwd_<self_type> {
static inline actor_ptr _(self_type const&) { return self; }
};
template<typename F, typename Arg0, typename... Args>
inline actor_ptr spawn(F&& what, Arg0&& arg0, Args&&... args) {
return spawn(std::bind(std::move(what),
spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...));
}
template<scheduling_hint Hint, typename F, typename Arg0, typename... Args>
inline actor_ptr spawn(F&& what, Arg0&& arg0, Args&&... args) {
return spawn<Hint>(std::bind(std::move(what),
spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...));
}
/*
/ **
* @ingroup ActorManagement * @ingroup ActorManagement
* @brief Spawns a new actor that executes @p what with given arguments. * @brief Spawns a new actor that executes @p what with given arguments.
* @tparam Hint Hint to the scheduler for the best scheduling strategy. * @tparam Hint Hint to the scheduler for the best scheduling strategy.
* @param what Function or functor that the spawned Actor should execute. * @param what Function or functor that the spawned Actor should execute.
* @param args Arguments needed to invoke @p what. * @param args Arguments needed to invoke @p what.
* @returns A pointer to the spawned {@link actor actor}. * @returns A pointer to the spawned {@link actor actor}.
*/ * /
template<scheduling_hint Hint, typename F, typename... Args> template<scheduling_hint Hint, typename F, typename... Args>
auto //actor_ptr auto //actor_ptr
spawn(F&& what, const Args&... args) spawn(F&& what, const Args&... args)
...@@ -514,18 +539,17 @@ spawn(F&& what, const Args&... args) ...@@ -514,18 +539,17 @@ spawn(F&& what, const Args&... args)
!std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value !std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value
&& !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value, && !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value,
actor_ptr actor_ptr
>::type >::type {
{
typedef typename util::rm_ref<F>::type ftype; typedef typename util::rm_ref<F>::type ftype;
std::integral_constant<bool, std::is_function<ftype>::value> is_fun; std::integral_constant<bool, std::is_function<ftype>::value> is_fun;
auto ptr = detail::get_behavior(is_fun, std::forward<F>(what), args...); auto ptr = detail::get_behavior(is_fun, std::forward<F>(what), args...);
return get_scheduler()->spawn(ptr, Hint); return get_scheduler()->spawn(ptr, Hint);
} }
/** / **
* @ingroup ActorManagement * @ingroup ActorManagement
* @brief Alias for <tt>spawn<scheduled>(what, args...)</tt>. * @brief Alias for <tt>spawn<scheduled>(what, args...)</tt>.
*/ * /
template<typename F, typename... Args> template<typename F, typename... Args>
auto // actor_ptr auto // actor_ptr
spawn(F&& what, const Args&... args) spawn(F&& what, const Args&... args)
...@@ -533,10 +557,10 @@ spawn(F&& what, const Args&... args) ...@@ -533,10 +557,10 @@ spawn(F&& what, const Args&... args)
!std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value !std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value
&& !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value, && !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value,
actor_ptr actor_ptr
>::type >::type {
{
return spawn<scheduled>(std::forward<F>(what), args...); return spawn<scheduled>(std::forward<F>(what), args...);
} }
*/
#ifdef CPPA_DOCUMENTATION #ifdef CPPA_DOCUMENTATION
...@@ -562,32 +586,29 @@ channel_ptr& operator<<(channel_ptr& whom, const any_tuple& what); ...@@ -562,32 +586,29 @@ channel_ptr& operator<<(channel_ptr& whom, const any_tuple& what);
#else #else
template<class C, typename Arg0, typename... Args> template<class C, typename Arg0, typename... Args>
void send(intrusive_ptr<C>& whom, const Arg0& arg0, const Args&... args) void send(intrusive_ptr<C>& whom, const Arg0& arg0, const Args&... args) {
{
static_assert(std::is_base_of<channel, C>::value, "C is not a channel"); static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
if (whom) whom->enqueue(self, make_cow_tuple(arg0, args...)); if (whom) self->send_message(whom.get(), make_cow_tuple(arg0, args...));
} }
template<class C, typename Arg0, typename... Args> template<class C, typename Arg0, typename... Args>
void send(intrusive_ptr<C>&& whom, const Arg0& arg0, const Args&... args) void send(intrusive_ptr<C>&& whom, const Arg0& arg0, const Args&... args) {
{
static_assert(std::is_base_of<channel, C>::value, "C is not a channel"); static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
intrusive_ptr<C> tmp(std::move(whom)); intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, make_cow_tuple(arg0, args...)); send(tmp, arg0, args...);
} }
// matches "send(this, ...)" in event-based actors // matches "send(this, ...)" in event-based actors
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void send(local_actor* whom, const Arg0& arg0, const Args&... args) inline void send(local_actor* whom, const Arg0& arg0, const Args&... args) {
{ CPPA_REQUIRE(whom != nullptr);
whom->enqueue(whom, make_cow_tuple(arg0, args...)); whom->enqueue(whom, make_cow_tuple(arg0, args...));
} }
// matches send(self, ...); // matches send(self, ...);
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
inline void send(const self_type&, const Arg0& arg0, const Args&... args) inline void send(const self_type&, const Arg0& arg0, const Args&... args) {
{
send(static_cast<local_actor*>(self), arg0, args...); send(static_cast<local_actor*>(self), arg0, args...);
} }
...@@ -596,9 +617,8 @@ typename std::enable_if< ...@@ -596,9 +617,8 @@ typename std::enable_if<
std::is_base_of<channel, C>::value, std::is_base_of<channel, C>::value,
intrusive_ptr<C>& intrusive_ptr<C>&
>::type >::type
operator<<(intrusive_ptr<C>& whom, const any_tuple& what) operator<<(intrusive_ptr<C>& whom, const any_tuple& what) {
{ if (whom) self->send_message(whom.get(), what);
if (whom) whom->enqueue(self, what);
return whom; return whom;
} }
...@@ -607,10 +627,9 @@ typename std::enable_if< ...@@ -607,10 +627,9 @@ typename std::enable_if<
std::is_base_of<channel, C>::value, std::is_base_of<channel, C>::value,
intrusive_ptr<C> intrusive_ptr<C>
>::type >::type
operator<<(intrusive_ptr<C>&& whom, const any_tuple& what) operator<<(intrusive_ptr<C>&& whom, const any_tuple& what) {
{
intrusive_ptr<C> tmp(std::move(whom)); intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, what); tmp << what;
return std::move(tmp); return std::move(tmp);
} }
...@@ -619,9 +638,8 @@ typename std::enable_if< ...@@ -619,9 +638,8 @@ typename std::enable_if<
std::is_base_of<channel, C>::value, std::is_base_of<channel, C>::value,
intrusive_ptr<C>& intrusive_ptr<C>&
>::type >::type
operator<<(intrusive_ptr<C>& whom, any_tuple&& what) operator<<(intrusive_ptr<C>& whom, any_tuple&& what) {
{ if (whom) self->send_message(whom.get(), std::move(what));
if (whom) whom->enqueue(self, std::move(what));
return whom; return whom;
} }
...@@ -630,10 +648,9 @@ typename std::enable_if< ...@@ -630,10 +648,9 @@ typename std::enable_if<
std::is_base_of<channel, C>::value, std::is_base_of<channel, C>::value,
intrusive_ptr<C> intrusive_ptr<C>
>::type >::type
operator<<(intrusive_ptr<C>&& whom, any_tuple&& what) operator<<(intrusive_ptr<C>&& whom, any_tuple&& what) {
{
intrusive_ptr<C> tmp(std::move(whom)); intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, std::move(what)); tmp << std::move(what);
return std::move(tmp); return std::move(tmp);
} }
...@@ -648,8 +665,7 @@ const self_type& operator<<(const self_type& s, any_tuple&& what); ...@@ -648,8 +665,7 @@ const self_type& operator<<(const self_type& s, any_tuple&& what);
* @brief Sends a message to the sender of the last received message. * @brief Sends a message to the sender of the last received message.
*/ */
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void reply(const Arg0& arg0, const Args&... args) void reply(const Arg0& arg0, const Args&... args) {
{
send(self->last_sender(), arg0, args...); send(self->last_sender(), arg0, args...);
} }
...@@ -661,8 +677,7 @@ void reply(const Arg0& arg0, const Args&... args) ...@@ -661,8 +677,7 @@ void reply(const Arg0& arg0, const Args&... args)
* @param data Any number of values for the message content. * @param data Any number of values for the message content.
*/ */
template<typename Duration, typename... Data> template<typename Duration, typename... Data>
void future_send(actor_ptr whom, const Duration& rel_time, const Data&... data) void future_send(actor_ptr whom, const Duration& rel_time, const Data&... data) {
{
get_scheduler()->future_send(whom, rel_time, data...); get_scheduler()->future_send(whom, rel_time, data...);
} }
...@@ -672,8 +687,7 @@ void future_send(actor_ptr whom, const Duration& rel_time, const Data&... data) ...@@ -672,8 +687,7 @@ void future_send(actor_ptr whom, const Duration& rel_time, const Data&... data)
* @see future_send() * @see future_send()
*/ */
template<typename Duration, typename... Data> template<typename Duration, typename... Data>
void delayed_reply(const Duration& rel_time, Data const... data) void delayed_reply(const Duration& rel_time, Data const... data) {
{
future_send(self->last_sender(), rel_time, data...); future_send(self->last_sender(), rel_time, data...);
} }
...@@ -683,8 +697,7 @@ void delayed_reply(const Duration& rel_time, Data const... data) ...@@ -683,8 +697,7 @@ void delayed_reply(const Duration& rel_time, Data const... data)
* @warning This function will cause a deadlock if * @warning This function will cause a deadlock if
* called from multiple actors. * called from multiple actors.
*/ */
inline void await_all_others_done() inline void await_all_others_done() {
{
detail::actor_count_wait_until((self.unchecked() == nullptr) ? 0 : 1); detail::actor_count_wait_until((self.unchecked() == nullptr) ? 0 : 1);
} }
......
...@@ -45,8 +45,7 @@ class object; ...@@ -45,8 +45,7 @@ class object;
* @ingroup TypeSystem * @ingroup TypeSystem
* @brief Technology-independent deserialization interface. * @brief Technology-independent deserialization interface.
*/ */
class deserializer class deserializer {
{
deserializer(const deserializer&) = delete; deserializer(const deserializer&) = delete;
deserializer& operator=(const deserializer&) = delete; deserializer& operator=(const deserializer&) = delete;
......
...@@ -31,77 +31,74 @@ ...@@ -31,77 +31,74 @@
#ifndef SCHEDULED_ACTOR_HPP #ifndef SCHEDULED_ACTOR_HPP
#define SCHEDULED_ACTOR_HPP #define SCHEDULED_ACTOR_HPP
#include <iostream>
#include <atomic>
#include "cppa/any_tuple.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/abstract_actor.hpp" #include "cppa/abstract_actor.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/scheduled_actor.hpp"
#include "cppa/util/fiber.hpp" #include "cppa/util/fiber.hpp"
#include "cppa/detail/filter_result.hpp"
#include "cppa/intrusive/singly_linked_list.hpp" #include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp" #include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { class scheduler; }
namespace cppa { namespace detail { namespace cppa { namespace detail {
// A spawned, scheduled Actor. // A spawned, scheduled Actor.
class abstract_scheduled_actor : public abstract_actor<local_actor> class abstract_scheduled_actor : public abstract_actor<scheduled_actor> {
{
friend class intrusive::single_reader_queue<abstract_scheduled_actor>;
abstract_scheduled_actor* next; // intrusive next pointer
void enqueue_node(queue_node* node); typedef abstract_actor<scheduled_actor> super;
protected: protected:
std::atomic<int> m_state; std::atomic<int> m_state;
scheduler* m_scheduler;
filter_result filter_msg(any_tuple const& msg) {
typedef abstract_actor super; auto& arr = detail::static_types_array<atom_value, std::uint32_t>::arr;
typedef super::queue_node_guard queue_node_guard; if ( msg.size() == 2
typedef super::queue_node queue_node; && msg.type_at(0) == arr[0]
typedef super::queue_node_ptr queue_node_ptr; && msg.type_at(1) == arr[1]) {
auto v0 = *reinterpret_cast<const atom_value*>(msg.at(0));
enum dq_result auto v1 = *reinterpret_cast<const std::uint32_t*>(msg.at(1));
{ if (v0 == atom("EXIT")) {
dq_done, if (this->m_trap_exit == false) {
dq_indeterminate, if (v1 != exit_reason::normal) {
dq_timeout_occured quit(v1);
}; }
return normal_exit_signal;
enum filter_result }
{ }
normal_exit_signal, else if (v0 == atom(":Timeout")) {
expired_timeout_message, return (v1 == m_active_timeout_id) ? timeout_message
timeout_message, : expired_timeout_message;
ordinary_message }
}; }
return ordinary_message;
filter_result filter_msg(const any_tuple& msg); }
auto dq(queue_node& node, partial_function& rules) -> dq_result; bool has_pending_timeout() {
bool has_pending_timeout()
{
return m_has_pending_timeout_request; return m_has_pending_timeout_request;
} }
void request_timeout(const util::duration& d); void request_timeout(const util::duration& d) {
if (d.valid()) {
get_scheduler()->future_send(this, d, atom(":Timeout"), ++m_active_timeout_id);
m_has_pending_timeout_request = true;
}
}
void reset_timeout() void reset_timeout() {
{ if (m_has_pending_timeout_request) {
if (m_has_pending_timeout_request)
{
++m_active_timeout_id; ++m_active_timeout_id;
m_has_pending_timeout_request = false; m_has_pending_timeout_request = false;
} }
} }
private:
bool m_has_pending_timeout_request; bool m_has_pending_timeout_request;
std::uint32_t m_active_timeout_id; std::uint32_t m_active_timeout_id;
...@@ -110,44 +107,71 @@ class abstract_scheduled_actor : public abstract_actor<local_actor> ...@@ -110,44 +107,71 @@ class abstract_scheduled_actor : public abstract_actor<local_actor>
static constexpr int ready = 0x00; static constexpr int ready = 0x00;
static constexpr int done = 0x01; static constexpr int done = 0x01;
static constexpr int blocked = 0x02; static constexpr int blocked = 0x02;
static constexpr int pending = 0x03;
static constexpr int about_to_block = 0x04; static constexpr int about_to_block = 0x04;
abstract_scheduled_actor(int state = done); abstract_scheduled_actor(int state = done)
: super(true), m_state(state)
abstract_scheduled_actor(scheduler* sched); , m_has_pending_timeout_request(false)
, m_active_timeout_id(0) {
void quit(std::uint32_t reason); }
void enqueue(actor* sender, any_tuple&& msg); bool pending_enqueue(actor* sender, any_tuple msg) {
return enqueue_node(super::fetch_node(sender, std::move(msg)), pending);
}
void enqueue(actor* sender, const any_tuple& msg); void quit(std::uint32_t reason) {
this->cleanup(reason);
throw actor_exited(reason);
}
int compare_exchange_state(int expected, int new_value); void enqueue(actor* sender, any_tuple msg) {
enqueue_node(super::fetch_node(sender, std::move(msg)));
}
struct resume_callback int compare_exchange_state(int expected, int new_value) {
{ int e = expected;
virtual ~resume_callback(); do {
// called if an actor finished execution if (m_state.compare_exchange_weak(e, new_value)) {
virtual void exec_done() = 0; return new_value;
}; }
}
while (e == expected);
return e;
}
// from = calling worker private:
virtual void resume(util::fiber* from, resume_callback* callback) = 0;
}; bool enqueue_node(typename super::mailbox_element* node,
int target_state = ready) {
CPPA_REQUIRE(node->marked == false);
if (this->m_mailbox._push_back(node)) {
for (;;) {
int state = m_state.load();
switch (state) {
case blocked: {
if (m_state.compare_exchange_weak(state, target_state)) {
CPPA_REQUIRE(this->m_scheduler != nullptr);
if (target_state == ready) {
this->m_scheduler->enqueue(this);
}
return true;
}
break;
}
case about_to_block: {
if (m_state.compare_exchange_weak(state, ready)) {
return false;
}
break;
}
default: return false;
}
}
}
return false;
}
struct scheduled_actor_dummy : abstract_scheduled_actor
{
void resume(util::fiber*, resume_callback*);
void quit(std::uint32_t);
void dequeue(behavior&);
void dequeue(partial_function&);
void link_to(intrusive_ptr<actor>&);
void unlink_from(intrusive_ptr<actor>&);
bool establish_backlink(intrusive_ptr<actor>&);
bool remove_backlink(intrusive_ptr<actor>&);
void detach(const attachable::token&);
bool attach(attachable*);
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -44,14 +44,12 @@ ...@@ -44,14 +44,12 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
enum tuple_impl_info enum tuple_impl_info {
{
statically_typed, statically_typed,
dynamically_typed dynamically_typed
}; };
class abstract_tuple : public ref_counted class abstract_tuple : public ref_counted {
{
tuple_impl_info m_impl_type; tuple_impl_info m_impl_type;
...@@ -97,31 +95,26 @@ class abstract_tuple : public ref_counted ...@@ -97,31 +95,26 @@ class abstract_tuple : public ref_counted
}; };
struct full_eq_type struct full_eq_type {
{
constexpr full_eq_type() { } constexpr full_eq_type() { }
template<class Tuple> template<class Tuple>
inline bool operator()(const tuple_iterator<Tuple>& lhs, inline bool operator()(const tuple_iterator<Tuple>& lhs,
const tuple_iterator<Tuple>& rhs) const const tuple_iterator<Tuple>& rhs) const {
{
return lhs.type() == rhs.type() return lhs.type() == rhs.type()
&& lhs.type()->equals(lhs.value(), rhs.value()); && lhs.type()->equals(lhs.value(), rhs.value());
} }
}; };
struct types_only_eq_type struct types_only_eq_type {
{
constexpr types_only_eq_type() { } constexpr types_only_eq_type() { }
template<class Tuple> template<class Tuple>
inline bool operator()(const tuple_iterator<Tuple>& lhs, inline bool operator()(const tuple_iterator<Tuple>& lhs,
uniform_type_info const* rhs ) const uniform_type_info const* rhs ) const {
{
return lhs.type() == rhs; return lhs.type() == rhs;
} }
template<class Tuple> template<class Tuple>
inline bool operator()(uniform_type_info const* lhs, inline bool operator()(uniform_type_info const* lhs,
const tuple_iterator<Tuple>& rhs) const const tuple_iterator<Tuple>& rhs) const {
{
return lhs == rhs.type(); return lhs == rhs.type();
} }
}; };
......
...@@ -32,59 +32,64 @@ ...@@ -32,59 +32,64 @@
#define ACTOR_PROXY_CACHE_HPP #define ACTOR_PROXY_CACHE_HPP
#include <string> #include <string>
#include <limits>
#include <vector>
#include <functional> #include <functional>
#include "cppa/actor_proxy.hpp" #include "cppa/actor_proxy.hpp"
#include "cppa/process_information.hpp" #include "cppa/process_information.hpp"
namespace cppa { namespace detail { #include "cppa/util/shared_spinlock.hpp"
class actor_proxy_cache
{
public:
typedef std::tuple<std::uint32_t, // actor id #include "cppa/detail/thread.hpp"
std::uint32_t, // process id
process_information::node_id_type> // node id
key_tuple;
typedef std::function<void (actor_proxy_ptr&)> new_proxy_callback; namespace cppa { namespace detail {
private:
std::map<key_tuple, process_information_ptr> m_pinfos;
std::map<key_tuple, actor_proxy_ptr> m_proxies;
new_proxy_callback m_new_cb;
process_information_ptr get_pinfo(const key_tuple& key); class actor_proxy_cache {
public: public:
// this callback is called if a new proxy instance is created actor_proxy_ptr get(actor_id aid, std::uint32_t process_id,
template<typename F> process_information::node_id_type const& node_id);
void set_new_proxy_callback(F&& cb)
{ // @returns true if pptr was successfully removed, false otherwise
m_new_cb = std::forward<F>(cb); bool erase(const actor_proxy_ptr& pptr);
template<typename Fun>
void erase_all(process_information::node_id_type const& nid,
std::uint32_t process_id,
Fun fun) {
key_tuple lb{nid, process_id, std::numeric_limits<actor_id>::min()};
key_tuple ub{nid, process_id, std::numeric_limits<actor_id>::max()}; {
lock_guard<util::shared_spinlock> guard{m_lock};
auto e = m_entries.end();
auto first = m_entries.lower_bound(lb);
if (first != e) {
auto last = m_entries.upper_bound(ub);
for (auto i = first; i != last; ++i) {
fun(i->second);
}
m_entries.erase(first, last);
}
}
} }
actor_proxy_ptr get(const key_tuple& key); private:
void add(actor_proxy_ptr& pptr); typedef std::tuple<process_information::node_id_type, // node id
std::uint32_t, // process id
actor_id> // (remote) actor id
key_tuple;
size_t size() const; struct key_tuple_less {
bool operator()(key_tuple const& lhs, key_tuple const& rhs) const;
};
void erase(const actor_proxy_ptr& pptr); util::shared_spinlock m_lock;
std::map<key_tuple, actor_proxy_ptr, key_tuple_less> m_entries;
actor_proxy_ptr get_impl(const key_tuple& key);
template<typename F>
void for_each(F&& fun)
{
for (auto i = m_proxies.begin(); i != m_proxies.end(); ++i)
{
fun(i->second);
}
}
}; };
......
...@@ -42,8 +42,7 @@ ...@@ -42,8 +42,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
class actor_registry class actor_registry {
{
public: public:
......
...@@ -38,22 +38,13 @@ ...@@ -38,22 +38,13 @@
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/detail/channel.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
class addressed_message class addressed_message {
{
public: public:
addressed_message(const actor_ptr& from, addressed_message(actor_ptr from, channel_ptr to, any_tuple ut);
const channel_ptr& to,
const any_tuple& ut);
addressed_message(const actor_ptr& from,
const channel_ptr& to,
any_tuple&& ut);
addressed_message() = default; addressed_message() = default;
addressed_message(addressed_message&&) = default; addressed_message(addressed_message&&) = default;
...@@ -61,38 +52,31 @@ class addressed_message ...@@ -61,38 +52,31 @@ class addressed_message
addressed_message& operator=(addressed_message&&) = default; addressed_message& operator=(addressed_message&&) = default;
addressed_message& operator=(const addressed_message&) = default; addressed_message& operator=(const addressed_message&) = default;
inline actor_ptr& sender() inline actor_ptr& sender() {
{
return m_sender; return m_sender;
} }
inline const actor_ptr& sender() const inline const actor_ptr& sender() const {
{
return m_sender; return m_sender;
} }
inline channel_ptr& receiver() inline channel_ptr& receiver() {
{
return m_receiver; return m_receiver;
} }
inline const channel_ptr& receiver() const inline const channel_ptr& receiver() const {
{
return m_receiver; return m_receiver;
} }
inline any_tuple& content() inline any_tuple& content() {
{
return m_content; return m_content;
} }
inline const any_tuple& content() const inline const any_tuple& content() const {
{
return m_content; return m_content;
} }
inline bool empty() const inline bool empty() const {
{
return m_content.empty(); return m_content.empty();
} }
...@@ -106,8 +90,7 @@ class addressed_message ...@@ -106,8 +90,7 @@ class addressed_message
bool operator==(const addressed_message& lhs, const addressed_message& rhs); bool operator==(const addressed_message& lhs, const addressed_message& rhs);
inline bool operator!=(const addressed_message& lhs, const addressed_message& rhs) inline bool operator!=(const addressed_message& lhs, const addressed_message& rhs) {
{
return !(lhs == rhs); return !(lhs == rhs);
} }
......
...@@ -34,8 +34,7 @@ ...@@ -34,8 +34,7 @@
namespace cppa { namespace detail { namespace { namespace cppa { namespace detail { namespace {
// encodes ASCII characters to 6bit encoding // encodes ASCII characters to 6bit encoding
constexpr char encoding_table[] = constexpr char encoding_table[] = {
{
/* ..0 ..1 ..2 ..3 ..4 ..5 ..6 ..7 ..8 ..9 ..A ..B ..C ..D ..E ..F */ /* ..0 ..1 ..2 ..3 ..4 ..5 ..6 ..7 ..8 ..9 ..A ..B ..C ..D ..E ..F */
/* 0.. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0.. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 1.. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1.. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
...@@ -52,13 +51,11 @@ constexpr char decoding_table[] = " 0123456789" ...@@ -52,13 +51,11 @@ constexpr char decoding_table[] = " 0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ_" "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
"abcdefghijklmnopqrstuvwxyz"; "abcdefghijklmnopqrstuvwxyz";
constexpr std::uint64_t next_interim(std::uint64_t current, size_t char_code) constexpr std::uint64_t next_interim(std::uint64_t current, size_t char_code) {
{
return (current << 6) | encoding_table[(char_code <= 0x7F) ? char_code : 0]; return (current << 6) | encoding_table[(char_code <= 0x7F) ? char_code : 0];
} }
constexpr std::uint64_t atom_val(char const* cstr, std::uint64_t interim = 0) constexpr std::uint64_t atom_val(char const* cstr, std::uint64_t interim = 0) {
{
return (*cstr == '\0') ? interim return (*cstr == '\0') ? interim
: atom_val(cstr + 1, : atom_val(cstr + 1,
next_interim(interim, next_interim(interim,
......
...@@ -37,50 +37,42 @@ ...@@ -37,50 +37,42 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename T> template<typename T>
struct boxed struct boxed {
{
typedef util::wrapped<T> type; typedef util::wrapped<T> type;
}; };
template<typename T> template<typename T>
struct boxed< util::wrapped<T> > struct boxed< util::wrapped<T> > {
{
typedef util::wrapped<T> type; typedef util::wrapped<T> type;
}; };
template<> template<>
struct boxed<anything> struct boxed<anything> {
{
typedef anything type; typedef anything type;
}; };
template<typename T> template<typename T>
struct is_boxed struct is_boxed {
{
static constexpr bool value = false; static constexpr bool value = false;
}; };
template<typename T> template<typename T>
struct is_boxed< util::wrapped<T> > struct is_boxed< util::wrapped<T> > {
{
static constexpr bool value = true; static constexpr bool value = true;
}; };
template<typename T> template<typename T>
struct is_boxed<util::wrapped<T>()> struct is_boxed<util::wrapped<T>()> {
{
static constexpr bool value = true; static constexpr bool value = true;
}; };
template<typename T> template<typename T>
struct is_boxed<util::wrapped<T>(&)()> struct is_boxed<util::wrapped<T>(&)()> {
{
static constexpr bool value = true; static constexpr bool value = true;
}; };
template<typename T> template<typename T>
struct is_boxed<util::wrapped<T>(*)()> struct is_boxed<util::wrapped<T>(*)()> {
{
static constexpr bool value = true; static constexpr bool value = true;
}; };
......
This diff is collapsed.
...@@ -38,8 +38,7 @@ namespace cppa { class message; } ...@@ -38,8 +38,7 @@ namespace cppa { class message; }
namespace cppa { namespace detail { namespace cppa { namespace detail {
// public part of the actor interface // public part of the actor interface
struct channel : ref_counted struct channel : ref_counted {
{
virtual void enqueue_msg(const message& msg) = 0; virtual void enqueue_msg(const message& msg) = 0;
}; };
......
...@@ -41,8 +41,7 @@ ...@@ -41,8 +41,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<class Container> template<class Container>
class container_tuple_view : public abstract_tuple class container_tuple_view : public abstract_tuple {
{
typedef abstract_tuple super; typedef abstract_tuple super;
...@@ -51,40 +50,34 @@ class container_tuple_view : public abstract_tuple ...@@ -51,40 +50,34 @@ class container_tuple_view : public abstract_tuple
typedef typename Container::value_type value_type; typedef typename Container::value_type value_type;
container_tuple_view(Container* c, bool take_ownership = false) container_tuple_view(Container* c, bool take_ownership = false)
: super(tuple_impl_info::dynamically_typed), m_ptr(c) : super(tuple_impl_info::dynamically_typed), m_ptr(c) {
{
CPPA_REQUIRE(c != nullptr); CPPA_REQUIRE(c != nullptr);
if (!take_ownership) m_ptr.get_deleter().disable(); if (!take_ownership) m_ptr.get_deleter().disable();
} }
size_t size() const size_t size() const {
{
return m_ptr->size(); return m_ptr->size();
} }
abstract_tuple* copy() const abstract_tuple* copy() const {
{
return new container_tuple_view{new Container(*m_ptr), true}; return new container_tuple_view{new Container(*m_ptr), true};
} }
void const* at(size_t pos) const void const* at(size_t pos) const {
{
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
auto i = m_ptr->begin(); auto i = m_ptr->begin();
std::advance(i, pos); std::advance(i, pos);
return &(*i); return &(*i);
} }
void* mutable_at(size_t pos) void* mutable_at(size_t pos) {
{
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
auto i = m_ptr->begin(); auto i = m_ptr->begin();
std::advance(i, pos); std::advance(i, pos);
return &(*i); return &(*i);
} }
uniform_type_info const* type_at(size_t) const uniform_type_info const* type_at(size_t) const {
{
return static_types_array<value_type>::arr[0]; return static_types_array<value_type>::arr[0];
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -34,8 +34,7 @@ ...@@ -34,8 +34,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename T> template<typename T>
class disablable_delete class disablable_delete {
{
bool m_enabled; bool m_enabled;
...@@ -45,8 +44,7 @@ class disablable_delete ...@@ -45,8 +44,7 @@ class disablable_delete
inline void disable() { m_enabled = false; } inline void disable() { m_enabled = false; }
inline void operator()(T* ptr) inline void operator()(T* ptr) {
{
if (m_enabled) delete ptr; if (m_enabled) delete ptr;
} }
......
...@@ -35,8 +35,7 @@ ...@@ -35,8 +35,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct empty_tuple : abstract_tuple struct empty_tuple : abstract_tuple {
{
using abstract_tuple::const_iterator; using abstract_tuple::const_iterator;
......
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.
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