tag:blogger.com,1999:blog-41715265178975774902024-02-07T12:21:45.192-08:00C++ Actor FrameworkAn Open Source Implementation of the actor model in C++.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.comBlogger44125tag:blogger.com,1999:blog-4171526517897577490.post-35737565703870703042014-11-04T07:37:00.000-08:002014-11-04T07:37:44.734-08:00We have moved our Developer Blog!As the last step of our project restructuring, we have moved our Blog to <a href="http://blog.actor-framework.org/">http://blog.actor-framework.org/</a>. Please feel free to send us feedback on the new layout and <a href="http://actor-framework.github.io/2014-11/we-have-moved-our-developer-blog/">read more in our new GitHub-hosted Dev Blog</a>.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-7526607990028109722014-09-24T07:53:00.000-07:002014-09-24T07:53:10.706-07:00Version 0.11 released!Version 0.11 of CAF has just been released. The core components mainly received optimizations and bugfixes this time around. However, CAF now includes the first alpha versions of a runtime inspection & debugging toolkit. <a href="https://github.com/actor-framework/actor-framework/releases/tag/0.11.0">Read more on GitHub</a>.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-24786351882285432852014-07-23T12:34:00.001-07:002014-07-23T12:34:43.665-07:00Version 0.10 released!Version 0.10 of <tt>CAF: C++ Actor Framework</tt> has just been released. <i>Wait, what?</i> For those of you that aren't subscribed to the mailing list, here is the Mail I've posted earlier this day:<br />
<br />
<blockquote class="tr_bq">
libcppa started in 2011 and it has been in constant development ever since. I think we can call this a success on its own and we see more and more applications using libcppa. We will announce the most exciting partners on our website soon, by the way.
<br />
<br />
To be quite frank, I did not expect the library to evolve that fast and with the recent additions to our team, I think it is a safe bet to say that the development will not slow down in the future. We are working on scaling the library down for embedded HW platforms and we are working on tools that make debugging and fine-tuning your applications easier. The project is about to become something bigger than "just" an actor library. Hence, we have decided to revamp libcppa and call the project:
<br />
<br />
CAF: C++ Actor Framework
<br />
<br />
We will move the GitHub repository to https://github.com/actor-framework/actor-framework and restructure it. This mailing list will be renamed to actor-framework@googlegroups.com and we will launch a new website. We have synchronized the release of the new repository with the release of version 0.10 of *libcaf*. The library has been modularized and you'll find libcaf_core and libcaf_io in the initial release of CAF. You can use libcaf_core if all you need is the concurrency abstraction of the library. The networking parts have been moved to libcaf_io. You will find "remote_actor" and "publish" there. The OpenCL part will be available as submodule soon. We go into more detail in a blog post covering the changes and you will find a migration guide in the manual.
<br />
<br />
Version 0.10, the new GitHub URL, and the new Google Group Name will go live *today*. 0.10 will have breaking changes. We tried to make migration less painful by still shipping the old cppa/cppa.hpp header, but there are breaking changes nonetheless. I am sorry that we break existing code again: twice in a row to be correct (0.9 had breaking changes, too). On the other hand, I think it really is worth it and we could get rid of some legacy code and inconsistencies that we don not want to maintain in the long run.
<br />
<br />
We sincerely hope that we can get a smooth transition. You *should* be forwarded to the repository URL automatically and still have it starred/watched/forked. The mailing list *should* keep you as member. However, please feel free to drop me a mail if something isn't working for you.
</blockquote>
<br />
<br />
So, here it is, <a href="https://github.com/actor-framework/actor-framework/releases/tag/V0.10.0">the first official release under the new name <tt>CAF</tt></a>. Once you've checked out the new release, you'll probably notice that things have changed quite a bit. The first thing you should do is to open the manual under <tt>manual/manual.pdf</tt> and scroll right to the end. You will find a migration guide from 0.9 to 0.10 on the last two pages.
<br />
<br />
To use the library, you can use the new CMake script under <tt>cmake/FindLibcaf.cmake</tt>. Usually, you want to have the two components "core" and "io": <tt>find_package(Libcaf COMPONENTS core io REQUIRED)</tt>. These two libraries offer you the functionality you're used to from <tt>libcppa</tt>. Please note that the OpenCL component is not ready quite yet. Upon success, the script will set the two variables <tt>${LIBCAF_LIBRARIES}</tt> and <tt>${LIBCAF_INCLUDE_DIRS}</tt>.
<br />
<br />
By the way, <tt>CAF</tt> is released under <i>both</i> the BSD 3-Clause and the Boost License. You can use it under the terms of either of those licenses (your choice!).
<br />
<br />
From now on, you can visit us at:
<br />
GitHub: <a href="https://github.com/actor-framework/actor-framework">https://github.com/actor-framework/actor-framework</a><br />
GoogleGroups: <a href="https://groups.google.com/d/forum/actor-framework">https://groups.google.com/d/forum/actor-framework</a><br />
... or go to our new project website: <a href="http://www.actor-framework.org/">http://www.actor-framework.org</a>.
<br><br>
As always, please don't hesitate to get in touch if you have any question.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-24135042666182808682014-05-30T06:02:00.001-07:002014-05-30T06:02:24.127-07:00Version 0.9.3 released ... under the Boost Software License!Version 0.9.3 of <tt>libcppa</tt> has just been released. The biggest change this time around is the switch from LGPL to the Boost Software License 1.0. If you are working in one of those companies that prohibit LGPL-licensed code, you are finally able to use actors in your day-to-day programming.
<br><br>
Due to the everlasting problems with the Boost.Context-based context-switching actor implementation, this features is now turned off by default. To re-enable it, use the <tt>--enable-context-switching</tt> option of the configure script. Since this feature is of limited use anyways, we consider removing it completely in a future version. We don't think it is worth the maintenance effort in the long run.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com3tag:blogger.com,1999:blog-4171526517897577490.post-3313078979294997462014-05-06T09:09:00.001-07:002014-05-06T09:09:55.378-07:00Issues with Boost on UbuntuAs reported by users of <tt>libcppa</tt>, the library fails to compile - or rather: to link - on the latest Ubuntu release with Boost. To get a running version of libcppa, please configure it using <tt>./configure --standalone-build</tt>. This will disable the context-switching feature of libcppa. Context-switching is only relevant in case you want to have cooperative scheduling of blocking actors. When disabling this feature, all blocking actors are implicitly detached.
<br><br>
Since Boost only enables context-switching, we are considering to turn this feature into an opt-in rather than an opt-out at compile time. In case your system is lacking Boost, you won't get the context-switching actors anyways (and will not be affected by this error). Other parts of the library do not depend on Boost, so there is no degradation of performance or functionality.
<br><br>
If you run into a similar error on a different Linux distribution, please let me know.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com5tag:blogger.com,1999:blog-4171526517897577490.post-70686556638569061462014-05-05T06:21:00.002-07:002014-05-05T06:21:38.509-07:00Version 0.9 released!Version 0.9 of <tt>libcppa</tt> has just been released. It features an all-new work-stealing scheduler. Expect new benchmark results in the near future as the last evaluation is heavily outdated by now.
<br><br>
Aside from performance performance tweaks, version 0.9 also features an improved broker interface covered in a <a href="http://neverlord.github.io/libcppa/manual/index_0_9_0.html#sec56">new manual section</a> as well as a <a href="https://github.com/Neverlord/libcppa/blob/master/examples/remote_actors/simple_broker.cpp">new example</a>.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-15056776669636913832014-02-21T12:13:00.000-08:002014-02-21T12:13:28.724-08:00Prerelease of Version 0.9 Version 0.9 of <tt>libcppa</tt> is just around the corner – and it's not simply an incremental update but a redesign of many (in fact: most) parts of <tt>libcppa</tt>.
Since we don't plan to make any more changes to the API, we've decided to do a prerelease.
This gives us the opportunity to get feedback from the community while polishing the remaining parts of the library and it also gives you the opportunity to start porting your code to 0.9 early.
<br />
<br />
<b>The most important changes</b>:
<br />
<ul>
<li>
<b><tt>self</tt> has been removed</b><br />
This is the biggest change and in fact did cause <i>a lot</i> of redesign and implementation work.
The major problem with this keyword-like identifier is that it must have a single type, because it's implemented as a thread-local variable.
Since there are so many different kinds of actors (event-based or blocking, untyped or typed), <tt>self</tt> simply isn't useful anymore.
It could only point to the <i>address</i> (see below) of an actor, but this isn't useful at all, because we cannot get the type information we need.
Instead of a thread-local pointer, you can now use the first argument in functor-based actors to "catch" the self pointer – with proper type information.
</li>
<li>
<b><tt>actor_ptr</tt> has been removed/replaced</b><br />
The name <tt>actor_ptr</tt> bothered me for long time now, because it's misleading.
The fact that <tt>libcppa</tt> uses pointers behind the scenes to keep things fast should not be exposed in the API.
However, that was not the reason for the change.
<tt>libcppa</tt> now distinguishes between handles to actors, i.e., <tt>typed_actor<...></tt> or <tt>actor</tt>, and addresses of actors, i.e., <tt>actor_addr</tt>.
The reason for this change is that each actor has a logical, (network-wide) unique address, which is used by the networking layer of <tt>libcppa</tt>.
Furthermore, for monitoring or linking, the address is all you need.
However, the address is not sufficient for sending messages, because it doesn't have any type information.
The function <tt>last_sender()</tt> now returns the <i>address</i> of the sender, meaning that <tt>send(last_sender(), ...)</tt> will cause a compiler error.
</li>
<li>
<b>The API for typed actors is now similar to the API for untyped actors</b><br />
Although there are some minor differences (typed actors cannot use guard expressions for instance), the APIs are quite similar.
You can use function-based or class-based actors, you can "catch" the self pointer in the same way, and you can change the behavior by calling <tt>become(...)</tt>.
</li>
</ul>
<br />
<br />
<b>Issues</b> (or: why this isn't a final release yet):
<br />
<ul>
<li>
<b>No scheduling</b><br />
The prerelease does <i>not</i> include a scheduler.
Instead, each actor is always mapped to a thread, whether or not you use the <tt>detach</tt> flag.
So... don't expect good performance when running many actors.
</li>
<li>
<b>Documentation incomplete</b><br />
The manual has been revised, but doesn't include all new features.
The same is true for the Doxygen-generated documentation.
</li>
<li>
<b>Testing</b><br />
The unit tests of <tt>libcppa</tt> cover most of the new features, but there's still work to do.
</li>
</ul>
<br />
<br />
As always, please don't hesitate to get in touch if you've found a bug, miss a feature, couldn't find something in the documentation, or simply have a question.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-34105023787475562372013-11-09T05:49:00.002-08:002013-11-09T05:49:45.042-08:00Moving Forward: Type Safety & ActorsType safety is a topic that comes up very frequently when talking to C++ developers about <tt>libcppa</tt> - and actors in general. Indeed, the major concern about <tt>libcppa</tt> at the C++Now 2013 conference was that it does not provide a type-safe messaging interface. I'm not going to discuss pros and cons of dynamic and static typing. Both approaches do have their benefits. In <tt>libcppa</tt>, you can use atoms to "create" new message types on the fly and then pattern match on the receiver side. In this way, it is very lightweight to introduce new message types to a system, as you don't have to maintain header files for your message types. On the flip side, "wrong" message types are detected at runtime. When sending arguments in the wrong order, your pattern on the receiver side will not match. Naturally, most C++ developers expect the compiler to detect those kind of bugs.<br />
<br />
Version 0.8 introduced strongly-typed actors to give developers a choice. Unfortunately, <tt>libcppa</tt> is now a two-class society. Even worse, it is indeed rather easy to get an untyped reference to a strongly-typed actor. But let's step back and take a look at the issues individually.
<br />
<ol>
<li><b>Second-class Typed Actors: </b>Typed actors are not allowed to use guard expressions. This in itself is not a problem. The problem is how <tt>libcppa</tt> signals system events. For example, when monitoring an actor, you'll receive a "down" message consisting of the atom 'DOWN' and the exit reason as uint32. Since typed actors are not allowed to use guards, the only thing they could possibly do is to define a handler for <i>all</i> messages with an atom as first element followed by an uint32. There are 10<sup>64</sup> possible atoms. As a consequence, <tt>libcppa</tt> needs to introduce message types for system messages. This will break code and I would prefer not to, but it's better to break some code that's easy to repair than to have a broken design.</li>
<li><b>Separated APIs:</b> To spawn a typed actor, we use functions that return the behavior. For untyped actors, we can use void functions that call 'become' internally. Even worse, 'become' now can throw - when called from a typed actor. It's probably for the best to move 'become' from the namespace cppa to the class event_based_actor and always use function that return a behavior.</li>
<li><b>Type-safety Not Enforced:</b> As you might know if you've ever used <tt>libcppa</tt>: An actor can get a handle to itself by using 'self' and a handle to any actor that sent a message to it by calling 'self->last_sender()'. This handle is of course untyped. So, not only can a typed actor get an untyped handle to itself, each actor it is communicating with has an untyped handle to it. The only way to enforce type safety is to either remove 'self' completely from the API or to change its type to something not convertible to actor_ptr, so that you can only access member functions like 'trap_exits'. The member function 'last_sender()' then also would have to go or to return only a logical address that you can use for monitoring and linking, but not for message passing.</li>
<li><b>Missing Features:</b> This is not a design issue, but <tt>libcppa</tt> 0.9 will of course implement proper remote communication for typed actors.</li>
</ol>
<tt>libcppa</tt> started as a DSL for Erlang-style actor programming in C++. With version 0.9, <tt>libcppa</tt> will (hopefully) evolve into a unique actor system that supports untyped and typed actors side by side. Stay tuned. :)Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-58838607071056195002013-10-15T03:13:00.001-07:002013-10-15T03:13:56.944-07:00Version 0.8 released!Version 0.8 of <tt>libcppa</tt> has just been released. The biggest change for existing code: The function <tt>reply</tt> is deprecated. Actors now do automatically reply to a message by returning a value from the message handler. This change does not only make your code cleaner, but this is also the only way a new kind of actors - strongly typed actors - are allowed to reply to incoming messages. Typed actors is the most frequently requested feature for <tt>libcppa</tt> - and have finally arrived. You can create typed actors using the function <tt>spawn_typed</tt>:
<br><br>
<pre class="brush:cpp">
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);
}
);
</pre>
<br><br>
As you can see, the argument to <tt>spawn_typed</tt> is a match expression rather than a function. This is because a typed actor is <b>not</b> allowed to change its behavior. The messaging interface is burnt into its type. In the example above, the type of <tt>p0</tt> is <tt>typed_actor_ptr<replies_to<int, int>::with<double>,replies_to<double, double>::with<double, double>></tt>. In this way, the compiler is now able to type-check your messages:
<br><br>
<pre class="brush:cpp">
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
);
</pre>
<br><br>
Typed actors are not "feature complete" yet, i.e., typed actors cannot be published and it is not possible to use priorities when sending a message to a typed actor. However, this is just a matter of time. To learn more about typed actors, visit Section 15 of the 0.8 manual.
<br><br>
As if typed actors were not enough, version 0.8 includes yet another new kind of actors: brokers. A broker connects your actor system to any other network protocol. The new release includes an example featuring Google Protobuf: <a href="https://github.com/Neverlord/libcppa/blob/master/examples/remote_actors/protobuf_broker.cpp">examples/remote_actors/protobuf_broker.cpp</a>.
<br><br>
A small addition that is worth mentioning is the new exit reason <tt>exit_reason::user_shutdown</tt>. This reason can be used whenever you force actors to quit as part of application shutdown or for shutting down parts of your system that are no longer necessary.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com2tag:blogger.com,1999:blog-4171526517897577490.post-50543857073454742872013-05-21T11:15:00.001-07:002013-05-21T11:15:27.968-07:00Version 0.7.1 releasedVersion 0.7.1 of <tt>libcppa</tt> has just been released. This release fixes some bugs and improves compatibility with GCC 4.8.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com9tag:blogger.com,1999:blog-4171526517897577490.post-49142779591323799942013-05-13T08:20:00.000-07:002013-05-21T11:16:23.445-07:00Version 0.7 releasedVersion 0.7 of <tt>libcppa</tt> has just been released. For the first time in an official release, this version breaks code compatibility with earlier versions (this was not an easy step and caused some discussion). When calling <tt>spawn</tt> with a function, the new default implementation is event-based. Hence, your actor should set its behavior using <tt>become</tt> and <b>not</b> use functions like <tt>receive</tt>. However, it is pretty easy to port your existing code. To opt-in to the "old" behavior, use <tt>spawn<blocking_api>(fun_name)</tt>.
<br><br>
Among improvements and optimizations, this version includes a few new functions as well:
<ul>
<li>Priority-aware messaging (opt-in feature)</li>
<li>OpenCL-based actors (must be enabled using '--with-opencl')</li>
</ul>
<br>
Please note that the manual has received a huge update due to the changed default behavior of <tt>spawn</tt> and has not caught up to the new features yet.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com4tag:blogger.com,1999:blog-4171526517897577490.post-38865821644849332012013-02-22T03:40:00.001-08:002013-02-22T03:40:59.587-08:00Version 0.6 releasedVersion 0.6 of <tt>libcppa</tt> has just been released. This release brings several improvements to the synchronous messaging API. Please read more about features like functor-only usage and continuations in the revamped <a href="http://neverlord.github.com/libcppa/manual/manual_0_6_0.html#sec40">Section 7 of the manual</a>.
<br><br>
Among several smaller improvements, this release also includes:
<ul>
<li><a href="http://neverlord.github.com/libcppa/manual/manual_0_6_0.html#sec39">manual skipping of messages</a></li>
<li>Boost 1.53 support thanks to GitHub user <a href="https://github.com/Neverlord/libcppa/pull/89">abigagli</a></li>
<li>a new <tt>quit_actor</tt> function to send 'EXIT' messages to actors</li>
</ul>Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-27977813518686844662013-01-07T16:11:00.000-08:002013-01-07T16:11:27.492-08:00Actor CompanionsIn the previous post about <a href="http://libcppa.blogspot.de/2012/11/using-actors-with-qt.html">actors with Qt</a>, we have already briefly discussed the concept of actor companions, but this post presents the general approach.<br>
<br>
<h2>What is it Good For?</h2>
<tt>libcppa</tt> automatically converts threads to actors if needed (using thread-local storage), whenever a thread uses a message passing primitive such as <tt>send()</tt>.
However, sometimes this conversion is too coarse-grained.
Simply put, whenever several independent entities share a thread, but should be addressed individually as actors, we need actor companions.
The classical example is a widget.
The thread is owned by the event loop, which manages any number of widgets, why we cannot rely on <tt>libcppa</tt>'s automatic thread conversion.
If you need to support a library wich internally schedules its entities (perhaps based on green threads or coroutines) - or if you just want to learn more about <tt>libcppa</tt>, this post is for you.<br>
<br>
<h2>Background</h2>
If you want to mix <tt>libcppa</tt> with an other framework, multiple inheritance is not an option.
Usually, each framework manages its entities in an incompatible way.
For example, Qt uses hierarchical object ownership by default.
This obviously interferes with the reference counting strategy of libcppa.
Even if the framework uses reference counts, you will end up having two reference counts in your object.
Instead of using multiple inheritance, we use co-existing objects (companions), which serve as gateway.
The companion implements the actor interface of <tt>libcppa</tt> but does not have a mailbox.
It forwards all messages it receives to its parent.<br>
<br>
<h2>Mixing in a Solution</h2>
Actor companions are enabled by the mixin <tt>actor_companion_mixin</tt>.
The mixin provides the member functions <tt>actor_ptr as_actor()</tt>, <tt>void set_message_handler(...)</tt>, and <tt>void handle_message(const message_pointer&)</tt>.
It also has one pure virtual member function: <tt>void new_message(message_pointer)</tt>.
This function must be implemented in a thread-safe way.
The type <tt>message_pointer</tt> is a smart pointer holding a tuple along with meta data such as sender information.
There is no need to interact with a <tt>message_pointer</tt>, as the message handler does everything necessary.<br>
<br>
<h2>A Working Example</h2>
<pre class="brush:cpp">
template<typename Base, int EventId = static_cast<int>(QEvent::User + 31337)>
class actor_widget_mixin : public actor_companion_mixin<Base> {
typedef actor_companion_mixin<Base> super;
typedef typename super::message_pointer message_pointer;
public:
template<typename... Args>
actor_widget_mixin(Args&&... args) : super(std::forward<Args>(args)...) { }
struct event_type : public QEvent {
message_pointer msg;
event_type(message_pointer mptr)
: QEvent(static_cast<QEvent::Type>(EventId)), msg(std::move(mptr)) { }
};
virtual bool event(QEvent* event) {
if (event->type() == static_cast<QEvent::Type>(EventId)) {
auto ptr = dynamic_cast<event_type*>(event);
if (ptr) {
this->handle_message(ptr->msg);
return true;
}
}
return super::event(event);
}
protected:
virtual void new_message(message_pointer ptr) {
qApp->postEvent(this, new event_type(std::move(ptr)));
}
};
</pre>
<br>
The code shown above is the actual code from <tt>cppa/qtsupport/actor_widget_mixin.hpp</tt>.
As you can see, it is Qt specific, but straightforward.
Our "derived mixin" has no constructor arguments and only forwards all arguments to the base constructor (line 11).<br>
<br>
The crucial point of this implementation is to convert <tt>libcppa</tt> messages to Qt events in the implementation of <tt>new_message</tt> (line 35).
The runtime system of Qt will then call the <tt>event</tt> member function (line 22) later on from inside the event loop.
All our implementation has to do is to unwrap the <tt>message_pointer</tt> and pass it to <tt>handle_message</tt>.<br>
<br>
Once we have called <tt>handle_message</tt>, our message handler gets invoked – with <tt>self</tt> pointing to the companion.
This way, we can use <tt>send</tt> and <tt>reply</tt> as usual in the handler.
Even though the code is Qt specific, it should be straightforward to implement a comparable mixin to support your framework of choice.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-22471859537756684282013-01-07T08:26:00.002-08:002013-01-07T08:27:31.594-08:00Version 0.5.5 releasedVersion 0.5.5 of <tt>libcppa</tt> has just been released. This release brings several bugfixes and performance improvements as well as <a href="http://neverlord.github.com/libcppa/manual/index_0_5_5.html#sec68"><tt>aout</tt> – A Thread-Safe Wrapper for <tt>std::cout</tt>.</a>Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-83303636419411008842012-11-14T04:32:00.000-08:002012-11-14T09:32:20.847-08:00Using Actors with QtActor programming is nice and makes our lives easier, but at some point, we have to display the output of our program to the user. Not everything is a command line tool. Hence, we have to use some sort of GUI library, which raises the question how we pass messages from actors - safely! - to the GUI at runtime. Well, what if we could send an ordinary message to the GUI as if it's an actor? What if the GUI can send us ordinary messages whenever the user pushes some buttons? Briefly speaking, can we treat GUI elements as actors? Luckily, the answer is yes! We have to write some gluecode, but in fact, you can treat <i>everything</i> as an actor with <tt>libcppa</tt>.<br>
<br>
<h2>Getting Started</h2>
In this article, we will focus on the Qt library, as it is the open source GUI library of choice for C++ developers. In the next article, we will have a look at the general concept of <i>actor companions</i>. An actor companion is an actor that co-exists with another object. In our case, this object is a QWidget-base class. The companion is used to receive and send messages, but it does not have any behavior itself. All it takes to enable a class to have such a companion is to use the <tt>actor_widget_mixin</tt>.<br><br>
The following class implements a simple group-based chat widget with a <tt>QTextEdit</tt> for text output and a <tt>QLineEdit</tt> for user input (chat messages). The full source code can be found <a href="https://github.com/Neverlord/libcppa/tree/master/examples/qtsupport">in the examples folder</a> in the Git repository.
<br>
<pre class="brush:cpp">
#include <QWidget>
#include "cppa/qtsupport/actor_widget_mixin.hpp"
class ChatWidget : public cppa::actor_widget_mixin<QWidget> {
Q_OBJECT
typedef cppa::actor_widget_mixin<QWidget> super;
// ...
public:
ChatWidget(QWidget* parent = nullptr, Qt::WindowFlags f = 0);
// ...
private:
std::string m_name;
cppa::group_ptr m_chatroom;
};</pre>
The mixin adds the following member functions to <tt>ChatWidget</tt>:
<ul>
<li> <tt>actor_ptr as_actor()</tt><br>returns the companion of this widget
<li> <tt>set_message_handler</tt><br>sets the partial function for message processing
</ul>
<br>
<h2>Handle Messages to the Widget</h2>
In our example, the widget should handle <tt>'join'</tt>, <tt>'setName'</tt>, and <tt>'quit'</tt> messages as well as display chat messages (received as <tt>std::string</tt>). We encode our message handling directly into the constructor of <tt>ChatWidget</tt>:
<pre class="brush:cpp">
ChatWidget::ChatWidget(QWidget* parent, Qt::WindowFlags f) : super(parent, f) {
set_message_handler (
on(atom("join"), arg_match) >> [=](const group_ptr& what) {
if (m_chatroom) {
send(m_chatroom, m_name + " has left the chatroom");
self->leave(m_chatroom);
}
self->join(what);
print(("*** joined " + to_string(what)).c_str());
m_chatroom = what;
send(what, m_name + " has entered the chatroom");
},
on(atom("setName"), arg_match) >> [=](string& name) {
send(m_chatroom, m_name + " is now known as " + name);
m_name = std::move(name);
print("*** changed name to "
+ QString::fromUtf8(m_name.c_str()));
},
on(atom("quit")) >> [=] {
close(); // close widget
},
on<string>() >> [=](const string& txt) {
// don't print own messages
if (self != self->last_sender()) {
print(QString::fromUtf8(txt.c_str()));
}
}
);
}</pre>
<br>
<h2>Pitfalls & Things to Know</h2>
The code is pretty straight forward if you are already familiar with <tt>libcppa</tt>, but there is one important thing to note: <i>Unhandled messages are lost</i>. Although the widget is able to handle <tt>libcppa</tt> messages now, it does <i>not</i> have a mailbox. Messages are delivered to the widget as <tt>QEvent</tt> objects that are disposed afterwards.
<br><br>
The second thing to note is that you should <i>never</i> use <tt>self</tt> outside the message handler. This includes using functions such as <i>send</i>, because <t>self</t> is internally used to determine the sender of a message. The reason to this limitation is that <tt>libcppa</tt>'s <tt>self</tt> "pointer" is thread-local. Using <tt>self</tt> would therefore convert the Qt thread your widget runs in to an actor, but it wouldn't address your widget's companion.<br><br>
To send a message from outside of your handler, you have to tell <tt>libcppa</tt> who is the sender of the message by hand:
<pre class="brush:cpp">send_as(as_actor(), m_chatroom, "hello world!");</pre>
<br><br>
Have fun!Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-20229297209510459572012-10-26T16:15:00.000-07:002012-10-26T16:15:29.204-07:00Version 0.5 releasedVersion 0.5 of <tt>libcppa</tt> has just been released. This release brings Log4j-like logfiles to <tt>libcppa</tt> developers (must be enabled at compile time), support for user-defined communication protocols, and <i>actor companions</i>.<br>
<br>
Each class using the <tt>actor_companion_mixin</tt> has such an actor companion, which provides an easy way for active non-actor objects, i.e., objects with an own thread or event loop, to send messages to/as actor. The default use case for this feature is to treat GUI elements - widgets - as actors. A more specific mixin for Qt widgets is on its way.<br><br>
By the way, <tt>libcppa</tt> now has <b>more than a thousand commits</b> on GitHub! :-)Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com4tag:blogger.com,1999:blog-4171526517897577490.post-38679050912627066502012-08-22T08:02:00.000-07:002012-08-22T08:02:26.579-07:00Version 0.4 releasedThe main feature of version 0.4 is a streamlined and bugfixed network layer. Of course, there are some new features as well:
<ul>
<li><b>Support for User-Defined Network Layer</b><br>
The functions <tt>publish</tt> and <tt>remote_actor</tt> were overloaded to allow user-defined network layers such as OpenSSL; see this <a href="https://groups.google.com/d/topic/libcppa/h9lIYytZj20/discussion">mailing list discussion</a> and the doxygen documentation of <tt>util::input_stream</tt>, <tt>util::output_stream</tt> and <tt>util::acceptor</tt> for more details.<br></li>
<li><b>Shutdown Function</b><br>
The new <tt>shutdown()</tt> function closes all network connections, stops the scheduler and deletes all of <t>libcppa</tt>'s singletons. It is strongly recommended to call this function before returning from <tt>main()</tt>, especially if you are connected to remote actors.<br></li>
<li><b>Syntactic Sugar for Synchronous Messaging</b><br>
Synchronous message handling using futures is flexible but sometimes too verbose.
<pre class="brush:cpp">
auto future = sync_send(...);
handle_response(future, ...); // event-based API
receive_response(future, ...); // blocking API</pre>
Version 0.4 provides some syntactic sugar to make your code more compact. Whenever you send a message and immediately wait for the response, you can write the following instead.
<pre class="brush:cpp">
sync_send(...).then(...); // event-based API
sync_send(...).await(...); // blocking API</pre>
Furthermore, there is a feature request for a continuation-passing style API to enable developers to easily encode "send X then receive Y then send Z" message flows (see <a href="https://github.com/Neverlord/libcppa/issues/58">Issue 58</a> on GitHub).</li>
<li><b>Local Groups & Remote Actors</b><br>
Local groups, as returned by calling <tt>group::get("local", ...);</tt> or <tt>group::anonymous()</tt>, are now not-so-local. It is possible to send a local group to a remote actor and let the remote actor join the group. Whenever an actor sends a message to the group, the message is send back to the owning process if needed and forwarded to all subscribers from there, including remote actors. This approach certainly does not scale for largely distributed groups, since it is N-times unicast*. However, it paves to path for more use cases of "local" groups and we are working on scalable group communication as well.<br><br>
<i>* The N in this case is the number of hosts and not the number of remote actors.</i><br></li>
</ul>Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com2tag:blogger.com,1999:blog-4171526517897577490.post-11092585220313362432012-08-10T04:02:00.000-07:002012-08-10T04:02:49.409-07:00New Functions in 0.3.3Among some bugfixes, version 0.3.3 also includes a few new functions to add 'missing' features:<br>
<ul>
<li><b>Forwarding of Messages</b><br><tt>libcppa</tt> lacked an easy and transparent way to forward messages. The new function <tt>forward_to</tt> finally adds this functionality. Furthermore, forwarding a synchronous messages is not possible without this function. Read more about forwarding in <a href="http://neverlord.github.com/libcppa/manual/index_0_3_3.html#htoc30">Section 5.4</a> of the manual.</li>
<li><b>Messaging with Tuples</b><br>Matthias Vallentin <a href="https://groups.google.com/forum/#!topic/libcppa/pwmy4zhyMzc%5B1-25%5D">pointed out</a> that the API was somewhat inconsistent, since it did not provide functions to use a tuple as response message. We have added the following functions in version 0.3.3 to treat tuples as first-class citizen: <tt>send_tuple</tt>, <tt>sync_send_tuple</tt>, <tt>reply_tuple</tt>, <tt>delayed_send_tuple</tt> and <tt>delayed_reply_tuple</tt>.</li>
<li><b>Manual</b><br>The manual is now included to the source distribution as <tt>manual.pdf</tt> and states the <tt>libcppa</tt> version.</li>
<li><b>Doxygen</b><br>CMake checks whether doxygen is available on your system and adds an optional "doc" target to the Makefile. You can create your own local version of the doxygen documentation by running "<tt>make doc</tt>". Open the file <tt>html/index.html</tt> afterwards.</li>
</ul>Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-63534917502050655102012-07-26T03:55:00.000-07:002012-07-26T03:55:52.931-07:00libcppa on Mountain LionI have just upgraded my Mac and I have good news for all Apple users out there!<br><br>
If you have switched to Mountain Lion or have plans to do so, you will find <tt>clang++</tt> in version 4.0 after installing XCode. Hence, there is finally no need to get a recent compiler from an external source. <tt>libcppa</tt> 0.3 compiles and runs like a charm after installing CMake and Boost from <a href="http://www.macports.org/">MacPorts</a>.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com1tag:blogger.com,1999:blog-4171526517897577490.post-3996469064303556232012-07-25T11:47:00.001-07:002012-08-22T08:02:39.651-07:00Version 0.3 Released<p>I'm glad to announce <tt>libcppa</tt> 0.3. This release has two major improvements.</p>
<h3>Synchronous Messages</h3>
<p>Actors can send synchronous response messages by using the function <tt>sync_send</tt>. This function returns a future to the response that can be received by using either the blocking <tt>receive_response</tt> or the event-based <tt>handle_response</tt>. Please read the <a href="http://neverlord.github.com/libcppa/manual/index.html#htoc37">section about synchronous communication</a> in the manual for further details.</p>
<h3>Configure Script</h3>
<p>Thanks to <a href="http://matthias.vallentin.net/">Matthias Vallentin</a> (a.k.a. <a href="https://github.com/mavam">mavam</a>), <tt>libcppa</tt> has a much simpler build process now. The new configure script hides all CMake details behind a nice and clean interface.</p>
<h3>Minor Improvements</h3>
<ul>
<li>Context-switching can be disabled by using the <tt>--disable-context-switching</tt> configure option for platforms without Boost.Context support (<a href="https://github.com/Neverlord/libcppa/issues/24">Issue 24</a>).</li>
<li>The function <tt>tuple_cast</tt> does no longer require an additional header include (<a href="https://github.com/Neverlord/libcppa/pull/38">Issue 38</a>).</li>
<li>The new "cppa_fwd.hpp" header provides forward declarations for heavily used data structures, such as <tt>actor_ptr</tt> (<a href="https://github.com/Neverlord/libcppa/issues/36">Issue 36</a>).</li>
<li><tt>become()</tt> no longer accepts pointers to avoid potential misuses and resulting memory leaks.</li>
</ul>Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-38040631803046160822012-06-29T06:27:00.000-07:002012-06-29T06:48:43.266-07:00We Have a Beta! Read the Manual!After months of development, I've just merged the development branch into the master branch. Get the <a href="https://github.com/Neverlord/libcppa/tags">V0.2.0 tag</a> from Github or update your local working copy.<br><br>
<b>What's new?</b><br><br>
<ul>
<li>Improved performance! (new benchark results will follow)</li>
<li>CMake instead of Automake</li>
<li>A <a href="http://neverlord.github.com/libcppa/manual/"><b>user manual</b></a> (<a href="http://neverlord.github.com/libcppa/manual/manual.pdf">PDF</a>)</li>
<li>A stable API*</li>
</ul>
<br><br>
* I know <tt>libcppa</tt> had a quite volatile API in the past. However, this is the first official release and <tt>libcppa</tt> is no longer released as experimental version. You will seldom see code-breaking changes from now on and in major updates only! This is the perfect time to get started with <tt>libcppa</tt>. :)
<br><br>That said, version 0.2 had a few changes. Here is a list of "quick-fixes" to get your code running again:
<br>
<ul>
<li><tt>become_void()</tt> => <tt>quit()</tt></li>
<li><tt>future_send()</tt> => <tt>delayed_send()</tt></li>
<li><tt>stacked_event_based_actor</tt> is dead and gone; just use <tt>event_based_actor</tt> and the new policy-based API of <tt>become/unbecome</tt> (please read the manual for further details)</li>
<li><tt>fsm_actor</tt> => <tt>sb_actor</tt> (read: "State-Based Actor"); because "real", transition-oriented FSM actors are something I am thinking about as a possible feature in a future release</li>
<li><tt>spawn(new T(...))</tt> => <tt>spawn<T>(...)</tt></li>
</ul>
<br><br>
I will update all blog posts in the near future, so that all code examples will compile and run with version 0.2.
<br><br>
Have fun!Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-68749603796399759532012-05-12T09:52:00.002-07:002012-08-22T08:05:06.367-07:00A Little Bit of History and Why Restrictions Breed CreativityIf you think about the (original) actor model, you'll find that it's defined by what you are <i>not</i> allowed to do. You are <i>not</i> allowed to share state. You are <i>not</i> allowed to use everything else but message passing for communication. You are <i>not</i> allowed to randomly change your state, because you shall change your state only in response to a received message. If you think about functional programming, you'll find the exact same mindset. Functional programming is all about immutability (read: "you are <i>not</i> allowed to change objects") and prohibition of side-effects (read: "you are <i>not</i> allowed to manipulate your arguments or some global state"). There are good reasons for such restrictions, but let's talk about Erlang first.
<br><br>
If you are familiar with Erlang, you've probably noticed that the word "actor" is not used at all. Neither in function names nor in its documentation. In fact, the <a href="http://pubftp0.availo.se/pub/FreeBSD/distfiles/erlang-doc/r13b01/armstrong_thesis_2003.pdf">dissertation of Joe Armstrong</a> (the inventor of Erlang) doesn't even include the word "actor". Why? Erlang is always referred to as the reference implementation of the actor model, isn't it?
<br><br>
Well, Erlang is based on a simple observation. In the "old days", people started implementing operation systems able to execute multiple programs in parallel. Mostly because <a href="http://en.wikipedia.org/wiki/Punched_cards">punched cards</a> and batch processing don't make fun. But this led to trouble. Serious trouble. In a naive mutlitasking-OS, you are limited by the amount of freedom you (and other developers) have, because if you are free to write everywhere you want, you can easily corrupt someone else's program. That's why we need <a href="http://en.wikipedia.org/wiki/Memory_management_unit">an MMU</a> in our computer. It's impossible to write a program if you know that someone else might manipulate your state (memory) at any point in time. So, the OS organized running programs into <i>processes that do not share state</i> and the world was sane again. You can start a program ten times and each of it will have a unique state. Pipes were added to allow processes to communicate. A process also can create a new process using <a href="http://linux.die.net/man/2/fork"><tt>fork</tt></a>. But then, people wanted concurrent execution of a single program, e.g., to keep GUI's responsive while doing background work. Threads were added, because <tt>fork</tt> is expensive and communicating via a pipe is complicated ... and the concurrency nightmare begun.
<br><br>
Erlang had the simple idea to fix the real issue here: processes are too expensive in modern OS's and communication between processes is too complicated. Do you know why Erlang does not have a threading library? Because no language should! Programs are written by humans and <i>humans cannot think concurrently</i>. Erlang's VM provides lightweight processes with a simple way to exchange messages. And it abstracts away all the dirty details. Plus, message passing is network transparent.
<br><br>
Message passing is something people can imagine. It is something people can reason about. Abstraction is always the answer in computer science. And abstraction means to build a simple model of something inherently complicated. Small systems communicating via message passing is something we can reason about. We can build large systems by "plugging" small systems together and we are still able to handle it. But hundreds of thousands of objects floating around, sharing state and run in parallel is hard to comprehend. To quote Rich Hickey (have a look at this <a href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure/">channel9 video</a> if you don't know him): "Mutable stateful objects are the new spaghetti code".
<br><br>
By <i>not</i> sharing memory, some problems just disappear. Isolation is a restriction, but it allows you to focus on <i>your</i> problems and you can use all your creativity and skill to do this. Threads are broken by design. Some <a href="http://bartoszmilewski.com/2012/05/11/the-future-of-c-concurrency-and-parallelism/">bright minds</a> are trying to fix them, but I think threads are best avoided. Unfortunately, we cannot "undo" threads and we cannot go back in time to implement OS's more suitable to write concurrent software. However, we can treat "std::thread" (and friends) the way we treat "goto". It's in the language/STL, but you should not use it in production code. Well, maybe someone implements something that's useful and safe on top of it (<tt>libcppa</tt> for example).
<br><br>
But let's get back to actors. <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.77.7898">Karl Hewitt et al.</a> published an article about isolated computational entities, "actors", in the year 1973 (btw. there's an interesting video featuring Hewitt <a href="http://channel9.msdn.com/Shows/Going+Deep/Hewitt-Meijer-and-Szyperski-The-Actor-Model-everything-you-wanted-to-know-but-were-afraid-to-ask">on channel9</a>). It's a theoretically point of view to answer the question "what is the minimum set of axioms we need to describe concurrency?" Erlang came from the opposite direction. They said "writing concurrent, fault-tolerant software in traditional programming models is extremely difficult, how can we provide a better model?" Interestingly enough, Erlang developers came up with a programming paradigm that's in fact based on the axioms of the actor model. So to speak, the wheel was invented twice. But Armstrong didn't came up with a remarkable name for the programming paradigm while Hewitt did.Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-45857277043007995792012-04-16T06:34:00.000-07:002012-06-29T06:48:29.706-07:00Guards! Guards!<i>(no, this post is not about <a href="http://en.wikipedia.org/wiki/Guards!_Guards!">the Discworld novel</a>)</i>
<br><br>
Guards are a new feature in libcppa. More precisely, it's an adaption of <a href="http://www.erlang.org/doc/reference_manual/expressions.html#id79432">Erlangs guard sequences for patterns</a>. A guard is an optional expression that evaluates to either true or false for a given input (message). Guards can be used to constrain a given match statement by using placeholders (<tt>_x1</tt> - <tt>_x9</tt>) as shown in the example below.
<pre class="brush:cpp">
using namespace cppa;
using namespace cppa::placeholders;
receive_loop(
on<int>().when(_x1 % 2 == 0) >> []() {
// int is even
},
on<int>() >> []() {
// int is odd
}
);</pre>
Guard expressions are a lazy evaluation technique (somewhat like <a href="http://www.boost.org/doc/libs/1_49_0/doc/html/lambda.html">boost lambdas</a>). The placeholder <tt>_x1</tt> is substituted with the first value of an incoming message. You can use all binary comparison and arithmetic operators as well as "<tt>&&</tt>" and "<tt>||</tt>". In addition, there are two functions designed to be used in guard expressions: <tt>gref</tt> and <tt>gcall</tt>. The function <tt>gref</tt> creates a reference wrapper. It's similar to <a href="http://en.cppreference.com/w/cpp/utility/functional/ref">std::ref</a> but it is always const and 'lazy'. A few examples to illustrate some pitfalls:
<pre class="brush:cpp">
int ival = 42;
receive(
on<int>().when(ival == _x1) // (1) ok, matches if _x1 == 42
on<int>().when(gref(ival) == _x1) // (2) ok, matches if _x1 == ival
on<int>().when(std::ref(ival) == _x1) // (3) ok, because of placeholder
on<anything>().when(gref(ival) == 42) // (4) ok, matches everything as long as ival == 42
on<anything>().when(std::ref(ival) == 42) // (5) compiler error
);
</pre>
The statement <tt>std::ref(ival) == 42</tt> is evaluated immediately and returns a boolean, whereas <tt>gref(ival) == 42</tt> creates a guard expression. Thus, you should always use <tt>gref</tt> instead of <tt>std::ref</tt> to avoid subtle errors.<br><br>
By the way, <tt>gref</tt> is a great way to reduce verbosity of receive loops:
<br><br>
<pre class="brush:cpp">
bool done = false;
do_receive(
// ...
on<atom("shutdown")>() >> [&]() {
done = true;
}
)
.until(gref(done));
//equal to: .until([&]() { return done; })</pre>
<br><br>
The second function, <tt>gcall</tt>, encapsulates a function call. It's usage is similar to <a href="http://en.cppreference.com/w/cpp/utility/functional/bind">std::bind</a>, but there is also a short version for unary functions: <tt>gcall(..., _x1)</tt> is equal to <tt>_x1(...)</tt>.
<pre class="brush:cpp">
auto vec_sorted = [](std::vector<int> const& vec) {
return std::is_sorted(vec.begin(), vec.end());
};
receive(
on<std::vector<int>>().when(gcall(vec_sorted, _x1)) // equal to:
on<std::vector<int>>().when(_x1(vec_sorted))) // ...
);
</pre>
Placeholders provide some more convenience member functions besides <tt>operator()</tt>. A few code snippets:
<pre class="brush:cpp">
_x1.starts_with("hello")
_x1.size() > 10
_x1.in({"abc", "def"})
_x1.not_in({0, 10, 100})
_x1.empty()
_x1.not_empty()
_x1.front() == 42
</pre>
A final note: you don't have to check if a container is empty before calling <tt>_x1.front()</tt>, because <tt>front()</tt> returns an <a href="http://libcppa.blogspot.de/2012/01/opt-for-option.html">option</a> for a reference to the first element.<br><br>
Have fun!Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0tag:blogger.com,1999:blog-4171526517897577490.post-45778228047362119662012-03-09T01:19:00.000-08:002012-06-29T06:46:47.257-07:00A Few Words About TheronTheron is currently the only existing actor library for C++ besides <tt>libcppa</tt>.
It implements event-based message processing without mailbox, using registered member functions as callbacks.
I wanted to include Theron to my three benchmarks, but I had some trouble to get Theron running on Linux. I've compiled Theron in release mode, ran its PingPong benchmark ... and got a segfault. GDB pointed me to the DefaultAllocator implementation and I could run the benchmarks after replacing the memory management with plain malloc/free. Thus, the shown results might be some percentages better with a fixed memory management. However, I was unable to get results for the <a href="http://libcppa.blogspot.com/2012/02/actor-creation-overhead.html">Actor Creation Overhead</a> benchmark because Theron crashed for more than 2<sup>10</sup> actors.
<br><br>
Theron has two ways of sending a message to an actor, because it distincts between references and addresses. The <tt>push</tt> method can be used only if one has a reference to an actor. This is usually only the case for the creator of an actor. The <tt>send</tt> method uses addresses and is the general way to send messages.
<br><br>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWbwO09brI4KROJUtKkJJo7pi7V1Qx1KIAZsJzGeAFTMhUrSFC50I1nvS1e5VUDUdZ52jp8HFy8s06S6ZHCbKbxMy4aJJLMLkfZpJiD8juqHmki4AOx5riG4C3qYHRXlns-zaQJBdhn-Q/s1600/theron_mailbox_performance.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="300" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWbwO09brI4KROJUtKkJJo7pi7V1Qx1KIAZsJzGeAFTMhUrSFC50I1nvS1e5VUDUdZ52jp8HFy8s06S6ZHCbKbxMy4aJJLMLkfZpJiD8juqHmki4AOx5riG4C3qYHRXlns-zaQJBdhn-Q/s400/theron_mailbox_performance.png" /></a></div>
<br><br>
The results for the <a href="http://libcppa.blogspot.com/2012/02/libcppa-vs-erlang-vs-scala-performance.html">Mixed Scenario</a> benchmark are as follows.
<br><br>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheeILYQ9H-Lme2JvlxZ8TDJyAVOH9MAXvsuY3TMOmLEWFGOuqErccx6f6zc1LOJK63aMZsX2HG2ChO1U9CBegw5Ezu3iAsgQew1HjXHxp-3QARwIzCWFbPH50rdFJqHY-WEA582i2TDik/s1600/theron_mixed_case.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="300" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheeILYQ9H-Lme2JvlxZ8TDJyAVOH9MAXvsuY3TMOmLEWFGOuqErccx6f6zc1LOJK63aMZsX2HG2ChO1U9CBegw5Ezu3iAsgQew1HjXHxp-3QARwIzCWFbPH50rdFJqHY-WEA582i2TDik/s400/theron_mixed_case.png" /></a></div>
<br><br>
Theron yields good results on two and four cores. However, the more concurrency we add, the more time Theron needs in the mixed scenario. I don't know about Theron's internals, but this is a common behavior of mutex-based software in many-core systems and cannot be explained by the "missing" memory management.
<br><br>
I used Theron in version 3.03. As always, the benchmarks ran on a virtual machine with Linux using 2 to 12 cores of the host system
comprised of two hexa-core Intel® Xeon® processors with 2.27GHz. All values are the average of five runs.<br>
<br>
The sources can be found on github in the <a href="https://github.com/Neverlord/libcppa/tree/master/benchmarks">benchmark folder</a> (<a href="https://github.com/Neverlord/libcppa/blob/master/benchmarks/theron_mailbox_performance.cpp">theron_mailbox_performance.cpp</a> and <a href="https://github.com/Neverlord/libcppa/blob/master/benchmarks/theron_mixed_case.cpp">theron_mixed_case.cpp</a>).Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com10tag:blogger.com,1999:blog-4171526517897577490.post-43751159235325105002012-03-08T07:38:00.000-08:002013-01-02T04:11:41.542-08:00Mailbox Part 2It's been a while since I've posted <a href="http://libcppa.blogspot.com/2011/04/mailbox-part-1.html">Mailbox Part 1</a> and I promised a benchmark for a 1:N communication scenario for up to 12 cores. So here it is. This benchmark compares libcppa to Erlang and Scala with its two standard library implementations and Akka.<br><br>
The benchmark uses 20 threads sending 1,000,000 messages each, except for Erlang which does not have a threading library. In Erlang, I spawned 20 actors instead. The minimal runtime of this benchmark is the time the receiving actor needs to process 20,000,000 messages and the overhead of passing the messages to the mailbox. More hardware concurrency leads to higher synchronization between the sending threads, since the mailbox acts as a shared resource.
<br><br>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMVH1Y9zQt9n0RfLBt-tsjcNGkMrp2CYBRzWvQrkJOus5gqcQ6KSr_HPQVPZvRm2BlGl9XPw3DnEeQyR1i0Up-ZK0S9RASk0VarewYGHerQj7xJoEVX2o9o8WYoba5fcGEBaLtcGfXn-w/s1600/mailbox_performance.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="300" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMVH1Y9zQt9n0RfLBt-tsjcNGkMrp2CYBRzWvQrkJOus5gqcQ6KSr_HPQVPZvRm2BlGl9XPw3DnEeQyR1i0Up-ZK0S9RASk0VarewYGHerQj7xJoEVX2o9o8WYoba5fcGEBaLtcGfXn-w/s400/mailbox_performance.png" /></a></div>
<br><br>
Both <tt>libcppa</tt> implementations show similar performance to Scala (receive) on two cores but have a faster increasing curve.
The message passing implementation of Erlang does not scale well for this use case. The more concurrency we add, the more time the Erlang program needs, up to an average of 600 seconds on 12 cores. The results are clipped for visibility purposes in the graph.
The increase in runtime for <tt>libcppa</tt> is similar to the increase seen in the <a href="http://libcppa.blogspot.com/2012/02/actor-creation-overhead.html">Actor Creation Overhead</a> benchmark and is caused by the scheduler (the cached stack algorithm scales very well and is not a limiting factor here).
The overhead of stack allocation is negligible in this use case. Thus, the run time of both <tt>libcppa</tt> implementations is almost identical.
<br><br>
The benchmarks ran on a virtual machine with Linux using 2 to 12 cores of the host system
comprised of two hexa-core Intel® Xeon® processors with 2.27GHz. All values are the average of five runs.<br>
<br>
The sources can be found <a href="https://github.com/Neverlord/cppa-benchmarks/tree/master">on github</a> (<a href="https://github.com/Neverlord/cppa-benchmarks/blob/master/scala/MailboxPerformance.scala">MailboxPerformance.scala</a>, <a href="https://github.com/Neverlord/cppa-benchmarks/blob/master/erlang/mailbox_performance.erl">mailbox_performance.erl</a> and <a href="https://github.com/Neverlord/cppa-benchmarks/blob/master/cppa/mailbox_performance.cpp">mailbox_performance.cpp</a>).Dominik Charoussethttp://www.blogger.com/profile/01681682799621239876noreply@blogger.com0