[boost] Is there any interest in a library for actor programming?

128 views
Skip to first unread message

Charousset, Dominik

unread,
May 17, 2013, 5:26:24 PM5/17/13
to bo...@lists.boost.org
Hi,

is there any interest in a library for actor programming?

The library we've developed is a C++11 open source library named "libcppa". It is currently released under LGPL2, but re-releasing the library under the boost license is not an issue. You'll find all important links and ressources either under http://libcppa.org or on the GitHub project page: https://github.com/Neverlord/libcppa, including a user manual as HTML or PDF. We've also submitted a paper to the C++Now conference.

What is actor programming? For those of you who aren't yet familiar with the actor model: actors basically represent tasks or services that communicate via message passing. In libcppa, actors are very lightweight (you can spawn literally millions of them) and scheduled cooperatively using a thread pool (although actors are allowed to opt-out of the cooperative scheduling). Some of the main strengths of this programming paradigm are: (1) network transparency, (2) race conditions are avoided by design, (3) a strong failure model that enables developers to build reliable distributed systems, and (4) the actor model addresses both concurrency (multiple actors on one host) and distribution (any number of actors on any number of hosts).

Here's the classical hello world example:

----------------------------------------------------------------------------------
#include <string>
#include <iostream>
#include "cppa/cppa.hpp"

using namespace std;
using namespace cppa;

void mirror() {
// wait for messages
become (
// invoke this lambda expression if we receive a string
on_arg_match >> [](const string& what) {
// prints "Hello World!" via aout (thread-safe cout wrapper)
aout << what << endl;
// replies "!dlroW olleH"
reply(string(what.rbegin(), what.rend()));
// terminates this actor ('become' otherwise loops forever)
self->quit();
}
);
}

void hello_world(const actor_ptr& buddy) {
// send "Hello World!" to our buddy ...
sync_send(buddy, "Hello World!").then(
// ... and wait for a response
on_arg_match >> [](const string& what) {
// prints "!dlroW olleH"
aout << what << endl;
}
);
}

int main() {
// create a new actor that calls 'mirror()'
auto mirror_actor = spawn(mirror);
// create another actor that calls 'hello_world(mirror_actor)'
spawn(hello_world, mirror_actor);
// wait until all other actors we have spawned are done
await_all_others_done();
// run cleanup code before exiting main
shutdown();
}
----------------------------------------------------------------------------------


A message is simply a tuple of values that is pattern matched at the receiver. For example, " on_arg_match >> [](const string& what) {...}" defines a message handler that is called whenever a tuple with one single string element arrives. "on_arg_match" simply defines a pattern that matches the signature of the given lambda.

Please have a look at the examples folder on GitHub (https://github.com/Neverlord/libcppa/tree/master/examples) or at the user manual (http://neverlord.github.io/libcppa/manual/) if you want to see more examples.


Best regards,
Dominik Charousset

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Bjorn Reese

unread,
May 18, 2013, 10:15:36 AM5/18/13
to bo...@lists.boost.org
On 05/17/2013 11:26 PM, Charousset, Dominik wrote:

> What is actor programming? For those of you who aren't yet familiar with the actor model: actors basically represent tasks or services that communicate via message passing. In libcppa, actors are very lightweight (you can spawn literally millions of them) and scheduled cooperatively using a thread pool (although actors are allowed to opt-out of the cooperative scheduling). Some of the main strengths of this programming paradigm are: (1) network transparency, (2) race conditions are avoided by design, (3) a strong failure model that enables developers to build reliable distributed systems, and (4) the actor model addresses both concurrency (multiple actors on one host) and distribution (any number of actors on any number of hosts).

Have you defined a network protocol? If so, can I plug in my own in
case I need to integrate with an existing messaging middleware such as
ZeroMQ or DDS?

Charousset, Dominik

unread,
May 18, 2013, 10:59:27 AM5/18/13
to bo...@lists.boost.org
> Have you defined a network protocol? If so, can I plug in my own in case I need to integrate with an existing messaging middleware such as ZeroMQ or DDS?

The default protocol is a simple, lightweight binary protocol. However, you can provide your own protocol by implementing cppa::network::protocol (you will most likely have to implement some other classes like cppa::actor_proxy as well).

And this is how you could use a custom protocol:

get_middleman()->add_protocol(new my_fancy_protocol); // registers your new protocol the libcppa's network stack

auto fancy_protocol = get_middleman()->protocol(atom("fancy")); // access custom protocol

fancy_protocol->publish(self, {host,port}); // make actor available to other peers

auto buddy = fancy_protocol->remote_actor({host,port}); // talk to a remote actor using the fancy protocol


Of course you would want to hide this for your users in real code with functions like fancy_publish(...) and fancy_remote_actor(...).

Vicente J. Botet Escriba

unread,
May 18, 2013, 5:54:51 PM5/18/13
to bo...@lists.boost.org
Le 17/05/13 23:26, Charousset, Dominik a écrit :
> Hi,
>
> is there any interest in a library for actor programming?
>
> The library we've developed is a C++11 open source library named "libcppa". It is currently released under LGPL2, but re-releasing the library under the boost license is not an issue. You'll find all important links and ressources either under http://libcppa.org or on the GitHub project page: https://github.com/Neverlord/libcppa, including a user manual as HTML or PDF. We've also submitted a paper to the C++Now conference.
>
> What is actor programming? For those of you who aren't yet familiar with the actor model: actors basically represent tasks or services that communicate via message passing. In libcppa, actors are very lightweight (you can spawn literally millions of them) and scheduled cooperatively using a thread pool (although actors are allowed to opt-out of the cooperative scheduling). Some of the main strengths of this programming paradigm are: (1) network transparency, (2) race conditions are avoided by design, (3) a strong failure model that enables developers to build reliable distributed systems, and (4) the actor model addresses both concurrency (multiple actors on one host) and distribution (any number of actors on any number of hosts).
>
> A message is simply a tuple of values that is pattern matched at the receiver. For example, " on_arg_match >> [](const string& what) {...}" defines a message handler that is called whenever a tuple with one single string element arrives. "on_arg_match" simply defines a pattern that matches the signature of the given lambda.
>
> Please have a look at the examples folder on GitHub (https://github.com/Neverlord/libcppa/tree/master/examples) or at the user manual (http://neverlord.github.io/libcppa/manual/) if you want to see more examples.
>
Hi,

This is really a lot of good and interesting work on your library.

Moving all the library to the Boost standards would be quite a lot of
work however. Replacing some classes by the corresponding Boost ones.

I would see already several Boost libraries in your libcppa library:
* Atoms
* CowTuples
* Dynamically Typed Tuples - type erased tuples
* Tuples Pattern matching
* Actors

There is something that I would like to see on the Actors architecture.
The interface of an actor is not really defined other than by their
behavior. It can receive any dynamic tuple. This is a lot. I would like
a more statically typed interface. An actor could define statically the
kind of messages/signals it is allowed to handle and make it part of the
interface.

While I find your tuple pattern matching quite interesting I'm looking
for a more low level interface for the Actors part, that doesn't force
to use tuples. It provides just a way to identify uniquely the message
type and the associated data.

on<messageType> >> [](associatedDateType const& data) { /*...*/},

Of course the user could already use {atom("messageName"),
associatedDataType()}, but this forces the user to use a cow data type
that could be too costly for some applications. As most the
communications are point to point, the ownership of the message is quite
clear in these cases, so no need for COW.

Last but not least your library works only on some C++11 compilers. I
have nothing against having C++11 specific libraries in Boost, even the
opposite (I proposed it long time ago) but the fact is that currently,
the Boost libraries provide at least a minimal interface on C++98
compilers. I don't know what the Boost community thinks about this point
now.

Welcome, keep up the good work and good luck with your library,
Vicente

Dominik Charousset

unread,
May 19, 2013, 7:48:41 PM5/19/13
to bo...@lists.boost.org

On May 18, 2013, at 11:54 PM, "Vicente J. Botet Escriba" <vicent...@wanadoo.fr> wrote:

> Le 17/05/13 23:26, Charousset, Dominik a écrit :
>> Hi,
>>
>> is there any interest in a library for actor programming?
>>
>> The library we've developed is a C++11 open source library named "libcppa". It is currently released under LGPL2, but re-releasing the library under the boost license is not an issue. You'll find all important links and ressources either under http://libcppa.org or on the GitHub project page: https://github.com/Neverlord/libcppa, including a user manual as HTML or PDF. We've also submitted a paper to the C++Now conference.
>>
>> What is actor programming? For those of you who aren't yet familiar with the actor model: actors basically represent tasks or services that communicate via message passing. In libcppa, actors are very lightweight (you can spawn literally millions of them) and scheduled cooperatively using a thread pool (although actors are allowed to opt-out of the cooperative scheduling). Some of the main strengths of this programming paradigm are: (1) network transparency, (2) race conditions are avoided by design, (3) a strong failure model that enables developers to build reliable distributed systems, and (4) the actor model addresses both concurrency (multiple actors on one host) and distribution (any number of actors on any number of hosts).
>>
>> A message is simply a tuple of values that is pattern matched at the receiver. For example, " on_arg_match >> [](const string& what) {...}" defines a message handler that is called whenever a tuple with one single string element arrives. "on_arg_match" simply defines a pattern that matches the signature of the given lambda.
>>
>> Please have a look at the examples folder on GitHub (https://github.com/Neverlord/libcppa/tree/master/examples) or at the user manual (http://neverlord.github.io/libcppa/manual/) if you want to see more examples.
>>
> Hi,
>
> This is really a lot of good and interesting work on your library.

Thanks.


> Moving all the library to the Boost standards would be quite a lot of
> work however. Replacing some classes by the corresponding Boost ones.
>
> I would see already several Boost libraries in your libcppa library:
> * Atoms
> * CowTuples
> * Dynamically Typed Tuples - type erased tuples
> * Tuples Pattern matching
> * Actors

I agree. At least separating pattern matching (for dynamically typed tuples) from the actual actor implementation would make sense.


> There is something that I would like to see on the Actors architecture.
> The interface of an actor is not really defined other than by their
> behavior. It can receive any dynamic tuple. This is a lot. I would like
> a more statically typed interface. An actor could define statically the
> kind of messages/signals it is allowed to handle and make it part of the
> interface.

There was some discussion about this topic after the talk at the C++Now conference. I do agree that it is desirable to enable the compiler to verify the correctness of actor programs at compile time. However, in order to be able to ensure the correctness of a program, one would have to define not only all possible input messages, but the response types depending on the input as well. Consider this example:

actor_type<reacts_to<atom("add"),int,int>::with<int>,
reacts_to<atom("hello")>::with<std::string>> my_actor() {
return (
on(atom("add"), arg_match) >> [](int a, int b) {
return a+b;
},
on(atom("hello")) >> [] {
return "world";
}
);
}

It's easy to check whether the interface is fulfilled. On each send, the compiler is able to check whether the given message matches actor_type and if the sender of the message (more precisely, the receiver of the response message) can handle the result. However, an approach like this cannot allow an actor to change its behavior. Hence, something as simple as the classical dining philosophers example (https://github.com/Neverlord/libcppa/blob/master/examples/message_passing/dining_philosophers.cpp) is not possible.

So, what if we allow actors to set a subset of given actor_type as behavior? Consider this example:

struct my_actor : actor_type<reacts_to<atom("init">,
reacts_to<atom("add"),int,int>::with<int>,
reacts_to<atom("hello")>::with<std::string>> {
void init() {
// check whether given match_expr defines a subset of defined actor_type
become (
on(atom("init")) >> [=] {
become (
on(atom("add"), arg_match) >> [=](int a, int b) {
return a+b;
},
on(atom("hello")) >> [=] {
return "world";
}
);
}
);
}
}

This approach only allows class-based actors, because we need to evaluate the type information provided by 'this'. We would enable the compiler to check for *some* errors, but we could not verify, at compile time, that an actor actually implements its own interface, because we have no way the check whether an actor implements a message handler for each message it claims to be able to receive.

Even worse, both approaches do not allow actors to send/receive messages before replying to a request (unless message passing would be blocking, which would put an end to scalability). If we go back to the reply() API currently found in libcppa, we couldn't match request and response type.


In any case, we would no longer be able to converts threads to actors on-the-fly:

int main() {
auto worker = spawn(...);
// Um... what is the type of 'self'? Is it a valid receiver for the response message?
send(worker, ...);
receive (
// again: what is 'self' allowed to receive/reply? ...
);
}


Long story short: a type-safe interface would be less powerful and would require more boilerplate code. However, perhaps there is a middle ground for doing type checks at runtime when compiled in debug mode?

int my_actor() {
// macro, defined as nothing if not compiled in debug mode
assert_protocol(reacts_to<atom("add"),int,int>::with<int>,
reacts_to<atom("hello")>::with<std::string>);
}

Perhaps it would be possible to include the first presented approach for type-safe actors along with the (dynamic) default actor API. In this way, we could compose type-safe subsystems of actors whenever a problem can be solved using the limited API.


> While I find your tuple pattern matching quite interesting I'm looking
> for a more low level interface for the Actors part, that doesn't force
> to use tuples. It provides just a way to identify uniquely the message
> type and the associated data.
>
> on<messageType> >> [](associatedDateType const& data) { /*...*/},
>
> Of course the user could already use {atom("messageName"),
> associatedDataType()}, but this forces the user to use a cow data type
> that could be too costly for some applications. As most the
> communications are point to point, the ownership of the message is quite
> clear in these cases, so no need for COW.

I guess this is more of an optimization issue. We have to wrap the values into a mailbox_element anyways before putting the message to an actor's mailbox (http://libcppa.blogspot.de/2011/04/mailbox-part-1.html). This element might as well *be* the tuple in case of 1:1 communication. When forwarding the message, we then could simply transfer ownership of the mailbox element. Only when accessing self->last_dequeued(), we would have to make sure to provide COW semantics.


> Last but not least your library works only on some C++11 compilers. I
> have nothing against having C++11 specific libraries in Boost, even the
> opposite (I proposed it long time ago) but the fact is that currently,
> the Boost libraries provide at least a minimal interface on C++98
> compilers. I don't know what the Boost community thinks about this point
> now.
> Welcome, keep up the good work and good luck with your library,
> Vicente

Thank you. At the "Future of Boost" session at the C++Now conference, most developers agreed that it makes sense to embrace C++11 and to use the momentum of the new standard. I hope this is a broad consensus among all Boost developers.

Vicente J. Botet Escriba

unread,
May 19, 2013, 9:31:52 PM5/19/13
to bo...@lists.boost.org
Le 20/05/13 01:48, Dominik Charousset a écrit :
What do you mean by change its behavior?
> So, what if we allow actors to set a subset of given actor_type as behavior? Consider this example:
>
> struct my_actor : actor_type<reacts_to<atom("init">,
> reacts_to<atom("add"),int,int>::with<int>,
> reacts_to<atom("hello")>::with<std::string>> {
> void init() {
> // check whether given match_expr defines a subset of defined actor_type
> become (
> on(atom("init")) >> [=] {
> become (
> on(atom("add"), arg_match) >> [=](int a, int b) {
> return a+b;
> },
> on(atom("hello")) >> [=] {
> return "world";
> }
> );
> }
> );
> }
> }
>
> This approach only allows class-based actors, because we need to evaluate the type information provided by 'this'. We would enable the compiler to check for *some* errors, but we could not verify, at compile time, that an actor actually implements its own interface, because we have no way the check whether an actor implements a message handler for each message it claims to be able to receive.
Good point. I think that your approach is to let the message on the mail
box until a match is requested. On the systems I use to work an
asynchronous message is simply destroyed if not handled explicitly, so
in my case the message is always implemented implicitly. Another history
is for the synchronous communication (reply?). I would say that this is
similar to callback interface.
>
> Even worse, both approaches do not allow actors to send/receive messages before replying to a request (unless message passing would be blocking, which would put an end to scalability). If we go back to the reply() API currently found in libcppa, we couldn't match request and response type.
You lost me.
>
> In any case, we would no longer be able to converts threads to actors on-the-fly:
Humm, this would be unfortunate.
> int main() {
> auto worker = spawn(...);
> // Um... what is the type of 'self'? Is it a valid receiver for the response message?
> send(worker, ...);
> receive (
> // again: what is 'self' allowed to receive/reply? ...
> );
> }
Couldn't spawn have a template parameter giving the provided protocol?
Self could be typed with the supported protocol(s). Self could be passed
by the underlying system as a parameter of the spawned function, as e.g.
Boost.Coroutine does. This avoids the use of thread specific data to get
the current self as I expect you do. Up to the user to manage with the
self parameter.

>
> Long story short: a type-safe interface would be less powerful and would require more boilerplate code. However, perhaps there is a middle ground for doing type checks at runtime when compiled in debug mode?
>
> int my_actor() {
> // macro, defined as nothing if not compiled in debug mode
> assert_protocol(reacts_to<atom("add"),int,int>::with<int>,
> reacts_to<atom("hello")>::with<std::string>);
> }
I don't think I would use this kind of assertions.
> Perhaps it would be possible to include the first presented approach for type-safe actors along with the (dynamic) default actor API. In this way, we could compose type-safe subsystems of actors whenever a problem can be solved using the limited API.
Yeah, providing both approaches would be great.
>
>
>> While I find your tuple pattern matching quite interesting I'm looking
>> for a more low level interface for the Actors part, that doesn't force
>> to use tuples. It provides just a way to identify uniquely the message
>> type and the associated data.
>>
>> on<messageType> >> [](associatedDateType const& data) { /*...*/},
>>
>> Of course the user could already use {atom("messageName"),
>> associatedDataType()}, but this forces the user to use a cow data type
>> that could be too costly for some applications. As most the
>> communications are point to point, the ownership of the message is quite
>> clear in these cases, so no need for COW.
> I guess this is more of an optimization issue. We have to wrap the values into a mailbox_element anyways before putting the message to an actor's mailbox (http://libcppa.blogspot.de/2011/04/mailbox-part-1.html). This element might as well *be* the tuple in case of 1:1 communication. When forwarding the message, we then could simply transfer ownership of the mailbox element. Only when accessing self->last_dequeued(), we would have to make sure to provide COW semantics.
When there are a lot of exchanged messages optimizing the communication
seems important to me. I would prefer move semantics in this particular
case. COW doesn't provides the efficiency I'm locking for. This doesn't
mean that your approach is not coherent, but at a higher level.
>
>
>> Last but not least your library works only on some C++11 compilers. I
>> have nothing against having C++11 specific libraries in Boost, even the
>> opposite (I proposed it long time ago) but the fact is that currently,
>> the Boost libraries provide at least a minimal interface on C++98
>> compilers. I don't know what the Boost community thinks about this point
>> now.
>> Welcome, keep up the good work and good luck with your library,
>> Vicente
> Thank you. At the "Future of Boost" session at the C++Now conference, most developers agreed that it makes sense to embrace C++11 and to use the momentum of the new standard. I hope this is a broad consensus among all Boost developers.
>
>
Great. Glad to hear we are ready to move.

Best,
Vicente

Oliver Kowalke

unread,
May 20, 2013, 12:14:39 AM5/20/13
to boost
2013/5/20 Vicente J. Botet Escriba <vicent...@wanadoo.fr>

> int main() {
>> auto worker = spawn(...);
>> // Um... what is the type of 'self'? Is it a valid receiver for the
>> response message?
>> send(worker, ...);
>> receive (
>> // again: what is 'self' allowed to receive/reply? ...
>> );
>> }
>>
> Couldn't spawn have a template parameter giving the provided protocol?
> Self could be typed with the supported protocol(s). Self could be passed
> by the underlying system as a parameter of the spawned function, as e.g.
> Boost.Coroutine does. This avoids the use of thread specific data to get
> the current self as I expect you do. Up to the user to manage with the self
> parameter.
>

This issue was discussed on the ISO C++ future proposals forum - using
thread specific data (thread_local,thread__) would not work if the worker
would migrate between the threads (compiler opts issue).

Dominik Charousset

unread,
May 20, 2013, 1:12:01 PM5/20/13
to bo...@lists.boost.org
To change the behavior of an actor means to replace the current message handler by another one, i.e., call become().


>> So, what if we allow actors to set a subset of given actor_type as behavior? Consider this example:
>>
>> struct my_actor : actor_type<reacts_to<atom("init">,
>> reacts_to<atom("add"),int,int>::with<int>,
>> reacts_to<atom("hello")>::with<std::string>> {
>> void init() {
>> // check whether given match_expr defines a subset of defined actor_type
>> become (
>> on(atom("init")) >> [=] {
>> become (
>> on(atom("add"), arg_match) >> [=](int a, int b) {
>> return a+b;
>> },
>> on(atom("hello")) >> [=] {
>> return "world";
>> }
>> );
>> }
>> );
>> }
>> }
>>
>> This approach only allows class-based actors, because we need to evaluate the type information provided by 'this'. We would enable the compiler to check for *some* errors, but we could not verify, at compile time, that an actor actually implements its own interface, because we have no way the check whether an actor implements a message handler for each message it claims to be able to receive.
> Good point. I think that your approach is to let the message on the mail
> box until a match is requested. On the systems I use to work an
> asynchronous message is simply destroyed if not handled explicitly, so
> in my case the message is always implemented implicitly. Another history
> is for the synchronous communication (reply?). I would say that this is
> similar to callback interface.

Yes, each message remains in the mailbox until the actor handled it. However, it's easy to define a catch-all rule to discard unexpected messages:

void my_actor() {
become(
on(atom("foo")) >> [] { reply(atom("bar")); },
others() >> [] { cerr << "unexpected message: " << to_string(self->last_dequeued()) << endl;
);
}


>>
>> Even worse, both approaches do not allow actors to send/receive messages before replying to a request (unless message passing would be blocking, which would put an end to scalability). If we go back to the reply() API currently found in libcppa, we couldn't match request and response type.
> You lost me.

The compiler needs to know what response type belongs to what request type. The only way to do this in C++ is to return the response from the request handler, so it becomes part of the signature. Using reply() wouldn't work, because we cannot determine from what handler it was called.


>>
>> In any case, we would no longer be able to converts threads to actors on-the-fly:
> Humm, this would be unfortunate.
>> int main() {
>> auto worker = spawn(...);
>> // Um... what is the type of 'self'? Is it a valid receiver for the response message?
>> send(worker, ...);
>> receive (
>> // again: what is 'self' allowed to receive/reply? ...
>> );
>> }
> Couldn't spawn have a template parameter giving the provided protocol?
> Self could be typed with the supported protocol(s). Self could be passed
> by the underlying system as a parameter of the spawned function, as e.g.
> Boost.Coroutine does. This avoids the use of thread specific data to get
> the current self as I expect you do. Up to the user to manage with the
> self parameter.

The 'self' pointer has to use a thread-local variable, because (1) scheduled actors migrate between threads (see Oliver Kowalke's response) and (2) threads are converted implicitly as soon as they use actor-related messages such as 'send'.


>> Long story short: a type-safe interface would be less powerful and would require more boilerplate code. However, perhaps there is a middle ground for doing type checks at runtime when compiled in debug mode?
>>
>> int my_actor() {
>> // macro, defined as nothing if not compiled in debug mode
>> assert_protocol(reacts_to<atom("add"),int,int>::with<int>,
>> reacts_to<atom("hello")>::with<std::string>);
>> }
> I don't think I would use this kind of assertions.

Well, it could make it easier to debug an actor-based application. Another possibility is to perform static analysis (maybe using a Clang plugin).


>> Perhaps it would be possible to include the first presented approach for type-safe actors along with the (dynamic) default actor API. In this way, we could compose type-safe subsystems of actors whenever a problem can be solved using the limited API.
> Yeah, providing both approaches would be great.

Agreed. It should be straightforward to implement, too.


>>> While I find your tuple pattern matching quite interesting I'm looking
>>> for a more low level interface for the Actors part, that doesn't force
>>> to use tuples. It provides just a way to identify uniquely the message
>>> type and the associated data.
>>>
>>> on<messageType> >> [](associatedDateType const& data) { /*...*/},
>>>
>>> Of course the user could already use {atom("messageName"),
>>> associatedDataType()}, but this forces the user to use a cow data type
>>> that could be too costly for some applications. As most the
>>> communications are point to point, the ownership of the message is quite
>>> clear in these cases, so no need for COW.
>> I guess this is more of an optimization issue. We have to wrap the values into a mailbox_element anyways before putting the message to an actor's mailbox (http://libcppa.blogspot.de/2011/04/mailbox-part-1.html). This element might as well *be* the tuple in case of 1:1 communication. When forwarding the message, we then could simply transfer ownership of the mailbox element. Only when accessing self->last_dequeued(), we would have to make sure to provide COW semantics.
> When there are a lot of exchanged messages optimizing the communication
> seems important to me. I would prefer move semantics in this particular
> case. COW doesn't provides the efficiency I'm locking for. This doesn't
> mean that your approach is not coherent, but at a higher level.

libcppa already uses move whenever possible. As long as you send a message to one actor (using move on your arguments), you won't make copy of any value, unless you do something silly like 'send_tuple(buddy, self->last_dequeued())'.

Oliver Kowalke

unread,
May 20, 2013, 1:52:44 PM5/20/13
to boost
2013/5/20 Dominik Charousset <dominik.c...@haw-hamburg.de>

> >> In any case, we would no longer be able to converts threads to actors
> on-the-fly:
> > Humm, this would be unfortunate.
> >> int main() {
> >> auto worker = spawn(...);
> >> // Um... what is the type of 'self'? Is it a valid receiver for the
> response message?
> >> send(worker, ...);
> >> receive (
> >> // again: what is 'self' allowed to receive/reply? ...
> >> );
> >> }
> > Couldn't spawn have a template parameter giving the provided protocol?
> > Self could be typed with the supported protocol(s). Self could be passed
> > by the underlying system as a parameter of the spawned function, as e.g.
> > Boost.Coroutine does. This avoids the use of thread specific data to get
> > the current self as I expect you do. Up to the user to manage with the
> > self parameter.
>
> The 'self' pointer has to use a thread-local variable, because (1)
> scheduled actors migrate between threads (see Oliver Kowalke's response)
> and (2) threads are converted implicitly as soon as they use actor-related
> messages such as 'send'.
>

What I tried to say - it will not work because compilers are allowed to do
some optimizations with addresses of thread-local data.

Hartmut Kaiser

unread,
May 20, 2013, 8:02:42 PM5/20/13
to bo...@lists.boost.org
Even if I have to admit that I don't understand all implication of what
you're saying, I would like to assert that it is possible to expose a fully
compile-time type-safe way of invoking remote functions (actors). Here is
what we do in HPX (https://github.com/STEllAR-GROUP/hpx/):

int foo(std::string s) { return boost::lexical_cast<int>(s); }

typedef hpx::make_action<decltype(&foo), &foo>::type foo_action_type;
foo_action_type foo_action;

// 'synchronous' invocation
cout << foo_action(remote_locality_id, "42"); // prints 42


// asynchronous invocation
hpx::future<int> f = hpx::async(foo_action, remote_locality_id, "42");
// do other stuff
cout << f.get(); // prints 42


// fails compiling
cout << foo_action(remote_locality_id, 42);

The same (similar) works for invoking member functions of remote objects.

Regards Hartmut
---------------
http://boost-spirit.com
http://stellar.cct.lsu.edu

Dominik Charousset

unread,
May 21, 2013, 2:55:55 PM5/21/13
to bo...@lists.boost.org
All operations in libcppa are network transparent. The problem is not to perform the type checks on messages, but to extract the type information in the first place. Basically, we cannot look inside of a function. So all calls to become() and reply() are "hidden" at compile time, unless we expose the actor's protocol through the function signature (in C++14, we can even suppress the actor_type<...> return type and let the compiler deduce it for us):

actor_type<reacts_to<atom("add"),int,int>::with<int>,
reacts_to<atom("hello")>::with<std::string>> my_actor() {
return (
on(atom("add"), arg_match) >> [](int a, int b) {
return a+b;
},
on(atom("hello")) >> [] {
return "world";
}
);
}

Given the implementation of my_actor above, spawn(my_actor) could return a strongly typed actor, because we can deduce this type information from the signature.


Best regards,
Dominik

Vicente J. Botet Escriba

unread,
May 22, 2013, 3:27:05 PM5/22/13
to bo...@lists.boost.org
Hi,

I've found this Scala Actor Akka 1[1] framework quite interesting. BTW,
it defines both untyped and typed actors.

Best,
Vicente

[1] http://doc.akka.io/docs/akka/2.1.4/Akka.pdf

Max Skvortsov

unread,
May 22, 2013, 9:31:21 PM5/22/13
to bo...@lists.boost.org
Vicente J. Botet Escriba <vicente.botet <at> wanadoo.fr> writes:

>
> Hi,
>
> I've found this Scala Actor Akka 1[1] framework quite interesting. BTW,
> it defines both untyped and typed actors.
>

And you probably know about this [1] interesting library

[1] https://github.com/Neverlord/libcppa

Vicente Botet

unread,
May 23, 2013, 1:37:08 AM5/23/13
to bo...@lists.boost.org
Max Skvortsov wrote
> Vicente J. Botet Escriba
> <vicente.botet <at>
> wanadoo.fr> writes:
>
>>
>> Hi,
>>
>> I've found this Scala Actor Akka 1[1] framework quite interesting. BTW,
>> it defines both untyped and typed actors.
>>
>
> And you probably know about this [1] interesting library
>
> [1] https://github.com/Neverlord/libcppa

Sorry, I would maintain some context . THis was a replay to the post on
libcppa :(

Best,
Vicente



--
View this message in context: http://boost.2283326.n4.nabble.com/Is-there-any-interest-in-a-library-for-actor-programming-tp4647465p4647715.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

Dominik Charousset

unread,
May 23, 2013, 8:45:29 AM5/23/13
to bo...@lists.boost.org
On 23.05.2013, at 07:37, Vicente Botet <vicent...@wanadoo.fr> wrote:
> Max Skvortsov wrote
>> Vicente J. Botet Escriba
>> <vicente.botet <at>
>> wanadoo.fr> writes:
>>
>>>
>>> Hi,
>>>
>>> I've found this Scala Actor Akka 1[1] framework quite interesting. BTW,
>>> it defines both untyped and typed actors.
>>>
>>
>> And you probably know about this [1] interesting library
>>
>> [1] https://github.com/Neverlord/libcppa
>
> Sorry, I would maintain some context . THis was a replay to the post on
> libcppa :(
>
> Best,
> Vicente


I'm glad you find libcppa interesting and I hope you'll support me in my effort of turning it into a Boost library. :)

Akka is an interesting library, too. They made some different design decisions (no automatic skipping of messages for instance), but our plans to provide an interface for Protobuf is not least because we want to be able to send messages from C++ actors to Scala (Akka) actors. Being able to talk to web services would be a nice side effect.


Best regards,
Dominik

Brandon Kohn

unread,
Jun 3, 2013, 9:09:37 AM6/3/13
to bo...@lists.boost.org
On 5/17/2013 5:26 PM, Charousset, Dominik wrote:
> is there any interest in a library for actor programming?
I'm quite interested in this.
>
> The library we've developed is a C++11 open source library named "libcppa". It is currently released under LGPL2, but re-releasing the library under the boost license is not an issue. You'll find all important links and ressources either under http://libcppa.org or on the GitHub project page: https://github.com/Neverlord/libcppa, including a user manual as HTML or PDF. We've also submitted a paper to the C++Now conference.
I agree that embracing C++11 is great, but would also be curious if a
significant amount of functionality could also work with earlier
versions/compilers by using the boost equivalents. This is perhaps a bit
selfish of me because I work in multi-agent simulation, and our current
code base is locked in msvc-9.0.

Let me know if you'd like any assistance. Your library looks really
nice, and I'd be happy to help.

Cheers,

Brandon

Dominik Charousset

unread,
Jun 3, 2013, 1:32:26 PM6/3/13
to bo...@lists.boost.org
On 03.06.2013, at 15:09, Brandon Kohn <blk...@hotmail.com> wrote:
> On 5/17/2013 5:26 PM, Charousset, Dominik wrote:
>> is there any interest in a library for actor programming?
> I'm quite interested in this.
>>
>> The library we've developed is a C++11 open source library named "libcppa". It is currently released under LGPL2, but re-releasing the library under the boost license is not an issue. You'll find all important links and ressources either under http://libcppa.org or on the GitHub project page: https://github.com/Neverlord/libcppa, including a user manual as HTML or PDF. We've also submitted a paper to the C++Now conference.
> I agree that embracing C++11 is great, but would also be curious if a
> significant amount of functionality could also work with earlier
> versions/compilers by using the boost equivalents. This is perhaps a bit
> selfish of me because I work in multi-agent simulation, and our current
> code base is locked in msvc-9.0.


The project originally started as C++03 project under the name 'acedia' (http://sourceforge.net/projects/acedia/), but you really end up tilting at windmills and the resulting code is neither clean nor readable. We switched to C++11 for that reason when GCC's "C++0x" support included lambdas and variadic templates (we've started development on a GCC 4.5 beta release). Variadic templates and lambda expressions are ubiquitously used in libcppa.

I guess you could "back-port" the core functionality, but you would destroy maintainability in the process. By replacing every peace of code in libcppa that uses C++11 features with a C++03 workaround, you'll increase the code size by an order of magnitude, while reducing the readability to zero. Let alone behavior definitions. Without lambdas, you will end up using boost::bind *a lot*.

Due to the lack of constexpr, you will have to evaluate each "atom(..)" call at runtime. That combined with the fact that boost::bind relies on heap allocations (while lambdas just use the stack), the back-port would perform very poorly.


> Let me know if you'd like any assistance. Your library looks really
> nice, and I'd be happy to help.

Support is always appreciated. :)
Just send me a mail what parts you are interested in (development, testing/debugging, documentation, help in porting it to windows either once MS finally has sufficient C++11 support or using MinGW for example).


Best regards,
Dominik

Hartmut Kaiser

unread,
Jun 5, 2013, 9:48:05 AM6/5/13
to bo...@lists.boost.org

> On 5/17/2013 5:26 PM, Charousset, Dominik wrote:
> > is there any interest in a library for actor programming?
> I'm quite interested in this.
> >
> > The library we've developed is a C++11 open source library named
> "libcppa". It is currently released under LGPL2, but re-releasing the
> library under the boost license is not an issue. You'll find all important
> links and ressources either under http://libcppa.org or on the GitHub
> project page: https://github.com/Neverlord/libcppa, including a user
> manual as HTML or PDF. We've also submitted a paper to the C++Now
> conference.
>
> I agree that embracing C++11 is great, but would also be curious if a
> significant amount of functionality could also work with earlier
> versions/compilers by using the boost equivalents. This is perhaps a bit
> selfish of me because I work in multi-agent simulation, and our current
> code base is locked in msvc-9.0.

Just to reiterate, HPX (https://github.com/STEllAR-GROUP/hpx/) is a very
similar library exposing actor oriented paradigms to the programmer (amongst
other things), just wrapped up into a C++11 compliant interface (future,
async, thread, bind, function, tuple, etc.). It's usable with C++03
compliant compilers (I have not tried msvc-9.0, though). While not part of
Boost, it strongly adheres to Boost coding guidelines and style and it is
maintained by long standing Boost authors.

Regards Hartmut
---------------
http://boost-spirit.com
http://stellar.cct.lsu.edu



Brandon Kohn

unread,
Jun 5, 2013, 9:53:38 AM6/5/13
to bo...@lists.boost.org
On 6/5/2013 9:48 AM, Hartmut Kaiser wrote:
> Just to reiterate, HPX (https://github.com/STEllAR-GROUP/hpx/) is a very
> similar library exposing actor oriented paradigms to the programmer (amongst
> other things), just wrapped up into a C++11 compliant interface (future,
> async, thread, bind, function, tuple, etc.). It's usable with C++03
> compliant compilers (I have not tried msvc-9.0, though). While not part of
> Boost, it strongly adheres to Boost coding guidelines and style and it is
> maintained by long standing Boost authors.
>
Thanks for posting this Hartmut. I was not aware of this library. It
looks very interesting.

Cheers,

Brandon

Dominik Charousset

unread,
Jun 6, 2013, 5:36:45 AM6/6/13
to bo...@lists.boost.org
On 18.05.2013, at 23:54, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
> This is really a lot of good and interesting work on your library.
>
> Moving all the library to the Boost standards would be quite a lot of
> work however. Replacing some classes by the corresponding Boost ones.
>
> I would see already several Boost libraries in your libcppa library:
> * Atoms
> * CowTuples
> * Dynamically Typed Tuples - type erased tuples
> * Tuples Pattern matching
> * Actors

I gave this some thoughts. cow_tuple and any_tuple use the same data representation underneath. In this way, there is no 'conversion' from one to the other. Assigning a cow_tuple to an any_tuple is trivial. To restore the type information, tuple_cast can be used. This cast also allows for wildcards:

auto t0 = make_cow_tuple(1, 2, 3, 4);
any_tuple t1 = t0;
auto opt = tuple_cast<anything, int, int>(t1);
if (opt) {
auto t2 = *opt;
cout << get<0>(t2) // will print 3
<< get<1>(t2) // will print 4
<< endl;
}


any_tuple provides the same copy-on-write behavior:

auto t0 = make_cow_tuple(1, "hello", "world"); // const char* is implicitly converted to std::string
any_tuple t1 = t0;
any_tuple t2 = t0;
assert(&t1.get_as<int>(0) == &t2.get_as<int>(0)); // same address
assert(&get<0>(t0) == &t1.get_as<int>(0)); // same address
t1.get_as_mutable<std::string>(2) = "libcppa";
assert(&t1.get_as<int>(0) != &t2.get_as<int>(0)); // no longer the same address
assert(&get<0>(t0) != &t1.get_as<int>(0)); // no longer the same address


Long story short: cow_tuple and any_tuple are closely related. any_tuple *is* a typed erased cow_tuple. Would it be beneficial to split them into two libraries? Any thoughts on that?


Currently, I'm reviewing the tuple classes and evaluate whether boost.serialization/boost::extended_type_info fit the needs of libcppa.




On 05.06.2013, at 15:48, Hartmut Kaiser <hartmut...@gmail.com> wrote:
> Just to reiterate, HPX (https://github.com/STEllAR-GROUP/hpx/) is a very
> similar library exposing actor oriented paradigms to the programmer (amongst
> other things), just wrapped up into a C++11 compliant interface (future,
> async, thread, bind, function, tuple, etc.). It's usable with C++03
> compliant compilers (I have not tried msvc-9.0, though). While not part of
> Boost, it strongly adheres to Boost coding guidelines and style and it is
> maintained by long standing Boost authors.

Hartmut, I can understand that you want to advertise your work, but hpx has nothing to do with actor programming. I saw your presentation at the C++Now conference. hpx offers a future-based API and you are proposing C#'s syntax for async/await (cf. N3564 [1]).


[1] http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3564.pdf



Best regards,
Dominik

David Sankel

unread,
Jun 8, 2013, 2:11:48 PM6/8/13
to bo...@lists.boost.org
On Sun, May 19, 2013 at 5:48 PM, Dominik Charousset <
dominik.c...@haw-hamburg.de> wrote:

>
> On May 18, 2013, at 11:54 PM, "Vicente J. Botet Escriba" <
> vicent...@wanadoo.fr> wrote:
>
> > Le 17/05/13 23:26, Charousset, Dominik a écrit :
> >> Hi,
> >>
> >> is there any interest in a library for actor programming?
> >>
> >> The library we've developed is a C++11 open source library named
> "libcppa".
>

> > There is something that I would like to see on the Actors architecture.
> > The interface of an actor is not really defined other than by their
> > behavior. It can receive any dynamic tuple. This is a lot. I would like
> > a more statically typed interface. An actor could define statically the
> > kind of messages/signals it is allowed to handle and make it part of the
> > interface.
>
> There was some discussion about this topic after the talk at the C++Now
> conference.


To continue that discussion...


> I do agree that it is desirable to enable the compiler to verify the
> correctness of actor programs at compile time. However, in order to be able
> to ensure the correctness of a program, one would have to define not only
> all possible input messages, but the response types depending on the input
> as well.


Yes, and when writing code with strong compiler guarantees, this is a
desirable feature.


> However, an approach like this cannot allow an actor to change its
> behavior.


I think there is a large subset of use-cases where there is a willingness
to disallow an actor to "change its behavior" (aka, change its type), in
order to gain the benefit of compile-time guarantees.


> Hence, something as simple as the classical dining philosophers example (
> https://github.com/Neverlord/libcppa/blob/master/examples/message_passing/dining_philosophers.cpp)
> is not possible.
>

I don't think it's been demonstrated that the 'typed' and 'untyped'
approaches are mutually exclusive.

For a Boost.Actor library, I would really like to see static types being
well supported. That would likely be the only type of Actor library I would
personally use in practice. Strong compiler guarantees enable safe
refactoring of large applications, which is where C++ shines.

I wouldn't object to there being a trap door to type-unsafety to fit some
need, though its use should rightfully be discouraged.

Long story short: a type-safe interface would be less powerful and would
> require more boilerplate code.


The same argument can be used for any dynamic vs. static type argument. The
user base of this library has already taken a stance on the issue by their
choice of C++. That may be why there is so much push back to the current
dynamic approach of libcppa.


> However, perhaps there is a middle ground for doing type checks at runtime
> when compiled in debug mode?
>
> int my_actor() {
> // macro, defined as nothing if not compiled in debug mode
> assert_protocol(reacts_to<atom("add"),int,int>::with<int>,
> reacts_to<atom("hello")>::with<std::string>);
> }
>
>

This mimics the python approach to check types at runtime. The whole
benefit of compile time safety is that we get guarantees about code
correctness *before* we run.

-- David Sankel

Dominik Charousset

unread,
Jun 10, 2013, 8:59:06 AM6/10/13
to bo...@lists.boost.org
Oh, I don't think they are. The problem with C++ is the limited meta programming capability. Unfortunately, we cannot traverse the AST. We are only allowed to introspect types and function signatures using template meta programming. Hence, wen cannot look "inside" of an actor implementation to extract all the type information we need by parsing become() and reply() statements. Clang offers a plugin infrastructure to give developers the opportunity to read and manipulate the AST directly, but there is no standard compliant way to do so.


> For a Boost.Actor library, I would really like to see static types being
> well supported. That would likely be the only type of Actor library I would
> personally use in practice. Strong compiler guarantees enable safe
> refactoring of large applications, which is where C++ shines.
>
> I wouldn't object to there being a trap door to type-unsafety to fit some
> need, though its use should rightfully be discouraged.
>
> Long story short: a type-safe interface would be less powerful and would
>> require more boilerplate code.
>
>
> The same argument can be used for any dynamic vs. static type argument. The
> user base of this library has already taken a stance on the issue by their
> choice of C++. That may be why there is so much push back to the current
> dynamic approach of libcppa.

I think providing a strongly typed subset of the library along with the "fully dynamic" version should be a good middle ground. Type safe actors will be more or less lifted functions, where we can derive all the type information we need from the signature.


>> However, perhaps there is a middle ground for doing type checks at runtime
>> when compiled in debug mode?
>>
>> int my_actor() {
>> // macro, defined as nothing if not compiled in debug mode
>> assert_protocol(reacts_to<atom("add"),int,int>::with<int>,
>> reacts_to<atom("hello")>::with<std::string>);
>> }
>>
>>
> This mimics the python approach to check types at runtime. The whole
> benefit of compile time safety is that we get guarantees about code
> correctness *before* we run.

It depends on what you want to achieve. In a largely distributed system, you want to be able to pass addresses around, read addresses from configuration (text) files, etc. You can do this with actors just as you can do it with web (HTTP) addresses. You have a communication layer that only needs addresses and transmits (any) messages. The protocol is a trait between sender/client and receiver/server.

However, if you are designing a tightly coupled system, you're only interested in the message passing (and maybe the failure model) part of the actor model. I guess this is your domain. In such a scenario, you are in control of all components and you want the protocol between the components to be checked before you deploy and run your application, i.e., at compile time.


Best regards,
Dominik

james

unread,
Jun 10, 2013, 4:30:47 PM6/10/13
to bo...@lists.boost.org
On 10/06/2013 13:59, Dominik Charousset wrote:
> On 08.06.2013, at 20:11, David Sankel<cam...@gmail.com> wrote:
> >The same argument can be used for any dynamic vs. static type argument. The
> >user base of this library has already taken a stance on the issue by their
> >choice of C++. That may be why there is so much push back to the current
> >dynamic approach of libcppa.
> I think providing a strongly typed subset of the library along with the "fully dynamic" version should be a good middle ground. Type safe actors will be more or less lifted functions, where we can derive all the type information we need from the signature.
If you are going to be strongly typed then I would suggest using some
kind of message and actor interface compiler and generating code. Using
something that is strongly typed with C++ at both ends of the wire is
going to be fragile in terms of requiring 'big bang' deployments and
also extremely constraining through an inability to communicate with
other language runtimes.

>This mimics the python approach to check types at runtime. The whole
>benefit of compile time safety is that we get guarantees about code
>correctness*before* we run.

(to David - sorry!)

I don't think that the limited correctness you get from that is very useful in a concurrent system. It may ensure that teh form of messages is compatible, but not what they mean, nor any ordering guarantees, and the flip-side is that you have the schema migration issues. IMO its why object databases never went anywhere, and the lingua-franca of SQL (and blob databases with JSON-like data) have been supreme.

James

Brandon Kohn

unread,
Jun 11, 2013, 8:03:24 AM6/11/13
to bo...@lists.boost.org
On 6/10/2013 4:30 PM, james wrote:
> I don't think that the limited correctness you get from that is very
> useful in a concurrent system.

Why not? I think the development crews that worked on the mars orbiter
mission which failed would beg to differ.

Regards,

Brandon

james

unread,
Jun 11, 2013, 5:31:16 PM6/11/13
to bo...@lists.boost.org
On 11/06/2013 13:03, Brandon Kohn wrote:
> On 6/10/2013 4:30 PM, james wrote:
>> I don't think that the limited correctness you get from that is very
>> useful in a concurrent system.
>
> Why not? I think the development crews that worked on the mars orbiter
> mission which failed would beg to differ.
>
> Regards,
>
> Brandon

Personal experience? Its a question of whether you are building and
releasing all components at once, and whether they will all be built in
the same team, and with the same technology.

I have found systems with soft data structures to be more easily
enhanced than ones built from IDL, and have not had many problems from
mismatched syntaxes. Rigid syntax (whether from IDL, or some XML form
check) always seem to end up subverted with additional key/value data or
(even worse) data embedded into 'structured comments'. There's a reason
for that and it all goes back to schema evolution, and that's why
systems like protobuf tend to sacrifice clean syntax for extensibility..

The critical size for a homogeneous system that must be built and
released from the same sources to guarantee wire compatibility seems to
be quite small in practice.

James

David Sankel

unread,
Jun 11, 2013, 7:40:15 PM6/11/13
to bo...@lists.boost.org
On Tue, Jun 11, 2013 at 3:31 PM, james <ja...@mansionfamily.plus.com> wrote:

> On 11/06/2013 13:03, Brandon Kohn wrote:
>
>> On 6/10/2013 4:30 PM, james wrote:
>>
>>> I don't think that the limited correctness you get from that is very
>>> useful in a concurrent system.
>>>
>>
>> Why not? I think the development crews that worked on the mars orbiter
>> mission which failed would beg to differ.
>>
>

> [I]t all goes back to schema evolution, and that's why systems like


> protobuf tend to sacrifice clean syntax for extensibility..
>

I think that goes back to my original point. For a large subset of users,
schema evolution is a non-issue—the entire system is deployed at once. A
Boost.Actor library should have a good story for these users IMO.

As an aside, the whole concept of 'schema evolution' has really piqued my
curiosity. Is there some academic key-word I can search with to learn more
about data structure evolution in systems that need to maintain some kind
of backwards compatibility?

--David Sankel

Bjorn Reese

unread,
Jun 12, 2013, 5:03:38 AM6/12/13
to bo...@lists.boost.org
On 06/11/2013 11:31 PM, james wrote:

> I have found systems with soft data structures to be more easily
> enhanced than ones built from IDL, and have not had many problems from
> mismatched syntaxes. Rigid syntax (whether from IDL, or some XML form
> check) always seem to end up subverted with additional key/value data or
> (even worse) data embedded into 'structured comments'. There's a reason
> for that and it all goes back to schema evolution, and that's why
> systems like protobuf tend to sacrifice clean syntax for extensibility..

JSON (combined with REST) is probably a better example, because
protobuf is also built from an IDL (the .proto file) and knowledge
of the IDL is needed in order to correctly interpret some fields.

Bjorn Reese

unread,
Jun 23, 2013, 5:26:51 AM6/23/13
to bo...@lists.boost.org
The documentation on atoms states that

"Atoms are mapped to integer values at compile time in libcppa. This
mapping is guaranteed to be collision-free and invertible, but limits
atom literals to ten characters and prohibits special characters."

Just wondering, is this some kind of base-64 encoding?

Dominik Charousset

unread,
Jun 24, 2013, 7:34:53 AM6/24/13
to bo...@lists.boost.org
On Jun 23, 2013, at 11:26 AM, Bjorn Reese <bre...@mail1.stofanet.dk> wrote:
> The documentation on atoms states that
>
> "Atoms are mapped to integer values at compile time in libcppa. This
> mapping is guaranteed to be collision-free and invertible, but limits
> atom literals to ten characters and prohibits special characters."
>
> Just wondering, is this some kind of base-64 encoding?

Actually, it is just a simple 6-bit encoding using a lookup table [1]. In this way, the mapping is guaranteed to be collision free and invertible.


[1] https://github.com/Neverlord/libcppa/blob/master/cppa/detail/atom_val.hpp

Bjorn Reese

unread,
Jun 24, 2013, 8:15:37 AM6/24/13
to bo...@lists.boost.org
On 06/24/2013 01:34 PM, Dominik Charousset wrote:

> Actually, it is just a simple 6-bit encoding using a lookup table [1]. In this way, the mapping is guaranteed to be collision free and invertible.

Base-64 is also just a simple 6-bit encoding using a lookup table ;-)

Looking at the code you referenced, it appears that your encoding
algorithm is the same as the base-64 algorithm, but your lookup table
is slightly different (yours includes space and underscore instead of
plus and slash, and the rest are offset by one.)

Thanks for the answer.

Dominik Charousset

unread,
Jun 24, 2013, 9:38:00 AM6/24/13
to bo...@lists.boost.org
On Jun 24, 2013, at 2:15 PM, Bjorn Reese <bre...@mail1.stofanet.dk> wrote:
> On 06/24/2013 01:34 PM, Dominik Charousset wrote:
>
>> Actually, it is just a simple 6-bit encoding using a lookup table [1]. In this way, the mapping is guaranteed to be collision free and invertible.
>
> Base-64 is also just a simple 6-bit encoding using a lookup table ;-)
>
> Looking at the code you referenced, it appears that your encoding
> algorithm is the same as the base-64 algorithm, but your lookup table
> is slightly different (yours includes space and underscore instead of
> plus and slash, and the rest are offset by one.)
>
> Thanks for the answer.

Ok, let's agree that it's a Base64-ish algorithm. ;)
However, the atom mapping does not use padding. Instead, it uses the remaining 4 bits of the 64bit integer to indicate the start of the string (leading zeros are ignored until '1111' is reached) [1].


[1] https://github.com/Neverlord/libcppa/blob/master/src/atom.cpp

Dave Abrahams

unread,
Jul 6, 2013, 9:35:52 AM7/6/13
to bo...@lists.boost.org

on Tue Jun 11 2013, David Sankel <camior-AT-gmail.com> wrote:

> As an aside, the whole concept of 'schema evolution' has really piqued my
> curiosity. Is there some academic key-word I can search with to learn more
> about data structure evolution in systems that need to maintain some kind
> of backwards compatibility?

You find this term all over discussions about applications—especially
web apps—that use persistent databases, but it also applies to anything
that saves and reads files whose format might need to change over time,
i.e. standard desktop apps.

--
Dave Abrahams

Dave Abrahams

unread,
Jul 6, 2013, 9:36:16 AM7/6/13
to bo...@lists.boost.org

on Tue Jun 11 2013, David Sankel <camior-AT-gmail.com> wrote:

> On Tue, Jun 11, 2013 at 3:31 PM, james <ja...@mansionfamily.plus.com> wrote:
>
>> On 11/06/2013 13:03, Brandon Kohn wrote:
>>
>>> On 6/10/2013 4:30 PM, james wrote:
>>>
>>>> I don't think that the limited correctness you get from that is very
>>>> useful in a concurrent system.
>>>>
>>>
>>> Why not? I think the development crews that worked on the mars orbiter
>>> mission which failed would beg to differ.
>>>
>>
>> [I]t all goes back to schema evolution, and that's why systems like
>> protobuf tend to sacrifice clean syntax for extensibility..
>>
>
> I think that goes back to my original point. For a large subset of users,
> schema evolution is a non-issue—the entire system is deployed at once. A
> Boost.Actor library should have a good story for these users IMO.

+1

--
Dave Abrahams

Dominik Charousset

unread,
Oct 15, 2013, 11:50:34 AM10/15/13
to bo...@lists.boost.org
On 06.07.2013, at 15:36, Dave Abrahams <da...@boostpro.com> wrote:
> on Tue Jun 11 2013, David Sankel <camior-AT-gmail.com> wrote:
>
>> On Tue, Jun 11, 2013 at 3:31 PM, james <ja...@mansionfamily.plus.com> wrote:
>>
>>> On 11/06/2013 13:03, Brandon Kohn wrote:
>>>
>>>> On 6/10/2013 4:30 PM, james wrote:
>>>>
>>>>> I don't think that the limited correctness you get from that is very
>>>>> useful in a concurrent system.
>>>>>
>>>>
>>>> Why not? I think the development crews that worked on the mars orbiter
>>>> mission which failed would beg to differ.
>>>>
>>>
>>> [I]t all goes back to schema evolution, and that's why systems like
>>> protobuf tend to sacrifice clean syntax for extensibility..
>>>
>>
>> I think that goes back to my original point. For a large subset of users,
>> schema evolution is a non-issue—the entire system is deployed at once. A
>> Boost.Actor library should have a good story for these users IMO.
>
> +1
>
> --
> Dave Abrahams


So... It's been a while and did indeed cause more implementation work than I had expected, but typed actors are finally ready to fly. A short example:

------------------------------------------------
// no class => actor from match expression
auto p0 = spawn_typed(
on_arg_match >> [](int a, int b) {
return static_cast<double>(a) * b;
},
on_arg_match >> [](double a, double b) {
return make_cow_tuple(a * b, a / b);
}
);
// equal class-based implementation
class foo : public typed_actor<replies_to<int, int>::with<double>,replies_to<double, double>::with<double, double>> {
protected:
// override inherited, pure virtual member function
behavior_type make_behavior() final {
return (
on_arg_match >> [](int a, int b) {
return static_cast<double>(a) * b;
},
on_arg_match >> [](double a, double b) {
return make_cow_tuple(a * b, a / b);
};
);
}
};
...
auto p0 = spawn_typed<foo>();
------------------------------------------------


The newly spawned actor addressed by "p0" has the type typed_actor_ptr<replies_to<int, int>::with<double>,replies_to<double, double>::with<double, double>>. A value returned from a message handler is implicitly used as response message. This now true for all types of actors (and the old 'reply' function is hence deprecated).

Typed actors are not allowed to use the "become()" API, because this would change its type. And without proper compiler support, we cannot traverse the AST to look "inside" the message handlers and parse each call to "become()" to extract all possible message types. Furthermore, typed actors are not allowed to use guards. Either it handles any input of a type or none.

The "replies_to<..>::with<..>" syntax may be a bit verbose, but I think a self-explanatory type is worth some typing. This type is of course assignable to any of its subtypes:

------------------------------------------------
typed_actor_ptr<replies_to<int, int>::with<double>> p1 = p0; // ok

typed_actor_ptr<replies_to<double, double>::with<double, double>> p1 = p0; // ok

typed_actor_ptr<replies_to<int>::with<double>> p3 = p0; // compiler error
------------------------------------------------


When using a typed interface, the compiler is now able to type-check messaging:

------------------------------------------------
send(p0, 42); // <- compiler error

send(p0, 42, 24); // <- ok

sync_send(p0, 1, 2, 3).then ... // <- compiler error

sync_send(p0, 1, 2).then(
[](float) { ... } // <- compiler error: expected double
);

sync_send(p0, 1, 2).then(
[](double d) { ... } // <- ok
);
------------------------------------------------


By the way, another big change in the library is that match expressions now handle result types properly:

------------------------------------------------
auto res = match(something) (
on("hello") >> [] { return 42; },
on("goodbye") >> [] { return "why are you leaving?"; }
);
if (res.is<int>()) { ... } else { ... }
------------------------------------------------


That's also a plus when releasing the pattern matching as standalone boost library. Of course, "res" can be inspected using a visitor as well. It is basically a variant type that is either none_t or any result type from one of the message handlers (void is mapped to void_t to be able to distinct between "no match" and "invoked a void function").

There are currently two "missing" features for typed actors: typed remote actors and priorities. However, this is merely ongoing implementation work and is not by design.

Since type-safety was the major (the only?) concern regarding the library, I would be happy to hear feedback and suggestions. Since most of the "heavy" implementation work is done, I would focus on integrating the library into boost (i.e. use other boost components wherever possible) and using boost namespaces next.

Dominik Charousset

unread,
May 8, 2014, 1:30:40 PM5/8/14
to bo...@lists.boost.org
Hi all,


attached you'll find the first preliminary submission for Boost.Actor as ZIP file along with the Manual in PDF version. You currently still need CMake, a Boost.Jam build file will follow. The project is hosted at GitHub: https://github.com/Neverlord/boost.actor

To state the obvious: we [1] took our time, but not because we are not taking the boost submission serious. In fact, the opposite is true. We did refine libcppa (which is the base for Boost.Actor) over the last months based on community feedback - feedback from this mailing list, last year's C++Now, GitHub, and libcppa's mailing list. However, we are not just trying to lift our library into Boost. We want Boost.Actor to fit into Boost as good as possible - and we did significant changes to the API (see below), which also took time. Furthermore, we think performance is key when providing a native actor system. Boost.Actor/libcppa has now reached a level of performance with the latest version that lives up to our expectations - and hopefully to the expectations of (future) users as well. A brief performance evaluation [2] is attached. The graphs still mention 'libcppa' instead of Boost.Actor.

I hope the lack of Boost.Jam support is not too much of an issue - I thought it would be a good idea to post the preliminary submission before the C++Now (you can meet me there!), to get people time to play with Boost.Actor beforehand.


*Differences between Boost.Actor and libcppa*

If you don't have any experience with libcppa, you can simply skip this. The most visible change is the removal of any_tuple and cow_tuple. The COW tuple implementation of libcppa is in our opinion not general enough and is too intermeshed with the type system. Instead, Boost.Actor provides the class `message` that is an opaque container from a user's point of view. Also, the pattern matching has been reduced to a minimal DSL for defining message handlers. The separate DSL for guard expressions is gone completely (a similar functionality still exists though). Since our pattern matching only worked with messages/any_tuples, we don't see too much use of it outside of Boost.Actor. We are still hoping for native pattern matching in C++ (N3449 proposed this a while ago) in which case our DSL would become unnecessary anyways. As a side-effect of removing all these parts, Boost.Actor has become a streamlined version of libcppa that is easier to grasp and that will be easier to maintain in the long run as well.


*Boost.Actor depends on...*

variant, optional, none, string_algorithms, intrusive_ptr, thread (currently as header-only dependency), context/coroutine (for cooperatively scheduled blocking actors). Some examples also require program_options.


*Boost.Actor does NOT use...*

(1) MPL. Boost.Actor uses a ludicrous amount of metaprogramming based on boost::actor::detail::type_list. I've tried to port it to MPL and wasted almost two days doing so. MPL is a great C++ library. Unfortunately, C++98, not C++11. Even after adding variadic helpers to reduce the amount of template instantiations, it would still explode and fail to compile. I've stopped after writing half the size of the current type_list utility functions and still wasn't able to reduce the amount of template instantiations significantly enough. That being said, I am looking forward to the GSoC project for MPL11.

(2) Serialization. The first and most obvious problem I have with this library is the lack of a portable binary archive. String serialization is sufficient for a lot of applications, but the performance hit for both networking overhead and the string serialization itself is not acceptable in an actor system. Furthermore, simply adding such a binary archive would not be enough. The library does not give you a platform-independent representation of the type names, which is crucial. Also, one cannot create an instance of a type given only its type name and then deserialize its values from a network stream (I was thinking of ETI::key_register using the uniform names and ETI::find, but it only solves a part of the problem). Adding all of these capabilities on top of boost.serialization plus writing a portable binary archive (or maybe use something like EOS - http://epa.codeplex.com/) would probably result in more code and most likely in a more complicated design, i.e., would be harder to maintain. Maybe I miss the forest for the trees here and some experienced boost.serialization user knows a straightforward way I don't see. However, maybe there is interest in extending boost.serialization. I'd be happy to work on patches for adding uniform names, etc.

(3) Boost.Asio. There is definitely potential to port the low-level parts of the middleman to Asio, I think. These changes would be transparent to the user, though, since users really only use the broker and can forget about the rest.


*Separating parts of Boost.Actor?*

Vicente J. Botet Escriba suggested to separate some parts of library. Namely the constexpr atom() [the other parts he suggested were removed, btw]. Aside from that, there are some C++11 utility functions that I think would be useful for other developers as well. Namely int_list [3] which can be used to create indices for variadic types such as tuples to allow users to apply the values of a tuple to a functor with apply_args [4]. type_list [5] is a powerful tool too, but I think this functionality goes to MPL11 anyways. Something that might be worth lifting to the boost namespace is unit [6], which makes metaprogramming (for me) a lot easier by providing an easy way of lifting void to something useful and don't need to worry whether or not it might end up in a tuple or variant. MPL already has void_t, but it doesn't seem to be indented to be used the way I use unit. For binary serialization of floats, there is IEEE 754 packing/unpacking [6] that is based on http://beej.us/guide/bgnet/examples/pack2.c



Sorry for the wall of text, the Mail got longer and longer somehow ...



[1] "We" are a working group at the University of Applied Sciences Hamburg: http://inet.cpt.haw-hamburg.de/

[2] The sources for all benchmark programs can be found here: https://github.com/Neverlord/cppa-benchmarks, please keep in mind that the evaluation uses libcppa, so the API used in the benchmarks is different.

[3] https://github.com/Neverlord/boost.actor/blob/a0cab41e2946df7d751c59dfead0c2122da0fb77/boost/actor/detail/int_list.hpp

[4] https://github.com/Neverlord/boost.actor/blob/ea53a515e09a98baa173ad379127c32ddf5e786e/boost/actor/detail/apply_args.hpp

[5] https://github.com/Neverlord/boost.actor/blob/58d6177837788b2e54b8547531bda99fc7d795e0/boost/actor/detail/type_list.hpp

[6] https://github.com/Neverlord/boost.actor/blob/644a47760d6b55eef438a81d7bcdc233d3575e2e/boost/actor/detail/ieee_754.hpp

[7] https://github.com/Neverlord/boost.actor/blob/ea53a515e09a98baa173ad379127c32ddf5e786e/boost/actor/unit.hpp



boost.actor-preliminary_submission_1.zip
boost submission performance evaluation.zip
manual.pdf

Jan Herrmann

unread,
May 9, 2014, 4:52:04 AM5/9/14
to bo...@lists.boost.org
On 08.05.2014 19:30, Dominik Charousset wrote:
> Hi all,
>
>
> attached you'll find the first preliminary submission for Boost.Actor as ZIP file along with the Manual in PDF version. You currently still need CMake, a Boost.Jam build file will follow. The project is hosted at GitHub: https://github.com/Neverlord/boost.actor

As far as I understand a library with LGPL can not be part of boost (see
www.boost.org/development/requirements.html ). So the it should be changed.

>
> To state the obvious: we [1] took our time, but not because we are not taking the boost submission serious. In fact, the opposite is true. We did refine libcppa (which is the base for Boost.Actor) over the last months based on community feedback - feedback from this mailing list, last year's C++Now, GitHub, and libcppa's mailing list. However, we are not just trying to lift our library into Boost. We want Boost.Actor to fit into Boost as good as possible - and we did significant changes to the API (see below), which also took time. Furthermore, we think performance is key when providing a native actor system. Boost.Actor/libcppa has now reached a level of performance with the latest version that lives up to our expectations - and hopefully to the expectations of (future) users as well. A brief performance evaluation [2] is attached. The graphs still mention 'libcppa' instead of Boost.Actor.
>
> I hope the lack of Boost.Jam support is not too much of an issue - I thought it would be a good idea to post the preliminary submission before the C++Now (you can meet me there!), to get people time to play with Boost.Actor beforehand.
>
>
> *Differences between Boost.Actor and libcppa*
>
> If you don't have any experience with libcppa, you can simply skip this. The most visible change is the removal of any_tuple and cow_tuple. The COW tuple implementation of libcppa is in our opinion not general enough and is too intermeshed with the type system. Instead, Boost.Actor provides the class `message` that is an opaque container from a user's point of view. Also, the pattern matching has been reduced to a minimal DSL for defining message handlers. The separate DSL for guard expressions is gone completely (a similar functionality still exists though). Since our pattern matching only worked with messages/any_tuples, we don't see too much use of it outside of Boost.Actor. We are still hoping for native pattern matching in C++ (N3449 proposed this a while ago) in which case our DSL would become unnecessary anyways. As a side-effect of removing all these parts, Boost.Actor has become a streamlined version of libcppa that is easier to grasp and that will be easier to mai
ntain i
n the long run as well.
>
>
> *Boost.Actor depends on...*
>
> variant, optional, none, string_algorithms, intrusive_ptr, thread (currently as header-only dependency), context/coroutine (for cooperatively scheduled blocking actors). Some examples also require program_options.
>
>
> *Boost.Actor does NOT use...*
>
> (1) MPL. Boost.Actor uses a ludicrous amount of metaprogramming based on boost::actor::detail::type_list. I've tried to port it to MPL and wasted almost two days doing so. MPL is a great C++ library. Unfortunately, C++98, not C++11. Even after adding variadic helpers to reduce the amount of template instantiations, it would still explode and fail to compile. I've stopped after writing half the size of the current type_list utility functions and still wasn't able to reduce the amount of template instantiations significantly enough. That being said, I am looking forward to the GSoC project for MPL11.
>
> (2) Serialization. The first and most obvious problem I have with this library is the lack of a portable binary archive. String serialization is sufficient for a lot of applications, but the performance hit for both networking overhead and the string serialization itself is not acceptable in an actor system. Furthermore, simply adding such a binary archive would not be enough. The library does not give you a platform-independent representation of the type names, which is crucial. Also, one cannot create an instance of a type given only its type name and then deserialize its values from a network stream (I was thinking of ETI::key_register using the uniform names and ETI::find, but it only solves a part of the problem). Adding all of these capabilities on top of boost.serialization plus writing a portable binary archive (or maybe use something like EOS - http://epa.codeplex.com/) would probably result in more code and most likely in a more complicated design, i.e., would be
harder
to maintain. Maybe I miss the forest for the trees here and some experienced boost.serialization user knows a straightforward way I don't see. However, maybe there is interest in extending boost.serialization. I'd be happy to work on patches for adding uniform names, etc.
>
> (3) Boost.Asio. There is definitely potential to port the low-level parts of the middleman to Asio, I think. These changes would be transparent to the user, though, since users really only use the broker and can forget about the rest.
>
>
> *Separating parts of Boost.Actor?*
>
> Vicente J. Botet Escriba suggested to separate some parts of library. Namely the constexpr atom() [the other parts he suggested were removed, btw]. Aside from that, there are some C++11 utility functions that I think would be useful for other developers as well. Namely int_list [3] which can be used to create indices for variadic types such as tuples to allow users to apply the values of a tuple to a functor with apply_args [4]. type_list [5] is a powerful tool too, but I think this functionality goes to MPL11 anyways. Something that might be worth lifting to the boost namespace is unit [6], which makes metaprogramming (for me) a lot easier by providing an easy way of lifting void to something useful and don't need to worry whether or not it might end up in a tuple or variant. MPL already has void_t, but it doesn't seem to be indented to be used the way I use unit. For binary serialization of floats, there is IEEE 754 packing/unpacking [6] that is based on http://beej.us/gu
ide/bgn
et/examples/pack2.c

What is the difference from your int_list and std::integer_sequence
(http://en.cppreference.com/w/cpp/utility/integer_sequence) ?

Larry Evans

unread,
May 9, 2014, 2:44:33 PM5/9/14
to bo...@lists.boost.org
On 05/08/14 12:30, Dominik Charousset wrote:
[snip]
>
> [3] https://github.com/Neverlord/boost.actor/blob/a0cab41e2946df7d751c59dfead0c2122da0fb77/boost/actor/detail/int_list.hpp

https://github.com/Neverlord/boost.actor/blob/a0cab41e2946df7d751c59dfead0c2122da0fb77/boost/actor/detail/int_list.hpp#L83

uses a recursive call using a List<typename ...Ts> which is 1 shorter
than the argument list, List<T0, Ts...>.
Why not just pass sizeof...(T0, Ts...):

http://en.cppreference.com/w/cpp/language/sizeof...

and keep adding indices while decreasing this sizeof value,
as done here:

http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/package_range_c.hpp

in the package_range_c template class where:

Start value would be 0
and Finish value would be sizeof...(T0, Ts...)

It achieves the same result, but without producing unneeded
instantiations. For example:

package_range_c<std::size_t,0,sizeof...(mpl::vector<T0,T2,T3>>::type
package_range_c<std::size_t,0,sizeof...(mpl::vector<S0,S2,S3>>::type

would produce 1 instantiation of:

package_range_c<std::size_t,0,3>

whereas the int_list.hpp code would, IIUC, produce the same
instantiations for the T's as well as the S's.

-regards,
Larry

Dominik Charousset

unread,
May 14, 2014, 1:53:01 AM5/14/14
to bo...@lists.boost.org


> On 11 May 2014, at 09:36 pm, Larry Evans wrote
>
> Hi Dominik,
>
> On 05/08/14 12:30, Dominik Charousset wrote post
> http://article.gmane.org/gmane.comp.lib.boost.devel/250747
> including:
> [snip]
>>
>> [3] https://github.com/Neverlord/boost.actor/blob/a0cab41e2946df7d751c59dfead0c2122da0fb77/boost/actor/detail/int_list.hpp
>
> However, I have a question about the implementation.
>
> https://github.com/Neverlord/boost.actor/blob/a0cab41e2946df7d751c59dfead0c2122da0fb77/boost/actor/detail/int_list.hpp#L83
>
> uses a recursive call using a List<typename ...Ts> which is 1 shorter
> than the argument list, List<T0, Ts...>.
> Why not just pass sizeof...(T0, Ts...):
>
> http://en.cppreference.com/w/cpp/language/sizeof...
>
> and keep adding indices while decreasing this sizeof value,
> as done here:
>
> http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/package_range_c.hpp
>
> in the package_range_c template class where:
>
> Start value would be 0
> and Finish value would be sizeof...(T0, Ts...)
>
> It achieves the same result, but without producing unneeded
> instantiations. For example:
>
> package_range_c<std::size_t,0,sizeof...(mpl::vector<T0,T2,T3>>::type
> package_range_c<std::size_t,0,sizeof...(mpl::vector<S0,S2,S3>>::type
>
> would produce 1 instantiation of:
>
> package_range_c<std::size_t,0,3>
>
> whereas the int_list.hpp code would, IIUC, produce the same
> number of instantiations for the T's and S's.
>
> Wouldn't using the sizeof... method be easier to understand
> as well as produce few instantions?

Reviewing the code again, I think there's really no good reason to recurse over Ts. Doing the unrolling in il_indices recursively with only two specializations is a simple design, but the instantiations of type_list are indeed unnecessary. Also, the dependency to type_list could be dropped when unrolling based on sizeof....


> -regards,
> Larry
>
> NOTE: I tried to post to the newsgroup; however, apparently my
> post got lost :(

Let's hope the list is working again...

Charousset, Dominik

unread,
May 14, 2014, 2:01:35 AM5/14/14
to bo...@lists.boost.org
Lets hope the mail arrives this time ...

bo...@lists.boost.org
[129.79.39.203] #<[129.79.39.203] #5.0.0 smtp; 5.4.7 - Delivery expired (message too old) [Default] 451-'4.3.5 Server configuration problem' (delivery attempts: 76)> #SMTP#

________________________________________
From: Dominik Charousset [dominik.c...@haw-hamburg.de]
Sent: Friday, May 09, 2014 14:18
To: bo...@lists.boost.org
Subject: Re: [boost] Is there any interest in a library for actor programming? [preliminary submission]

On 09.05.2014, at 10:52, Jan Herrmann <jherr...@gmx.de> wrote:
On 08.05.2014 19:30, Dominik Charousset wrote:
>> Hi all,
>>
>>
>> attached you'll find the first preliminary submission for Boost.Actor as ZIP file along with the Manual in PDF version. You currently still need CMake, a Boost.Jam build file will follow. The project is hosted at GitHub:https://github.com/Neverlord/boost.actor
>
> As far as I understand a library with LGPL can not be part of boost (see www.boost.org/development/requirements.html ). So the it should be changed.

Yes, we would switch the license to the Boost License should it become accepted.


>> To state the obvious: we [1] took our time, but not because we are not taking the boost submission serious. In fact, the opposite is true. We did refine libcppa (which is the base for Boost.Actor) over the last months based on community feedback - feedback from this mailing list, last year's C++Now, GitHub, and libcppa's mailing list. However, we are not just trying to lift our library into Boost. We want Boost.Actor to fit into Boost as good as possible - and we did significant changes to the API (see below), which also took time. Furthermore, we think performance is key when providing a native actor system. Boost.Actor/libcppa has now reached a level of performance with the latest version that lives up to our expectations - and hopefully to the expectations of (future) users as well. A brief performance evaluation [2] is attached. The graphs still mention 'libcppa' instead of Boost.Actor.
>>
>> I hope the lack of Boost.Jam support is not too much of an issue - I thought it would be a good idea to post the preliminary submission before the C++Now (you can meet me there!), to get people time to play with Boost.Actor beforehand.
>>
>>
>> *Differences between Boost.Actor and libcppa*
>>
>> If you don't have any experience with libcppa, you can simply skip this. The most visible change is the removal of any_tuple and cow_tuple. The COW tuple implementation of libcppa is in our opinion not general enough and is too intermeshed with the type system. Instead, Boost.Actor provides the class `message` that is an opaque container from a user's point of view. Also, the pattern matching has been reduced to a minimal DSL for defining message handlers. The separate DSL for guard expressions is gone completely (a similar functionality still exists though). Since our pattern matching only worked with messages/any_tuples, we don't see too much use of it outside of Boost.Actor. We are still hoping for native pattern matching in C++ (N3449 proposed this a while ago) in which case our DSL would become unnecessary anyways. As a side-effect of removing all these parts, Boost.Actor has become a streamlined version of libcppa that is easier to grasp and that will be easier to ma
i
> ntain i
> n the long run as well.
>>
>>
>> *Boost.Actor depends on...*
>>
>> variant, optional, none, string_algorithms, intrusive_ptr, thread (currently as header-only dependency), context/coroutine (for cooperatively scheduled blocking actors). Some examples also require program_options.
>>
>>
>> *Boost.Actor does NOT use...*
>>
>> (1) MPL. Boost.Actor uses a ludicrous amount of metaprogramming based on boost::actor::detail::type_list. I've tried to port it to MPL and wasted almost two days doing so. MPL is a great C++ library. Unfortunately, C++98, not C++11. Even after adding variadic helpers to reduce the amount of template instantiations, it would still explode and fail to compile. I've stopped after writing half the size of the current type_list utility functions and still wasn't able to reduce the amount of template instantiations significantly enough. That being said, I am looking forward to the GSoC project for MPL11.
>>
>> (2) Serialization. The first and most obvious problem I have with this library is the lack of a portable binary archive. String serialization is sufficient for a lot of applications, but the performance hit for both networking overhead and the string serialization itself is not acceptable in an actor system. Furthermore, simply adding such a binary archive would not be enough. The library does not give you a platform-independent representation of the type names, which is crucial. Also, one cannot create an instance of a type given only its type name and then deserialize its values from a network stream (I was thinking of ETI::key_register using the uniform names and ETI::find, but it only solves a part of the problem). Adding all of these capabilities on top of boost.serialization plus writing a portable binary archive (or maybe use something like EOS - http://epa.codeplex.com/) would probably result in more code and most likely in a more complicated design, i.e., would be
> harder to maintain. Maybe I miss the forest for the trees here and some experienced boost.serialization user knows a straightforward way I don't see. However, maybe there is interest in extending boost.serialization. I'd be happy to work on patches for adding uniform names, etc.
>>
>> (3) Boost.Asio. There is definitely potential to port the low-level parts of the middleman to Asio, I think. These changes would be transparent to the user, though, since users really only use the broker and can forget about the rest.
>>
>>
>> *Separating parts of Boost.Actor?*
>>
>> Vicente J. Botet Escriba suggested to separate some parts of library. Namely the constexpr atom() [the other parts he suggested were removed, btw]. Aside from that, there are some C++11 utility functions that I think would be useful for other developers as well. Namely int_list [3] which can be used to create indices for variadic types such as tuples to allow users to apply the values of a tuple to a functor with apply_args [4]. type_list [5] is a powerful tool too, but I think this functionality goes to MPL11 anyways. Something that might be worth lifting to the boost namespace is unit [6], which makes metaprogramming (for me) a lot easier by providing an easy way of lifting void to something useful and don't need to worry whether or not it might end up in a tuple or variant. MPL already has void_t, but it doesn't seem to be indented to be used the way I use unit. For binary serialization of floats, there is IEEE 754 packing/unpacking [6] that is based on http://beej.us/g
u
> ide/bgn
> et/examples/pack2.c
>
> What is the difference from your int_list and std::integer_sequence (http://en.cppreference.com/w/cpp/utility/integer_sequence) ?

The difference is: integer_sequence didn't exist when I wrote int_list. But it's good to know that there's a standard way to do it in C++14. Thanks for the hint.

By the way, is there any policy regarding C++11 in Boost? Should we just skip it and directly aim for C++14? The code base is currently C++11 compliant. Switching to C++14 would make a thing or two easier (i.e. I could remove some code).

Larry Evans

unread,
May 14, 2014, 2:48:29 PM5/14/14
to bo...@lists.boost.org
On 05/17/13 16:26, Charousset, Dominik wrote:> Hi,
>
> is there any interest in a library for actor programming?
>
> The library we've developed is a C++11 open source library named
> "libcppa". It is currently released under LGPL2, but re-releasing
> the library under the boost license is not an issue. You'll find all
> important links and ressources either under http://libcppa.org or on
> the GitHub project page: https://github.com/Neverlord/libcppa,
[snip]
I tried following the steps described here:

https://github.com/Neverlord/boost.actor

in the README.md; however, apparently my bash interpreter is not the
same as yours:

~/prog_dev/boost/sandbox/boost.actor $ echo $BOOST_ROOT
/home/evansl/prog_dev/boost/boost-modular/modular-boost
~/prog_dev/boost/sandbox/boost.actor $ ./configure
./configure: 94: ./configure: [[: not found
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found g++ version 4.8

-- Looking for C++ include valgrind/valgrind.h
-- Looking for C++ include valgrind/valgrind.h - found
-- Build type:
CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1202 (message):
Unable to find the requested Boost libraries.

Boost version: 1.56.0

Boost include path:
/home/evansl/prog_dev/boost/boost-modular/modular-boost

The following Boost libraries could not be found:

boost_system
boost_context
boost_coroutine
boost_thread

No Boost libraries were found. You may need to set BOOST_LIBRARYDIR
to the
directory containing Boost libraries or BOOST_ROOT to the location of
Boost.
Call Stack (most recent call first):
CMakeLists.txt:235 (find_package)

.
.
.

My OS info is:

~/prog_dev/boost/sandbox $ uname -a
Linux evansl-Inspiron-531 3.2.0-61-generic #93-Ubuntu SMP Fri May 2
21:31:50 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

I tried modifying the configure script by replacing the [[...]] with
[...]; however, then I got another error:

~/prog_dev/boost/sandbox/boost.actor $ ./configure
./configure: 94: [: /C:\nppdf32Log\debuglog.txt: unexpected operator
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
.
.
.

I've no idea what to do to solve this problem :(

-regards,
Larry

Larry Evans

unread,
May 14, 2014, 3:23:48 PM5/14/14
to bo...@lists.boost.org
On 05/14/14 13:48, Larry Evans wrote:
> On 05/17/13 16:26, Charousset, Dominik wrote:> Hi,
> >
> > is there any interest in a library for actor programming?
> >
> > The library we've developed is a C++11 open source library named
> > "libcppa". It is currently released under LGPL2, but re-releasing
> > the library under the boost license is not an issue. You'll find all
> > important links and ressources either under http://libcppa.org or on
> > the GitHub project page: https://github.com/Neverlord/libcppa,
> [snip]
> I tried following the steps described here:
>
> https://github.com/Neverlord/boost.actor
>
> in the README.md; however, apparently my bash interpreter is not the
> same as yours:
>
> ~/prog_dev/boost/sandbox/boost.actor $ echo $BOOST_ROOT
> /home/evansl/prog_dev/boost/boost-modular/modular-boost
> ~/prog_dev/boost/sandbox/boost.actor $ ./configure
> ./configure: 94: ./configure: [[: not found
> -- The C compiler identification is GNU
Changed 1st line of configure to:

#!/bin/bash

and now there's no error with the [[...]]. Apparently, on
your system, sh is same as bash; however, on mine, I guess
they're different.

However, still getting the errors about not finding boost libraries:

CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1202 (message):
Unable to find the requested Boost libraries.

Boost version: 1.56.0

Boost include path:
/home/evansl/prog_dev/boost/boost-modular/modular-boost

The following Boost libraries could not be found:

boost_system
boost_context
boost_coroutine
boost_thread




Charousset, Dominik

unread,
May 14, 2014, 3:58:18 PM5/14/14
to bo...@lists.boost.org
Yes, sh is an alias for bash on my test machines. I fixed the configure script in the master branch.

The FindBoost script supports hints about search paths, in particular BOOST_LIBRARYDIR might be useful: http://www.cmake.org/cmake/help/git-master/module/FindBoost.html. Hope that helps.


________________________________________
From: Boost [boost-...@lists.boost.org] on behalf of Larry Evans [cpplj...@suddenlink.net]
Sent: Wednesday, May 14, 2014 21:23
To: bo...@lists.boost.org
Subject: Re: [boost] Is there any interest in a library for actor programming?

Larry Evans

unread,
May 15, 2014, 4:14:14 PM5/15/14
to bo...@lists.boost.org
On 05/14/14 14:58, Charousset, Dominik wrote:
> Yes, sh is an alias for bash on my test machines. I fixed the configure script in the master branch.
>
> The FindBoost script supports hints about search paths, in particular BOOST_LIBRARYDIR might be useful: http://www.cmake.org/cmake/help/git-master/module/FindBoost.html. Hope that helps.
>
>
I tried the attached wrapper around boost.actor/configure; however,
despite setting all the relevant environment variables, cmake still
fails to find the boost libraries:

~/prog_dev/boost/sandbox $ . boost.actor.configure.sh
("BOOST_ROOT=" "/home/evansl/prog_dev/boost/boost-modular/modular-boost")
("Boost_DIR=" "/home/evansl/prog_dev/boost/boost-modular/modular-boost")
("BOOST_INCLUDEDIR="
"/home/evansl/prog_dev/boost/boost-modular/modular-boost")
("BOOST_LIBRARYDIR="
"/home/evansl/prog_dev/boost/boost-modular/modular-boost")
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found g++ version 4.8

-- Looking for C++ include valgrind/valgrind.h
-- Looking for C++ include valgrind/valgrind.h - found
-- Build type:
CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1202 (message):
Unable to find the requested Boost libraries.

Boost version: 1.56.0

Boost include path:
/home/evansl/prog_dev/boost/boost-modular/modular-boost

The following Boost libraries could not be found:

boost_system
boost_context
boost_coroutine
boost_thread

No Boost libraries were found. You may need to set BOOST_LIBRARYDIR
to the
directory containing Boost libraries or BOOST_ROOT to the location of
Boost.
Call Stack (most recent call first):
CMakeLists.txt:235 (find_package)


CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1202 (message):
Unable to find the requested Boost libraries.

Boost version: 1.56.0

Boost include path:
/home/evansl/prog_dev/boost/boost-modular/modular-boost

The following Boost libraries could not be found:

boost_program_options

No Boost libraries were found. You may need to set BOOST_LIBRARYDIR
to the
directory containing Boost libraries or BOOST_ROOT to the location of
Boost.
Call Stack (most recent call first):
examples/CMakeLists.txt:4 (find_package)


-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)

====================| Build Summary |====================

Build type: RelWithDebInfo
Debug mode: no
Log level: none
Context switching: yes
Valgrind: yes
Build examples: yes
Build unit tests: yes
Build static: no
Bulid static only: no
Build OpenCL: no
With mem. mgmt.: yes

CXX: /usr/bin/c++
CXXFLAGS: -std=c++11 -Wextra -Wall -pedantic
-ftemplate-backtrace-limit=0 -pthread -O2 -g
LD_DIRS:
LIBRARIES:
Boost_COROUTINE_LIBRARY-NOTFOUND;Boost_CONTEXT_LIBRARY-NOTFOUND;Boost_SYSTEM_LIBRARY-NOTFOUND

Source directory: /home/evansl/prog_dev/boost/sandbox/boost.actor
Build directory: /home/evansl/prog_dev/boost/sandbox/boost.actor/build
Executable path: /home/evansl/prog_dev/boost/sandbox/boost.actor/build/bin
Library path: /home/evansl/prog_dev/boost/sandbox/boost.actor/build/lib
Install prefix: /usr/local

Boost: /home/evansl/prog_dev/boost/boost-modular/modular-boost

===========================================================

CMake Error: The following variables are used in this project, but they
are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the
CMake files:
Boost_CONTEXT_LIBRARY (ADVANCED)
linked by target "libboost_actor" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor
linked by target "announce_1" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_2" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_3" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_4" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_5" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "aout" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dancing_kirby" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dining_philosophers" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "distributed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_chat" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_server" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "hello_world" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "typed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
Boost_COROUTINE_LIBRARY (ADVANCED)
linked by target "libboost_actor" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor
linked by target "announce_1" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_2" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_3" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_4" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_5" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "aout" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dancing_kirby" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dining_philosophers" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "distributed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_chat" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_server" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "hello_world" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "typed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
Boost_PROGRAM_OPTIONS_LIBRARY (ADVANCED)
linked by target "announce_1" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_2" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_3" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_4" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_5" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "aout" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dancing_kirby" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dining_philosophers" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "distributed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_chat" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_server" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "hello_world" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "typed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
Boost_SYSTEM_LIBRARY (ADVANCED)
linked by target "libboost_actor" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor
linked by target "announce_1" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_2" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_3" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_4" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "announce_5" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "aout" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dancing_kirby" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "dining_philosophers" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "distributed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_chat" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "group_server" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "hello_world" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples
linked by target "typed_calculator" in directory
/home/evansl/prog_dev/boost/sandbox/boost.actor/examples

-- Configuring incomplete, errors occurred!
~/prog_dev/boost/sandbox $


Any cmake experts out there know what I'm doing wrong?

TIA.

-regards,
Larry


boost.actor.configure.sh

Tim Keitt

unread,
May 15, 2014, 4:32:41 PM5/15/14
to bo...@lists.boost.org
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


I'm a bit of a lurker on this list but your post got me curious. The actor
model looks quite appealing. However a bit of self study led me to
http://www.theron-library.com/. Their code examples look more like
something I would use. I'd be curious to know how you see the differences.


Cheers,
THK

--
http://www.keittlab.org/

Larry Evans

unread,
May 15, 2014, 4:39:09 PM5/15/14
to bo...@lists.boost.org
Do I need to create a link library for each of these boost libraries?
I assumed the above error messages meant it could find the include files
for the libraries, but I noticed system and context have build/Jamfiles
which, after a brief glance, look like they create a link library.

Matthias Vallentin

unread,
May 15, 2014, 7:53:25 PM5/15/14
to bo...@lists.boost.org
(Disclaimer: I'm a libcppa user for quite a while now.)

> attached you'll find the first preliminary submission for Boost.Actor
> as ZIP file along with the Manual in PDF version.

I would like to express my full support for Boost.Actor. The number one
reason why I believe we need the library in Boost, is that the library
raises the level abstraction for concurrent and network-transparent
message passing in a type-safe manner. It provides a framework allowing
users to efficiently harness (i) all available cores on a modern
multi-core machine, (ii) general-purpose clusters, and (iii) the compute
power of graphics card via OpenCL [1].

My own experiences with libcppa:

- Quick round-trips on mailing list and during bug reports

- Low CPU overhead (<=5%)

- Works robust and stable since 0.9

In the past, I attempted to build a similar abstraction out of 0mq and
Boost.Asio, with mildly put, limited success. Therefore I am thrilled to
see someone attempting to implement the actor model natively The Right
Way.

By adopting the library in Boost, users would receive a tool to express
their concurrent and distributed programs while focussing on the
challenges of their domain, as opposed to grappling with low-level
intricacies of data structure synchronization and threading. Personally,
I found it immensely productive to not having to worry about data races
anymore, as these are eradicated by design.

Matthias

[1] This is a feature of libcppa and not planned for Boost.Actor,
although the functionality should remain in some form.

Charousset, Dominik

unread,
May 16, 2014, 1:12:47 AM5/16/14
to bo...@lists.boost.org
Yes, you need to create link libraries for those libraries. You could strip the Boost.Thread dependency from the CMake file (as long as you have the headers), because Boost.Actor only needs some header-only parts from Boost.Thread. For the other libraries, you need to have a compiled library.

________________________________________
From: Boost [boost-...@lists.boost.org] on behalf of Larry Evans [cpplj...@suddenlink.net]
Sent: Thursday, May 15, 2014 22:39
To: bo...@lists.boost.org
Subject: Re: [boost] Is there any interest in a library for actor programming?

Charousset, Dominik

unread,
May 16, 2014, 2:01:37 AM5/16/14
to bo...@lists.boost.org
> I'm a bit of a lurker on this list but your post got me curious. The actor
> model looks quite appealing. However a bit of self study led me to
> http://www.theron-library.com/. Their code examples look more like
> something I would use. I'd be curious to know how you see the differences.


Theron has a completely different design based on classes alone. You have to maintain your Framework and pass it around all the times. You have to register your message handlers using member function pointers. You can't change your behavior dynamically, which in turn means you cannot build a simple state machine. The Boost.Actor abstraction is more powerful and at the same time easier to use. Theron only has untyped actor handles, meaning that there's a whole class of errors that your compiler could catch at compile time rather than having them fired at runtime. The Theron way of doing things will cause you to write more boilerplate code, since you have to write a class and you have to have a constructor taking the Framework as reference, etc.

Boost.Actor is a C++11 library with an emphasis on a clean library design that requires as little boilerplate code as possible. If you prefer class-based designs, you can just use classes in Boost.Actor as well. You simply derive from event_based_actor and have each actor have its own class. In my opinions, classes are overused and most actors don't need a class. But that's a decision that's up to the user of Boost.Actor.

Bjorn Reese

unread,
May 17, 2014, 4:17:25 AM5/17/14
to bo...@lists.boost.org
I have a couple of major concerns with the current submission, and I am
going to suggest some substantial changes. I hope that it does not
discourage you too much.

I am going to suggest that:

1. The library is broken into more fundamental building-blocks (which
is what both Boost and the C++ standard is all about.)
2. A more flexible data flow architecture is adopted.
3. More use of existing Boost libraries.

I recognize three more fundamental building-blocks in the current
submission: active objects, messaging middleware, and data flow. I am
not against a higher level actor API, but the fundamentals need to be
in place first.

Building-blocks
---------------

Boost.Actor implements a distributed mailbox-based actor model. While
this is a building-block to some users, it is not fundamental. It
conflates the actor with distribution.

I suggest that you start with a non-distributed actor model. This is
simply an active object with an incoming message queue. This can be
used its own right without distribution and mailboxes. Many applications
have classes with a working thread inside them, and active objects
should strive to replace these classes [1].

Active objects have two important variation points: scheduling and the
queue type. Regarding scheduling there is a C++ standards proposal that
should be considered [2]. There is a GSoC project about this [3]. For
the distributed case, boost::asio::io_service also has to be considered.

There is also work done on message queues. We already have some in
Boost.Lockfree, or the wait-free multi-producer queue in the
Boost.Atomic examples, as well as sync_queue in Boost.Thread.

Architecture
------------

Once we have got active objects, the question is how do we connect them?
The variation points here are routing and transmission.

The mailbox approach is too simple for many applications. Partly
because it is too limited in some regards (e.g. push-only) and too
flexible in other regards (e.g. you cannot have fine-grained
access control or restricted visibility.)

There are several flow-based approaches that should be considered:
Boost.Iostreams has all the required concepts in place. There was a
Boost.Dataflow GSoC project [4] some years ago. There is a C++ standards
proposal [5] about C++ pipelines. See also the ZeroMQ guide [6] for
various examples.

Boost.Actor implements its own network protocol, but you often need to
integrate with an existing protocol, such as MQTT [7] or DDS [8].

We can add distribution by having proxies. The proxies can hide the
details about routing (e.g. actors may change location due to load
balancing or migration,) and network protocol.

Library reuse
-------------

Although Boost.Actor reuses other Boost libraries, it has implemented
quite a lot that either exists in other Boost libraries, or that could
be moved to those.

You have already mentioned that you do not use MPL, Serialization, and
Asio, so I will not delve into these, other than saying that I believe
that having your own socket implementation instead of using Boost.Asio
is a show-stopper.

Apart from these three, there are other libraries that should be
considered. Boost.Actor has:

o Own continuations instead of Boost.Thread (future::then)
o Own producer-consumer queue instead of Boost.Lockfree
o Own logging framework instead of Boost.Log, although I would
prefer not having logging in a library at all.
o Own UUID instead of Boost.UUID
o Own time duration instead of Boost.Chrono

Then there are code that could be refactored to other Boost libraries
so they can be used in other contexts. For example:

o Stacktrace dumper
o RIPEMD hash function
o MAC address


[1]
http://www.drdobbs.com/parallel/prefer-using-active-objects-instead-of-n/225700095
[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3785.pdf
[3] http://cs.mcgill.ca/~iforbe/
[4] http://www.dancinghacker.com/code/dataflow/index.html
[5] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3534.html
[6] http://zguide.zeromq.org/page:all
[7] http://mqtt.org/
[8] http://portals.omg.org/dds/

Dominik Charousset

unread,
May 17, 2014, 11:56:59 AM5/17/14
to bo...@lists.boost.org
On Sat, May 17, 2014 at 10:17:25AM +0200, Bjorn Reese wrote:
> I have a couple of major concerns with the current submission, and I am
> going to suggest some substantial changes. I hope that it does not
> discourage you too much.
>
> I am going to suggest that:
>
> 1. The library is broken into more fundamental building-blocks (which
> is what both Boost and the C++ standard is all about.)
> 2. A more flexible data flow architecture is adopted.
> 3. More use of existing Boost libraries.
>
> I recognize three more fundamental building-blocks in the current
> submission: active objects, messaging middleware, and data flow. I am
> not against a higher level actor API, but the fundamentals need to be
> in place first.

Thank you for taking your time for this thorough comment. However, I have to
say I disagree on many levels. First of all: C++ is not about having a low
level of abstraction. C++ is about having the highest level of abstraction
possible without sacrificing performance. What you are suggesting is to not
having an actor library in Boost. You want to have a low-level active object
library with low-level networking primitives.


> Building-blocks
> ---------------
>
> Boost.Actor implements a distributed mailbox-based actor model. While
> this is a building-block to some users, it is not fundamental. It
> conflates the actor with distribution.

An actor *is* the fundamental primitive! We are talking about an implementation
of the actor model. The whole point of the actor model is to have software
entities that abstract over physical deployment. Actors are *not* the same
thing as active objects. There is obviously overlap of these two models, but
the actor modle is more general, i.e., describes a higher level of abstraction.


> I suggest that you start with a non-distributed actor model. This is
> simply an active object with an incoming message queue. This can be
> used its own right without distribution and mailboxes. Many applications
> have classes with a working thread inside them, and active objects
> should strive to replace these classes [1].

A non-distributed actor model? I think what you really want to say here is: you
want users to be able to use the lightweight actor implementation and the
work-stealing scheduler without having link-dependencies to networking
infrastructure they don't use. Can you agree on that? That's a fair point and
useful indeed. Well, here's the thing: there is nothing baked into the actor
primitive that would require such a dependency. The software design is fully
modular. Separate the middleman, move publish/remote_actor to a different
namespace, ship it separately, done. All you have to do to extend boost.actor
is to provide an implementation for actor_proxy. Behind the scenes, you can do
all kinds of stuff: networking, OpenCL-binding (that's how it's done in
licppa), you name it.


> Active objects have two important variation points: scheduling and the
> queue type. Regarding scheduling there is a C++ standards proposal that
> should be considered [2]. There is a GSoC project about this [3]. For
> the distributed case, boost::asio::io_service also has to be considered.

I know the Executor proposal and I think it's too basic to be useful for
anything other than implementing std::async. ThreadPool implementations in
general do work-sharing, whereas boost.actor implements work-stealing. The
latter yields superior performance in almost all use cases.

I wouldn't mind moving the scheduler to it's own namespace to allow other
projects to build on top of that. The scheduler uses the interfaces resumable
and execution_unit, so there aren't any actor-specific types.


> There is also work done on message queues. We already have some in
> Boost.Lockfree, or the wait-free multi-producer queue in the
> Boost.Atomic examples, as well as sync_queue in Boost.Thread.

Show me a queue that outperforms single_reader_queue and I'll take it. Keep in
mind though, that the enqueue operation uses only *a single* compare-and-swap
operation [1]. I don't see how you can outperform that. Did you have a look at
the performance evaluation? In particular the N:1 communication? This queue
scales up to 63 concurrent writers without a measurable perforance hit. I'm not
passionate about implementations details, though. Show me a queue that performs
even better in boost.actor and I'll take it.


> Architecture
> ------------
>
> Once we have got active objects, the question is how do we connect them?
> The variation points here are routing and transmission.

Again, this library is not about active objects. It's about actors.


> The mailbox approach is too simple for many applications. Partly
> because it is too limited in some regards (e.g. push-only) and too
> flexible in other regards (e.g. you cannot have fine-grained
> access control or restricted visibility.)
>
> There are several flow-based approaches that should be considered:
> Boost.Iostreams has all the required concepts in place. There was a
> Boost.Dataflow GSoC project [4] some years ago. There is a C++ standards
> proposal [5] about C++ pipelines. See also the ZeroMQ guide [6] for
> various examples.

All of that is true and it's damn good that libcppa/boost.actor it is the way
it is. I'm sorry, but again: this is an actor library. If you want to fiddle
with low-level networking, this is not the library you are looking for. There
was a talk at this year's C++Now about libcppa and VAST. VAST is a distributed,
interactive database allowing you to do full-text search over gigabytes (that's
only what's working right now, VAST aims for scanning petabytes!) of data in
realtime, i.e., sub-second round-trip times. Matthias Vallentin gave a great
talk about his design - purely based on libcppa actors! The flow-control needed
to do the indexing in realtime (which btw is a constant stream of events) is
build *on top* of actors. Not the other way around. Matthias tried a ZeroMQ
design first, you might want to ask him how well that went... Having a low
level of abstraction does by no means implies good performance or scalability.

This is a fundamental design decision and I want people to write code on a
sane, reasonable level of abstraction. If you can't reason about your code, it
doesn't matter how "efficient" your building blocks are. The actor model is so
appealing because it *takes away* the complexity of distributed runtime
environments. And guess what? You can get insane performance out of actor
systems with less headache. If you don't believe me that actor systems scale,
go have a look at the selection of Production Users at http://akka.io/ and see
for yourself. Those companies pick Scala and Java over C++ for
*performance-critical applications* because of the actor model.


> Boost.Actor implements its own network protocol, but you often need to
> integrate with an existing protocol, such as MQTT [7] or DDS [8].

You can integrate any network protocol by using brokers:
http://neverlord.github.io/boost.actor/manual/#sec45

There's an example how to integrate Google Protobuf in libcppa:
https://github.com/Neverlord/libcppa/tree/master/examples/remote_actors


> We can add distribution by having proxies. The proxies can hide the
> details about routing (e.g. actors may change location due to load
> balancing or migration,) and network protocol.

That's exactly how it's done.


> Library reuse
> -------------
>
> Although Boost.Actor reuses other Boost libraries, it has implemented
> quite a lot that either exists in other Boost libraries, or that could
> be moved to those.
>
> You have already mentioned that you do not use MPL, Serialization, and
> Asio, so I will not delve into these, other than saying that I believe
> that having your own socket implementation instead of using Boost.Asio
> is a show-stopper.

Aren't peer reviews about interface design, documentation, and testing? I
cannot believe an implementation detail can be a show-stopper. To be quite
frank, I just don't care about it. I do care about performance. As long as Asio
delivers equal or better performance, I'll migrate sooner rather than later.
But to me, this is an unimportant implementation detail.


> Apart from these three, there are other libraries that should be
> considered. Boost.Actor has:
>
> o Own continuations instead of Boost.Thread (future::then)

Futures don't deal with messages and know nothing about the scheduling in
boost.actor. The syntax is similar, but the continuations used in boost.actor
are syntactic sugar for the message pasing underneath.


> o Own producer-consumer queue instead of Boost.Lockfree

The producer-consumer queue used in the scheduler ist based on an excellent Dr.
Dobb's article of Herb Sutter [2] and performs reasonably well. Maybe there's
interest in adding it to Boost.


> o Own logging framework instead of Boost.Log, although I would
> prefer not having logging in a library at all.

As a user, you won't have logging. It's purely for debugging purposes and not
compiled unless you define the macros to do so. It really should be in the
detail namespace though.


> o Own UUID instead of Boost.UUID

Can this library give me the UUID of the first hard drive? That's the only use
case I have for this. The generators in the documentation don't mention
anything like this.


> o Own time duration instead of Boost.Chrono

The reason is the same why I don't ues std::chrono::duration: they are
templated. I need a generic duration type that has the unit as member rather
than as template parameter and also can be invalid. Maybe I could replace this
with optional<std::chrono::milliseconds> in the future, though it would mean to
hardcode the maximum resolution.


> Then there are code that could be refactored to other Boost libraries
> so they can be used in other contexts. For example:
>
> o Stacktrace dumper
> o RIPEMD hash function
> o MAC address

Agree, except for the stacktrace dumper. Unless someone else refactores it to
work on Windows.


I hope I could convince you that you are not requesting changes to boost.actor.
What you want is a different library entirely. An actor *is* the fundamental
building block, that's what actor programming is all about.



[1] http://libcppa.blogspot.de/2011/04/mailbox-part-1.html
[2] http://www.drdobbs.com/parallel/writing-a-generalized-concurrent-queue/211601363

Larry Evans

unread,
May 17, 2014, 5:06:52 PM5/17/14
to bo...@lists.boost.org
On 05/17/14 10:56, Dominik Charousset wrote:
> On Sat, May 17, 2014 at 10:17:25AM +0200, Bjorn Reese wrote:
>> I have a couple of major concerns with the current submission, and I am
>> going to suggest some substantial changes. I hope that it does not
>> discourage you too much.
>>
>> I am going to suggest that:
>>
>> 1. The library is broken into more fundamental building-blocks (which
>> is what both Boost and the C++ standard is all about.)
>> 2. A more flexible data flow architecture is adopted.
>> 3. More use of existing Boost libraries.
>>
>> I recognize three more fundamental building-blocks in the current
>> submission: active objects, messaging middleware, and data flow. I am
>> not against a higher level actor API, but the fundamentals need to be
>> in place first.
>
> Thank you for taking your time for this thorough comment. However, I have to
> say I disagree on many levels. First of all: C++ is not about having a low
> level of abstraction. C++ is about having the highest level of abstraction
> possible without sacrificing performance. What you are suggesting is to not
> having an actor library in Boost. You want to have a low-level active object
> library with low-level networking primitives.
>
>
[snip]
Hi Dominik,

The way I read Bjorn's statement:

I am not against a higher level actor API, but the fundamentals
need to be in place first.

is that Bjorn's not objecting to a high level of abstraction; however,
he wants a lower level first on which to build the higher level. IOW,
he's not saying, as you suggest:

to not having an actor library in Boost

At least that's the way I read his post, FWIW.

-regards,
Larry

Dominik Charousset

unread,
May 18, 2014, 2:46:49 AM5/18/14
to bo...@lists.boost.org
On Sat, May 17, 2014 at 04:06:52PM -0500, Larry Evans wrote:
> The way I read Bjorn's statement:
>
> I am not against a higher level actor API, but the fundamentals
> need to be in place first.
>
> is that Bjorn's not objecting to a high level of abstraction; however,
> he wants a lower level first on which to build the higher level. IOW,
> he's not saying, as you suggest:
>
> to not having an actor library in Boost
>
> At least that's the way I read his post, FWIW.

Fair enough. I'm not subjecting the idea of having buiding blocks generalized
to allow others to build on top of it. I hope my response didn't sound
disrespectful. Still, I don't think active objects are building blocks for
actors, they're a different kind of abstraction.

Bjorn also mentioned data flow as building block. You can see the messages
going through an actor system as some kind of dataflow, but there are no
streams. This is about message oriented programming, not about streams and
dataflows. It's a different paradigm. The middleman operates on messages and
(logical) actor addresses, not on data flows.

I don't know if the middleman implementation has parts that are worth
separating. It (1) manages connections (you can do that with Asio already), (2)
dispatches messages based on logical actor addresses, (3) manages proxy
instances for remote actors, and (4) keeps a lookup table for type IDs for each
connection it has; this is only an optimization though, nothing essential.
That's about it. The serialization layer used by the middleman might be useful
to others, but it is strongly coupled with uniform_type_info. If there's any
interest in lifting this thing to its own library, I have no objections.


Please let's take the discussion to a different level. With this preliminary
submission, I wanted to get a feeling if there is interest in a Boost.Actor
library and if it can get enough momentum to eventually find a review manager.
I guess this is the question I should have asked in my original post: "Do you
think Boost should provide a high-level programming paradigm such as the actor
model and if you do, do you think the proposed design is the right one?"

I know that this is a large library. The more important it is in my opinion to
talk about concepts, API, and possibly documentation. Maybe I'm naive, but
separating parts of the library or tweaking implementation details should be
the last step, should it not?

Julian Gonggrijp

unread,
May 20, 2014, 1:05:25 PM5/20/14
to bo...@lists.boost.org
Dominik Charousset wrote:

> Please let's take the discussion to a different level. With this preliminary
> submission, I wanted to get a feeling if there is interest in a Boost.Actor
> library and if it can get enough momentum to eventually find a review manager.
> I guess this is the question I should have asked in my original post: "Do you
> think Boost should provide a high-level programming paradigm such as the actor
> model

If by "a high-level programming paradigm such as the actor model" you
mean a lock-free concurrency library with high conceptual abstraction,
then yes. I think the programming community at large, and the C++
community in particular, is dying for a solution to (hard)
concurrency that is safe and simple to use, powerful, performant as
well as general.

> and if you do, do you think the proposed design is the right one?"

I think the actor model is good, because messaging is the most
elegant solution to concurrency that I know of. However, I believe
the actor model is not the *best* possible approach to message
passing. The model is rather intricate, with monitors, links,
handles, timeouts, priorities, groups, and so on. To me it seems a
bit like the OO of concurrency: well-designed and insightful, but
needlessly complicated compared to a more general and powerful
paradigm such as generic programming. (To stick with the metaphor:
the status quo with locks and mutexes would be the concurrent
equivalent of pure procedural programming).

I think the *right* design would be a concurrent equivalent of
generic programming, where the only fundamental building blocks
should be a well-designed statically typed SPSC queue, move
semantics, a low-level thread launching utility (such as
boost::thread) and a concise generic EDSL for the linking of nodes
with queues. All further abstractions can be built on top of those
ingredients (a bit like the STL is built on top of templates). It
should allow me to do something like this:

start(readfile(input) | runlengthenc | huffmanenc | writefile(output));

At some point I want to publish a proposal for a library that does
exactly this, but I need to find more time to work on it. The good
news is that all necessary ingredients appear to already exist with
C++11, Boost.Proto and Boost.Lockfree.


As for libcppa, my impression from the manual is that it might be a
good implementation of the actor model. I dislike the option to
throw out static typing but I realise that's a matter of taste. I'm
a bit skeptical about the necessity and usefulness of built-in
network transparency, but you might be able to convince me that it
needs to be there.

>
> I know that this is a large library. The more important it is in my opinion to
> talk about concepts, API, and possibly documentation. Maybe I'm naive, but
> separating parts of the library or tweaking implementation details should be
> the last step, should it not?

I think it depends, but in this case I think separating
sublibraries would be wise. In addition to actor programming,
libcppa appears to provide three other facilities: CoW tuples,
guards and pattern matching, and platform-independent RTTI. It
would seem reasonable (and modular) to me to treat each as an
independent sublibrary and review them as such.

HTH,
Julian

Matthias Vallentin

unread,
May 20, 2014, 3:51:18 PM5/20/14
to bo...@lists.boost.org
> However, I believe the actor model is not the *best* possible approach
> to message passing. The model is rather intricate, with monitors,
> links, handles, timeouts, priorities, groups, and so on. To me it
> seems a bit like the OO of concurrency: well-designed and insightful,
> but needlessly complicated compared to a more general and powerful
> paradigm such as generic programming.

In my eyes, the well-defined failure semantics with links/monitors do
not convolute the design, but rather make the important aspect of error
handling explicit. Moreover, priorities, links, monitors are all
*opt-in* and concepts orthogonal to each other. A user can ignore them
if desired. To stick with your analogy, it sounds to me that this
modular behavior is what you'd expect from "concurrent generic
programming."

> I think the *right* design would be a concurrent equivalent of
> generic programming, where the only fundamental building blocks
> should be a well-designed statically typed SPSC queue, move
> semantics, a low-level thread launching utility (such as
> boost::thread) and a concise generic EDSL for the linking of nodes
> with queues.

The notion of *right* is very subjective, in my eyes. For example, I
personally don't want threads to be the concurrency building block in my
application. I would like to run as many threads as I have cores on my
machine, and a scheduler that maps logical tasks to a thread pool.
Today, a thread is what C++ programmers choose as concurrency primitive.
But it's a hardware abstraction and does not scale. (You cannot spawn
millions of threads efficiently.) Your application may offer a much
higher degree of logical parallelism, for whatever notion of task you
choose.

We have to start appreciating that other languages have had tremendous
success with the actor model. Skala/Akka, Clojure, Erlang, all show that
the this is an industrial-strength abstraction of not only concurrency
but also network transparency. (When programming for cloud/cluster
applications, one has to consider the latter; see below.)

> start(readfile(input) | runlengthenc | huffmanenc | writefile(output));

You describe a classic pipes-and-filters notion of concurrency here,
where presumably you'd expect your data to flow asynchronously through
the filters. Effectively, this is just syntactic sugar for message
passing, where nodes represent actors taking one type of message,
transforming it, and spitting out another (except for the sink).
Such an EDSL is orthogonal to the underlying mechanism for message
passing.

> I dislike the option to throw out static typing but I realise that's a
> matter of taste.

Yeah, I agree with you. Static typing is what makes C++ powerful. We
have to understand though, that from the perspective of a single actor,
message handling is *always* type-safe. It's only when you build larger
systems and want to test whether the protocol match. And libcppa offers
that, it's just more boilerplate. For rapid prototyping, I can
understand that one may want a weaker notion of protocol compatibility,
though.

> I'm a bit skeptical about the necessity and usefulness of built-in
> network transparency, but you might be able to convince me that it
> needs to be there.

I feel quite the opposite: network transparency is an essential aspect
of any message passing abstraction. When developing cluster-scale
applications, I would like to write my application logic once and
consider deployment an orthogonal problem. Wiring components without
needing to touch the implementation is a *huge* advantage. It enables
implementing complex and dynamic behaviors of distributed systems, for
example spawn new nodes if the system sense a compute bottleneck.

Matthias

Julian Gonggrijp

unread,
May 20, 2014, 5:15:22 PM5/20/14
to bo...@lists.boost.org
Matthias Vallentin wrote:

>> However, I believe the actor model is not the *best* possible approach
>> to message passing. The model is rather intricate, with monitors,
>> links, handles, timeouts, priorities, groups, and so on. To me it
>> seems a bit like the OO of concurrency: well-designed and insightful,
>> but needlessly complicated compared to a more general and powerful
>> paradigm such as generic programming.
>
> In my eyes, the well-defined failure semantics with links/monitors do
> not convolute the design, but rather make the important aspect of error
> handling explicit.

I will immediately concede that this is important, but I don't think
it is the only possible way.

> Moreover, priorities, links, monitors are all
> *opt-in* and concepts orthogonal to each other. A user can ignore them
> if desired. To stick with your analogy, it sounds to me that this
> modular behavior is what you'd expect from "concurrent generic
> programming."

Yes, I think you are right. So much for my analogy, then. Thanks for
pointing this out to me. :-)

>
>> I think the *right* design would be a concurrent equivalent of
>> generic programming, where the only fundamental building blocks
>> should be a well-designed statically typed SPSC queue, move
>> semantics, a low-level thread launching utility (such as
>> boost::thread) and a concise generic EDSL for the linking of nodes
>> with queues.
>
> The notion of *right* is very subjective, in my eyes.

Of course! No denying that.

> For example, I
> personally don't want threads to be the concurrency building block in my
> application. I would like to run as many threads as I have cores on my
> machine, and a scheduler that maps logical tasks to a thread pool.
> Today, a thread is what C++ programmers choose as concurrency primitive.
> But it's a hardware abstraction and does not scale. (You cannot spawn
> millions of threads efficiently.) Your application may offer a much
> higher degree of logical parallelism, for whatever notion of task you
> choose.

In the approach I proposed threads would be fundamental building
blocks of the framework, but they do not need to be building blocks
in your application. In fact, there is a fairly straightforward way
to implement a worker pool with a scheduler as an abstraction on top
of the fundamental building blocks. Your application could create the
same network of nodes and queues and feed it into the abstraction of
the scheduled worker pool instead of directly into a thread launcher,
or even take a hybrid approach.

>
> We have to start appreciating that other languages have had tremendous
> success with the actor model. Skala/Akka, Clojure, Erlang,

I do appreciate that! In fact this is the main reason I believe the
actor model is *good*, and learning about Erlang and the actor model
caused me to look into SPSC queues. I just think it is possible to do
*even better*.

> all show that
> the this is an industrial-strength abstraction of not only concurrency
> but also network transparency. (When programming for cloud/cluster
> applications, one has to consider the latter; see below.)
>
>> start(readfile(input) | runlengthenc | huffmanenc | writefile(output));
>
> You describe a classic pipes-and-filters notion of concurrency here,
> where presumably you'd expect your data to flow asynchronously through
> the filters. Effectively, this is just syntactic sugar for message
> passing, where nodes represent actors taking one type of message,
> transforming it, and spitting out another (except for the sink).
> Such an EDSL is orthogonal to the underlying mechanism for message
> passing.

All true, the same syntax could be an interface to an actor-based
framework. The syntactical interface by itself is important, though.

> [...]
>
>> I'm a bit skeptical about the necessity and usefulness of built-in
>> network transparency, but you might be able to convince me that it
>> needs to be there.
>
> I feel quite the opposite: network transparency is an essential aspect
> of any message passing abstraction. When developing cluster-scale
> applications, I would like to write my application logic once and
> consider deployment an orthogonal problem. Wiring components without
> needing to touch the implementation is a *huge* advantage. It enables
> implementing complex and dynamic behaviors of distributed systems, for
> example spawn new nodes if the system sense a compute bottleneck.

In other words, it is very powerful to work with nodes/workers/actors
without needing to know whether they are on the same processor or a
remote one. I understand this and I agree that network transparency
has value. What I'm rather skeptical about is that it needs to be
built-in by default; I would prefer it to be opt-in.

Cheers,
Julian

Dominik Charousset

unread,
May 20, 2014, 7:01:27 PM5/20/14
to bo...@lists.boost.org
>> In my eyes, the well-defined failure semantics with links/monitors do
>> not convolute the design, but rather make the important aspect of error
>> handling explicit.
>
> I will immediately concede that this is important, but I don't think
> it is the only possible way.

The hierarchical “supervision trees” (as they are called in Erlang) have proven to be a solid foundation to build applications on. That being said, Boost.Actor is in a state where it provides the basics of an actor system (Links, Monitors, etc), but is by no means “complete”. That’s why I think this is the perfect time to submit the library: there’s still room for input and contributions from the community and this is what we are looking forward to.


>> For example, I
>> personally don't want threads to be the concurrency building block in my
>> application. I would like to run as many threads as I have cores on my
>> machine, and a scheduler that maps logical tasks to a thread pool.
>> Today, a thread is what C++ programmers choose as concurrency primitive.
>> But it's a hardware abstraction and does not scale. (You cannot spawn
>> millions of threads efficiently.) Your application may offer a much
>> higher degree of logical parallelism, for whatever notion of task you
>> choose.
>
> In the approach I proposed threads would be fundamental building
> blocks of the framework, but they do not need to be building blocks
> in your application. In fact, there is a fairly straightforward way
> to implement a worker pool with a scheduler as an abstraction on top
> of the fundamental building blocks. Your application could create the
> same network of nodes and queues and feed it into the abstraction of
> the scheduled worker pool instead of directly into a thread launcher,
> or even take a hybrid approach.

In a sense, Boost.Actor is already a hybrid system. It uses a work-stealing scheduler underneath for its cooperatively scheduling, which of course uses threads. If you have actors that really need to have their own thread (e.g. because they are calling blocking APIs), you can simply opt-out of the cooperative scheduling by using spawn<detached>(...).


>> We have to start appreciating that other languages have had tremendous
>> success with the actor model. Skala/Akka, Clojure, Erlang,
>
> I do appreciate that! In fact this is the main reason I believe the
> actor model is *good*, and learning about Erlang and the actor model
> caused me to look into SPSC queues. I just think it is possible to do
> *even better*.

I don't think there is is a “best” solution when it comes to concurrency. There are amazing Haskell applications using data flow paradigms. Clojure has agents concurrently working on transactional data structures which is just great for simulations (have a look at the Clojure ant simulation from Rich Hickey). The actor model has a unique and powerful way to describe both concurrent and distributed applications. That’s why I prefer it for most applications.


>> I feel quite the opposite: network transparency is an essential aspect
>> of any message passing abstraction. When developing cluster-scale
>> applications, I would like to write my application logic once and
>> consider deployment an orthogonal problem. Wiring components without
>> needing to touch the implementation is a *huge* advantage. It enables
>> implementing complex and dynamic behaviors of distributed systems, for
>> example spawn new nodes if the system sense a compute bottleneck.
>
> In other words, it is very powerful to work with nodes/workers/actors
> without needing to know whether they are on the same processor or a
> remote one. I understand this and I agree that network transparency
> has value. What I'm rather skeptical about is that it needs to be
> built-in by default; I would prefer it to be opt-in.

It’s actually easy to separate the middleman and ship the network abstraction separately. The networking parts are not built into the actor class(es). Maybe we could use the namespace boost::actor_io for this and move the publish/remote_actor function pair as well as the brokers to this namespace (and provide it as separate library to link against).


> I think separating
> sublibraries would be wise. In addition to actor programming,
> libcppa appears to provide three other facilities: CoW tuples,
> guards and pattern matching, and platform-independent RTTI. It
> would seem reasonable (and modular) to me to treat each as an
> independent sublibrary and review them as such.

Boost.Actor is actually a redesign of libcppa, not just a port to Boost. The CowTuples are gone. I found them to be too entangled with the RTTI system and it’s just not needed for the actor programming. The guard expressions are gone, too. You still can do filtering by providing a “T -> optional<T>” functor. The guard expression library seemed neat at the time, but at the end of the day it’s making easy things complicated and had a rather lengthy implementation. The pattern matching has been reduced to be a factory for message handlers. It’s only working on messages, so there’s no point in separating it IMO. My hope is that the proposal for Type Switch / Native Pattern Matching will someday make its way to the standard, rendering any library implementation obsolete.

Larry Evans

unread,
May 22, 2014, 12:03:05 PM5/22/14
to bo...@lists.boost.org
On 05/16/14 00:12, Charousset, Dominik wrote:
> Yes, you need to create link libraries for those libraries. You could strip the Boost.Thread dependency from the CMake file (as long as you have the headers), because Boost.Actor only needs some header-only parts from Boost.Thread. For the other libraries, you need to have a compiled library.
>
> ________________________________________
> From: Boost [boost-...@lists.boost.org] on behalf of Larry Evans [cpplj...@suddenlink.net]
> Sent: Thursday, May 15, 2014 22:39
> To: bo...@lists.boost.org
> Subject: Re: [boost] Is there any interest in a library for actor programming?
>
> On 05/15/14 15:14, Larry Evans wrote:
[snip]
>> The following Boost libraries could not be found:
>>
>> boost_system
>> boost_context
>> boost_coroutine
>> boost_thread
>>
> to the
>> directory containing Boost libraries or BOOST_ROOT to the location of
>> Boost.
>
> Do I need to create a link library for each of these boost libraries?
> I assumed the above error messages meant it could find the include files
> for the libraries, but I noticed system and context have build/Jamfiles
> which, after a brief glance, look like they create a link library.
>
I created the boost libraries and tried the boost.actor configure again
and it worked. However, the subsequent make failed because compiler
could not find memcmp, as shown by the terminal session at the end of
this post. Note that I did do a `git diff` which showed the only'
difference was in the ./configure. Also, there were several
warnings.

Is there something I should do to get the make to work?

TIA.

-regards,
Larry

------------ the terminal session -------------:

~/prog_dev/boost/sandbox/boost.actor.dir $ . boost.actor.configure.sh
("BOOST_ROOT="
"/home/evansl/prog_dev/boost/boost-modular/modular-boost/install")
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found g++ version 4.8

-- Looking for C++ include valgrind/valgrind.h
-- Looking for C++ include valgrind/valgrind.h - found
-- Build type:
-- Boost version: 1.56.0
-- Found the following Boost libraries:
-- system
-- context
-- coroutine
-- thread
-- Boost version: 1.56.0
-- Found the following Boost libraries:
-- program_options
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)

====================| Build Summary |====================

Build type: RelWithDebInfo
Debug mode: no
Log level: none
Context switching: yes
Valgrind: yes
Build examples: yes
Build unit tests: yes
Build static: no
Bulid static only: no
Build OpenCL: no
With mem. mgmt.: yes

CXX: /usr/bin/c++
CXXFLAGS: -std=c++11 -Wextra -Wall -pedantic
-ftemplate-backtrace-limit=0 -pthread -O2 -g
LD_DIRS:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib
LIBRARIES:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_coroutine.so;/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_context.so;/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_system.so

Source directory:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor
Build directory:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build
Executable path:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build/bin
Library path:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build/lib
Install prefix: /usr/local

Boost:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/include

===========================================================

-- Configuring done
-- Generating done
-- Build files have been written to:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build
~/prog_dev/boost/sandbox/boost.actor.dir $ cd boost.actor
~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $ make
make[1]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[2]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
Scanning dependencies of target libboost_actor
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
[ 0%] Building CXX object
CMakeFiles/libboost_actor.dir/src/middleman_event_handler_epoll.cpp.o
[ 1%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_actor.cpp.o
[ 2%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_channel.cpp.o
[ 3%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_group.cpp.o
In file included from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/all.hpp:34:0,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/abstract_group.cpp:31:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/on.hpp:303:2:
warning: extra ';' [-Wpedantic]
};
^
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/on.hpp:309:2:
warning: extra ';' [-Wpedantic]
};
^
[ 4%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_tuple.cpp.o
[ 4%] Building CXX object CMakeFiles/libboost_actor.dir/src/acceptor.cpp.o
[ 5%] Building CXX object CMakeFiles/libboost_actor.dir/src/actor.cpp.o
In file included from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/continue_helper.hpp:36:0,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/typed_continue_helper.hpp:34,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/typed_behavior.hpp:36,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/typed_actor.hpp:38,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/spawn_fwd.hpp:38,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/local_actor.hpp:44,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/actor.cpp:37:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/on.hpp:303:2:
warning: extra ';' [-Wpedantic]
};
^
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/on.hpp:309:2:
warning: extra ';' [-Wpedantic]
};
^
In file included from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/system_messages.hpp:40:0,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/detail/response_handle_util.hpp:36,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/response_handle.hpp:44,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/blocking_actor.hpp:42,
from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/actor.cpp:38:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/io/buffer.hpp:
In function 'bool boost::actor::io::operator==(const
boost::actor::io::buffer&, const boost::actor::io::buffer&)':
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/io/buffer.hpp:237:57:
error: 'memcmp' was not declared in this scope
return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
^
make[3]: *** [CMakeFiles/libboost_actor.dir/src/actor.cpp.o] Error 1
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[2]: *** [CMakeFiles/libboost_actor.dir/all] Error 2
make[2]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[1]: *** [all] Error 2
make[1]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make: *** [all] Error 2
~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/gh-pages
remotes/origin/master
~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $ git diff
WARNING: terminal is not fully functional
- (press RETURN)
diff --git a/configure b/configure
index 71f6b42..d99231a 100755
--- a/configure
+++ b/configure
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# Convenience wrapper for easily viewing/setting options that
# the project's CMake scripts will recognize.

~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $

Larry Evans

unread,
May 22, 2014, 1:23:20 PM5/22/14
to bo...@lists.boost.org
On 05/22/14 11:03, Larry Evans wrote:
[snip]
> I created the boost libraries and tried the boost.actor configure again
> and it worked. However, the subsequent make failed because compiler
> could not find memcmp, as shown by the terminal session at the end of
> this post. Note that I did do a `git diff` which showed the only'
> difference was in the ./configure. Also, there were several
> warnings.
>
> Is there something I should do to get the make to work?
>
[snip]
I modified the configure arguments as shown in 1st attachment.
Now, at the `make` step, it aborts at the same place, but
with a message about incompatible args instead of not finding
the memcmp function. The complete terminal session is in
2nd attachment.

Should maybe the args to wmemcmp be static_cast<const wchar_t *>?

-Larry


boost.actor.configure.sh
actor.configure.make.out

Dominik Charousset

unread,
May 22, 2014, 1:56:58 PM5/22/14
to bo...@lists.boost.org
>> I created the boost libraries and tried the boost.actor configure again
>> and it worked. However, the subsequent make failed because compiler
>> could not find memcmp, as shown by the terminal session at the end of
>> this post. Note that I did do a `git diff` which showed the only'
>> difference was in the ./configure. Also, there were several
>> warnings.
>>
>> Is there something I should do to get the make to work?
>>
> [snip]
> I modified the configure arguments as shown in 1st attachment.
> Now, at the `make` step, it aborts at the same place, but
> with a message about incompatible args instead of not finding
> the memcmp function. The complete terminal session is in
> 2nd attachment.

Thank you for your patience. The function memcmp is defined in <cstring>, which was simply not included. I don’t know why I never got this error (I’ve tested on SuSE 13.1, Ubuntu 13.10, Fedora, Mac OS, MinGW @ Win7). Btw, you don’t have to pass both GCC and Clang to the configure script. I would recommend using the compiler you’ve used to build the Boost libraries to avoid running into ABI incompatibilities.

I have added the missing include in the master branch and fixed the mismatched-tags warnings as well. Hope that fixes your issues. Oh, and don’t be surprised that almost each file has changed if you’re running git pull: the license has been changed from LGPL to the Boost Software License.



Best regards,
Dominik

Larry Evans

unread,
May 23, 2014, 12:20:04 PM5/23/14
to bo...@lists.boost.org
Did a pull yesterday:

evansl@evansl-Inspiron-531:~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor$
git pull
remote: Counting objects: 359, done.
remote: Compressing objects: 100% (260/260), done.
remote: Total 359 (delta 209), reused 122 (delta 92)
Receiving objects: 100% (359/359), 320.70 KiB | 379 KiB/s, done.
Resolving deltas: 100% (209/209), done.
From https://github.com/Neverlord/boost.actor
e0411b5..e618a54 master -> origin/master
From https://github.com/Neverlord/boost.actor
* [new tag] preliminary_submission_2 -> preliminary_submission_2
Updating e0411b5..e618a54
Fast-forward
CMakeLists.txt | 4 +-
LICENCE | 525
+-------------------
boost.actor.files | 39 +-
boost/actor/abstract_actor.hpp | 32 +-
boost/actor/abstract_channel.hpp | 32 +-
.
.
.
src/yield_interface.cpp | 32 +-
unit_testing/test_broker.cpp | 32 +-
unit_testing/test_intrusive_containers.cpp | 32 +-
unit_testing/test_typed_spawn.cpp | 32 +-
276 files changed, 3215 insertions(+), 6606 deletions(-)
delete mode 100644 boost/actor/io/ipv4_acceptor.hpp
delete mode 100644 boost/actor/io/ipv4_io_stream.hpp
create mode 100644 boost/actor/io/tcp_acceptor.hpp
create mode 100644 boost/actor/io/tcp_io_stream.hpp
create mode 100644 examples/remote_actors/simple_broker.cpp
rename src/{ipv4_acceptor.cpp => tcp_acceptor.cpp} (64%)
rename src/{ipv4_io_stream.cpp => tcp_io_stream.cpp} (65%)
evansl@evansl-Inspiron-531:~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor$


Then did configure again (with just the --with-clang flag:

~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $ .
../boost.actor.configure.sh
-- The C compiler identification is GNU
-- The CXX compiler identification is Clang
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler:
/home/evansl/dwnlds/llvm/versions/3.4/configurations/Release/install/bin/clang++
-- Check for working CXX compiler:
/home/evansl/dwnlds/llvm/versions/3.4/configurations/Release/install/bin/clang++
-- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found clang++ version 3.4

-- NOTE: Automatically added -stdlib=libc++ flag, you can override this
by defining CMAKE_CXX_FLAGS (see 'configure --help')
/home/evansl/dwnlds/llvm/versions/3.4/configurations/Release/install/bin/clang++
CXXFLAGS: -std=c++11 -Wextra -Wall -pedantic
-ftemplate-backtrace-limit=0 -pthread -O2 -g
LD_DIRS:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib
LIBRARIES:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_coroutine.so;/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_context.so;/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/lib/libboost_system.so

Source directory:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor
Build directory:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build
Executable path:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build/bin
Library path:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build/lib
Install prefix: /usr/local

Boost:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/install/include

===========================================================

-- Configuring done
-- Generating done
-- Build files have been written to:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build
~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $

However, when tried make, got other errors:

make[1]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[2]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
Scanning dependencies of target libboost_actor
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
[ 0%] Building CXX object
CMakeFiles/libboost_actor.dir/src/middleman_event_handler_epoll.cpp.o
[ 1%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_actor.cpp.o
In file included from
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/abstract_actor.cpp:31:
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/./boost/actor/actor_addr.hpp:116:1:
warning: 'hash' defined as a class template here but
previously declared as a struct template [-Wmismatched-tags]
class hash<boost::actor::actor_addr> {
^
.
.
.
[ 20%] Building CXX object CMakeFiles/libboost_actor.dir/src/cs_thread.cpp.o
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:154:61:
error: no member named 'minimum_stacksize' in

'boost::coroutines::basic_standard_stack_allocator<boost::coroutines::stack_traits>'
auto mss = static_cast<intptr_t>(
stack_allocator::minimum_stacksize()
~~~~~~~~~~~~~~~~~^
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:158:13:
error: assigning to 'context' (aka 'void **') from incompatible
type 'fcontext_t' (aka 'void *')
ctx = ctxn::make_fcontext(sinf.sp, sinf.size, cst_trampoline);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:160:24:
error: member reference base type 'ctxn::fcontext_t'
(aka 'void *') is not a structure or union
ctx->fc_stack.sp,
~~~^ ~~~~~~~~
3 errors generated.
make[3]: *** [CMakeFiles/libboost_actor.dir/src/cs_thread.cpp.o] Error 1
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[2]: *** [CMakeFiles/libboost_actor.dir/all] Error 2
make[2]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make[1]: *** [all] Error 2
make[1]: Leaving directory
`/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
make: *** [all] Error 2
~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $

Please, how should I correct the errors?

-regards,
Larry

Dominik Charousset

unread,
May 23, 2014, 6:02:56 PM5/23/14
to bo...@lists.boost.org
> [ 20%] Building CXX object CMakeFiles/libboost_actor.dir/src/cs_thread.cpp.o
> /home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:154:61: error: no member named 'minimum_stacksize' in
> 'boost::coroutines::basic_standard_stack_allocator<boost::coroutines::stack_traits>'
> auto mss = static_cast<intptr_t>( stack_allocator::minimum_stacksize()
> ~~~~~~~~~~~~~~~~~^
> /home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:158:13: error: assigning to 'context' (aka 'void **') from incompatible
> type 'fcontext_t' (aka 'void *')
> ctx = ctxn::make_fcontext(sinf.sp, sinf.size, cst_trampoline);
> ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/src/cs_thread.cpp:160:24: error: member reference base type 'ctxn::fcontext_t'
> (aka 'void *') is not a structure or union
> ctx->fc_stack.sp,
> ~~~^ ~~~~~~~~
> 3 errors generated.
> make[3]: *** [CMakeFiles/libboost_actor.dir/src/cs_thread.cpp.o] Error 1
> make[3]: Leaving directory `/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
> make[2]: *** [CMakeFiles/libboost_actor.dir/all] Error 2
> make[2]: Leaving directory `/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
> make[1]: *** [all] Error 2
> make[1]: Leaving directory `/home/evansl/prog_dev/boost/sandbox/boost.actor.dir/boost.actor/build'
> make: *** [all] Error 2
> ~/prog_dev/boost/sandbox/boost.actor.dir/boost.actor $
>
> Please, how should I correct the errors?

What Version of Boost are you using? Did they change the Boost.Context API again? Disabling it should help: ./configure --disable-context-switching

This option turns off the context-switching actor implementation, i.e., actors that use the blocking API but still participate in the cooperative scheduling.

Larry Evans

unread,
May 24, 2014, 11:37:47 AM5/24/14
to bo...@lists.boost.org
I'm using git. Maybe this output will tell you what I'm using:

evansl@evansl-Inspiron-531:~/prog_dev/boost/boost-modular/modular-boost$
git log -g
commit 5e1543bb9f96f8fbf08f19ed05522c0cf9c48cdd
Reflog: HEAD@{0} (cppljevans <cpplj...@suddenlink.net>)
Reflog message: pull: Fast-forward
Author: Automated Commit <auto...@calamity.org.uk>
Date: Fri Apr 25 13:00:12 2014 -0400

Update intrusive from master.

commit 31e07090a4d89038d0fa3da5e7ea82b313b6e23a
Reflog: HEAD@{1} (cppljevans <cpplj...@suddenlink.net>)
Reflog message: checkout: moving from master to master
Author: Automated Commit <auto...@calamity.org.uk>
Date: Wed Apr 23 18:30:07 2014 -0400

Update container from master.

commit 31e07090a4d89038d0fa3da5e7ea82b313b6e23a
Reflog: HEAD@{2} (cppljevans <cpplj...@suddenlink.net>)
Reflog message: clone: from https://github.com/boostorg/boost.git
Author: Automated Commit <auto...@calamity.org.uk>
Date: Wed Apr 23 18:30:07 2014 -0400

Update container from master.
evansl@evansl-Inspiron-531:~/prog_dev/boost/boost-modular/modular-boost$


> Did they change the Boost.Context API again?

> Disabling it should help: ./configure --disable-context-switching
>
> This option turns off the context-switching actor implementation,
> i.e., actors that use the blocking API but still participate in the cooperative scheduling.
>
Made that change with the result shown in the attachment.

The error about missing unique_ptr is surprising.
I added an #include <memory> near the top of demangle.cpp and that
solved the problem; however, now getting other errors:

/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/src/get_root_uuid.cpp:79:10:
fatal error:
'boost/actor/detail/algorithm.hpp' file not found
#include "boost/actor/detail/algorithm.hpp"
^
1 error generated.

What should be done about this problem?

-regards,
Larry

actor.configure.make.out

Dominik Charousset

unread,
May 24, 2014, 4:33:27 PM5/24/14
to bo...@lists.boost.org

On May 24, 2014, at 5:37 PM, Larry Evans <cpplj...@suddenlink.net> wrote:
>> What Version of Boost are you using?
>
> I'm using git. Maybe this output will tell you what I'm using:

I’ve disabled the context-switching feature per default in the master branch. This also gets rid of the context and coroutine dependency for now.


> /home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/src/get_root_uuid.cpp:79:10: fatal error:
> 'boost/actor/detail/algorithm.hpp' file not found
> #include "boost/actor/detail/algorithm.hpp"
> ^
> 1 error generated.
>
> What should be done about this problem?

That header was a leftover from libcppa. I’ve fixed this issue in master and tested a Linux build of Boost.Actor on Ubuntu 13.10 OpenSuSE 13.1. Have fun. :)

Larry Evans

unread,
May 25, 2014, 11:01:41 AM5/25/14
to bo...@lists.boost.org
On 05/24/14 15:32, Dominik Charousset wrote:
>
> On May 24, 2014, at 5:37 PM, Larry Evans <cpplj...@suddenlink.net> wrote:
>>> What Version of Boost are you using?
>>
>> I'm using git. Maybe this output will tell you what I'm using:
>
> I’ve disabled the context-switching feature per default in the master branch. This also gets rid of the context and coroutine dependency for now.
>
>
>> /home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/src/get_root_uuid.cpp:79:10: fatal error:
>> 'boost/actor/detail/algorithm.hpp' file not found
>> #include "boost/actor/detail/algorithm.hpp"
>> ^
>> 1 error generated.
>>
>> What should be done about this problem?
>
> That header was a leftover from libcppa. I’ve fixed this issue in master and tested a Linux build of Boost.Actor on Ubuntu 13.10 OpenSuSE 13.1. Have fun. :)
>
Thanks Dominik. That solved the problem and now `make` completes with
just warnings:

~/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor
$ make
make[1]: Entering directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
make[2]: Entering directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
Scanning dependencies of target libboost_actor
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
make[3]: Entering directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
[ 0%] Building CXX object
CMakeFiles/libboost_actor.dir/src/middleman_event_handler_epoll.cpp.o
[ 1%] Building CXX object
CMakeFiles/libboost_actor.dir/src/abstract_actor.cpp.o
In file included from
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/src/abstract_actor.cpp:31:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/./boost/actor/actor_addr.hpp:116:1:
warning:
'hash' defined as a class template here but previously declared
as a struct template [-Wmismatched-tags]
class hash<boost::actor::actor_addr> {
^
/home/evansl/dwnlds/gcc/4.8.1/install/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/../../../../include/c++/4.8.1/system_error:112:5:
note: did you
mean class here?
struct hash;
^
.
.
.
make[3]: Leaving directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
[100%] Built target typed_calculator
make[2]: Leaving directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
make[1]: Leaving directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
~/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor
$

Larry Evans

unread,
May 25, 2014, 5:57:10 PM5/25/14
to bo...@lists.boost.org
Unfortunately, `make test` failed all the tests. Adding a -VV flag
to the /usr/bin/ctest invocation, as shown here:

# Special rule for the target test
test:
$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running
tests..."
/usr/bin/ctest -VV --force-new-ctest-process $(ARGS)
.PHONY : test


in the */build/Makefile resulted in output:

~/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor
$ make test
make[1]: Entering directory
`/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build'
Running tests...
UpdateCTestConfiguration from
:/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/DartConfiguration.tcl
UpdateCTestConfiguration from
:/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/DartConfiguration.tcl
Test project
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build
Constructing a list of tests
Done constructing a list of tests
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: ripemd_160

1: Test command:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/bin/test_ripemd_160
1: Test timeout computed to be: 9.99988e+06
1:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/bin/test_ripemd_160:
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.18' not
found (required by
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/lib/libboost_actor.so.0)
1:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/bin/test_ripemd_160:
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.17' not
found (required by
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/lib/libboost_actor.so.0)
1:
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/bin/test_ripemd_160:
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.19' not
found (required by
/home/evansl/prog_dev/boost/boost-modular/modular-boost/sandbox/rw/sandbox/boost.actor.dir/boost.actor/build/lib/libboost_actor.so.0)
1/16 Test #1: ripemd_160 .......................***Failed 0.00 sec


How do you allow the test runs to find the libstdc++.so.6 files?
Maybe modify the LD_LIBRARY_PATH? Right now, it's empty.

-regards,
Larry

Larry Evans

unread,
May 25, 2014, 11:19:55 PM5/25/14
to bo...@lists.boost.org
I hadn't installed the gcc4.8.1 and that's probably why the above didn't
work. Adding $(GCC4_8_1.Install)/lib64 to the library
search path worked.

Nat Goodspeed

unread,
May 28, 2014, 7:53:00 AM5/28/14
to bo...@lists.boost.org
On Tue, May 20, 2014 at 1:05 PM, Julian Gonggrijp <j.gon...@gmail.com> wrote:

> I think the *right* design would be a concurrent equivalent of
> generic programming, where the only fundamental building blocks
> should be a well-designed statically typed SPSC queue, move
> semantics, a low-level thread launching utility (such as
> boost::thread) and a concise generic EDSL for the linking of nodes
> with queues. All further abstractions can be built on top of those
> ingredients (a bit like the STL is built on top of templates). It
> should allow me to do something like this:
>
> start(readfile(input) | runlengthenc | huffmanenc | writefile(output));
>
> At some point I want to publish a proposal for a library that does
> exactly this, but I need to find more time to work on it. The good
> news is that all necessary ingredients appear to already exist with
> C++11, Boost.Proto and Boost.Lockfree.

[OT, sorry...]
Julian, are you familiar with this pipeline proposal?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3534.html

Julian Gonggrijp

unread,
May 28, 2014, 3:14:58 PM5/28/14
to bo...@lists.boost.org
Nat Goodspeed wrote:

>> I think the *right* design would be a concurrent equivalent of
>> generic programming, where the only fundamental building blocks
>> should be a well-designed statically typed SPSC queue, move
>> semantics, a low-level thread launching utility (such as
>> boost::thread) and a concise generic EDSL for the linking of nodes
>> with queues. All further abstractions can be built on top of those
>> ingredients (a bit like the STL is built on top of templates). It
>> should allow me to do something like this:
>>
>> start(readfile(input) | runlengthenc | huffmanenc | writefile(output));
>>
>> At some point I want to publish a proposal for a library that does
>> exactly this, but I need to find more time to work on it. The good
>> news is that all necessary ingredients appear to already exist with
>> C++11, Boost.Proto and Boost.Lockfree.
>
> [OT, sorry...]
> Julian, are you familiar with this pipeline proposal?
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3534.html

No I wasn't! Thanks a lot for making me aware of it.

It is almost exactly what I had in mind, except that the authors seem to not have realised the full generality of the approach. This worries me. Has the proposal progressed far towards standardization already?

If I want to react to this proposal so that the standards committee knows about it, what should I do?

Cheers,
Julian

Benedek Thaler

unread,
May 28, 2014, 3:17:28 PM5/28/14
to bo...@lists.boost.org
> It is almost exactly what I had in mind, except that the authors seem to
> not have realised the full generality of the approach. This worries me. Has
> the proposal progressed far towards standardization already?
>
> If I want to react to this proposal so that the standards committee knows
> about it, what should I do?
>
> Cheers,
> Julian
>
>
Hi,

I'm also working on it, it's supported by GSoC.
Work in progress is at GitHub: https://github.com/erenon/pipeline

Benedek
Reply all
Reply to author
Forward
0 new messages