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.