After some research on internet for an efficient way to implement events in C++, I found the following methods
Interface class - Applications can override the virtual functions in the derived class
Normal Callback mechanism using function pointers
Delegates using Boost.function
Signals and slots (as used in Qt)
I am confused on advantages and disadvantages of each of these and when to use anyone of this.
Which is the best method and why?
Is there any other solutions which are better than the ones listed?
FWIW, my vote would be for Boost Signals any day.
Boost ensures portability. Of course it integrates nicely with e.g. Boost Asio, Functional, Bind, etc.
Update:
Signals2
This documentation describes a thread-safe variant of the original Boost.Signals library. There have been some changes to the interface to support thread-safety, mostly with respect to automatic connection management. [....]
Boost ensures portability. Of course it integrates nicely with e.g. Boost Asio, Functional, Bind, etc.
boost::signals2::signal sig;
sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);
sig(5., 3.);
This program will print out the following:
The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
sample actions:
void print_sum(float x, float y)
{
std::cout << "The sum is " << x+y << std::endl;
}
void print_product(float x, float y)
{
std::cout << "The product is " << x*y << std::endl;
}
void print_difference(float x, float y)
{
std::cout << "The difference is " << x-y << std::endl;
}
void print_quotient(float x, float y)
{
std::cout << "The quotient is " << x/y << std::endl;
}
Have you checked GBL library? It has all facilities that you might need (and probably more) for even-driven design. You can build (real) timed and un-timed models with it. It's pure C++, not polluted with macros. It also makes use of C++0x for improved performance. Also if you use C++0x compiler you get lambda functions working as event handlers -- it's very powerful. GBL supports synchronous and asynchronous event handlers, threads, and fibers. It abstracts event flow via signals and ports. With some ingenuity and careful design you can use asynchronous event handlers and significantly improve performance on multicore/multiprocessor systems. It also has a graphical designer and tracer.
Building and maintaining event-driven applications can be very difficult without visualization, designer helps with that a lot. Debugging event-driven applications can also be very difficult, because you no longer have a sequential execution, rather the execution is jumping from one event handler to another, so having an event tracer helps significantly.
First two options are part of the basic C++ standard, with the function callbacks being compatible with C code as well.
The other two options require using boost and Qt respectively.
Advantages/disadvantages is kindof too broad a question, and the answer depends greatly on what you're doing, in what environment and for what purpose.
You can use Observer design pattern. Here is an example C++ source of it.
http://sourcemaking.com/design_patterns/observer/cpp/3
Related
I've been writing some javascript and one of the few things I like about the environment is the way it uses promises/futures to make handlers for asynchronous events.
In C++ you have to call .get on a future and it blocks until the result of the future is available but in Javascript you can write .then(fn) and it will call the function when the result is ready. Critically it does this in the same thread as the caller at a later time so there are no thread synchronization issues to worry about, at least not the same ones as in c++.
I'm thinking in c++ something like -
auto fut = asyncImageLoader("cat.jpg");
fut.then([](Image img) { std::cout << "Image is now loaded\n" << image; });
Is there any way to achieve this in c++? Clearly it will need some kind of event queue and event loop to handle dispatching the callbacks. I could probably eventually write the code to do most of this but wanted to see if there was any way to achieve the goal easily using standard facilities.
A .then function for std::future has been proposed for the upcoming C++17 standard.
Boost's implementation of future (which is compliant with the current standard, but provides additional features as extensions) already provides parts of that functionality in newer versions (1.53 or newer).
For a more well-established solution, take a look at the Boost.Asio library, which does allow easy implementation of asynchronous control flows as provided by future.then. Asio's concept is slightly more complicated, as it requires access to a central io_service object for dispatching asynchronous callbacks and requires manual management of worker threads. But in principle this is a very good match for what you asked for.
I don't like c++'s future, so i wrote a promise libraries as javascript here
https://github.com/xhawk18/promise-cpp
/* Convert callback to a promise (Defer) */
Defer myDelay(boost::asio::io_service &io, uint64_t time_ms) {
return newPromise([&io, time_ms](Defer &d) {
setTimeout(io, [d](bool cancelled) {
if (cancelled)
d.reject();
else
d.resolve();
}, time_ms);
});
}
void testTimer(io_service &io) {
myDelay(io, 3000).then([&] {
printf("timer after 3000 ms!\n");
return myDelay(io, 1000);
}).then([&] {
printf("timer after 1000 ms!\n");
return myDelay(io, 2000);
}).then([] {
printf("timer after 2000 ms!\n");
}).fail([] {
printf("timer cancelled!\n");
});
}
int main() {
io_service io;
testTimer(io);
io.run();
return 0;
}
compare with Javascript promise, just --
Use newPromise instead of js's new Promise
Use lambda instead of js function
Use d.resolve instead of js's resolve
Use d.reject instead of js's reject
You can resolve/reject with any type of paramters, and need not care about the troublesome of <> in c++ template.
While then is proposed, you can implement your own infix then via the named operator technique.
Create a struct then_t {}; and a static then_t then;. Now override operator* on the left and right so that std::future<bool> *then* lambda creates a std::async that waits on the future, and passes the result to the lambda, then returns the return value of the lambda.
This requires lots of care and attention, as you have to carefully create copies to avoid dangling references, and mess around with r and l value syntax to make it fully efficient.
The end syntax you get is:
aut fut = asyncLoader("cat.jpg");
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; };
which is pretty close to what you want.
If you are really smart, you could even have it also support:
aut fut = asyncLoader("cat.jpg");
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); };
which gets rid of some of the boilerplate and would be useful sometimes. This requires asyncLoader to return a std::shared_future instead of a future.
You could pass an object thats for example implementing a Runnable class to the "then" method of the Future class. Once the Future finished its work, call the "run" method of the passed object.
Take a look at https://github.com/Naios/continuable . It supports Javascript style .then(). It also supports exceptions with .fail() (instead of .catch()). There is a great talk about it here https://www.youtube.com/watch?v=l6-spMA_x6g
Use JavaScript-like Promises for C++20. It relies on C++20 coroutines, supports ES6 await/async semantics, and very importantly, it supports 'move' so you can write wrappers for frameworks like asio (e.g. because asio::ip::tcp::socket cannot be copied).
Link: https://github.com/virgil382/JSLikePromise
The question is a bit old, but here is a Javascript-like promise library (consist of a single header that you simply need to include) that aims to do exactly what you ask for, of course together with some sort of async I/O library to implement the actual asyncImageLoader().
https://github.com/alxvasilev/cpp-promise
While at their core dynamic binding and templates are fundamentally different things, they can be used to implement the same functionality.
Code example (only for reference)
A) dynamic binding
namespace DB {
// interface
class CustomCode {
public:
virtual void operator()(char) const = 0;
};
class Lib {
public:
void feature(CustomCode const& c) {
c('d');
}
};
// user code
class MyCode1 : public CustomCode {
public:
void operator()(char i) const {
std::cout << "1: " << i << std::endl;
}
};
class MyCode2 : public CustomCode {
public:
void operator()(char i) const {
std::cout << "2: " << i << std::endl;
}
};
void use() {
Lib lib;
lib.feature(MyCode1());
lib.feature(MyCode2());
}
}
B) generic programming
namespace GP {
//interface
template <typename CustomCode> class Lib {
public:
void feature(CustomCode const& c) {
c('g');
}
};
// user code
class MyCode1 {
public:
void operator()(char i) const {
std::cout << "1: " << i << std::endl;
}
};
class MyCode2 {
public:
void operator()(char i) const {
std::cout << "2: " << i << std::endl;
}
};
void use() {
Lib<MyCode1> lib;
lib.feature(MyCode1());
//lib.feature(MyCode2()); <-- illegal
}
}
Question
Some thoughts
While these paradigms are not identical and have their advantages and disadvantages (A is a bit more powerful (see MyCode2) and B is more flexible for the user) they both allow the implementation of the same functionality (while the limitations hinted above apply).
Anyway, in theory (TM) A is a bit slower at runtime because of the indirection of the virtual function, while B offers some great optimisation opportunities as methods can be inlined (and of course you don't have the indirection).
However, I often feel that A is a bit more self-documenting because you have a clear interface you have to implement (which usually consists of more than one method) while B is a bit more anarchistic (which implies its flexibility).
Core
Are there any general results / comparative studies of these paradigms?
Is the speed-up significant?
What about compilation time?
What are the design implications of either for interfaces in larger systems (I mainly used A for my inter-module interfaces and I haven't done really really big projects so far)?
Edit
Note: Saying "dynamic binding is better because it is more powerful" is not at all an answer, because the precondition is that you have a case where both approaches are applicable (otherwise there is no freedom to choose -- at least not reasonably).
Are there any general results / comparative studies of these paradigms?
from what i have seen, many examples of proofs can be found in articles and publications. your favorite c++ books should provide several demonstrations; if you have no such resource, you may want to read Modern C++ Design: Generic Programming and Design Patterns Applied - A. Alexandrescu. although, there is not a specific resource that comes to mind that directly answers your question. as well, the result will vary by implementation and compiler - even compiler settings can greatly affect the outcome of such a test. (responding to each of your questions, although this does not qualify as an answer to this specific question).
Is the speed-up significant?
short answer: it depends.
in your example, the compiler could in fact use static dispatch or even inline the virtual function calls (enough information is visible to the compiler). i am now going to move the responses away from a trivial example (specifically, the OP) to larger, more complex programs.
expanding on 'it depends': yes, the speed up can range from unmeasurable to huge. you have to (and likely already) realize that the compiler can be provided an incredible amount of information at compilation via generics. it can then use this information to optimize your program much more accurately. one good example of this is the use of std::array vs std::vector. the vector adds flexibility at runtime, but the cost can be quite significant. the vector needs to implement more for resizing, the need for dynamic allocations can be costly. there are other differences: the backing allocation of the array will not change (++optimization), the element count is fixed (++optimization), and again - there's no need to call through new in many cases.
you may now be thinking this example has significantly deviated from the original question. in many ways, it's really not so different: the compiler knows more and more about your program as its complexity expands. this information can remove several portions of your program (dead code) and using std::array as an example, the information the type provides is enough such that a compiler can easily say "oh, i see that this array's size is seven elements, i will unroll the loop accordingly" and you will have fewer instructions and will have eliminated mispredictions. there's a lot more to it, but in the array/vector case, i have seen executable size of optimized programs reduce to 20% when converting from vector to an interface similar to array. as well, the code can perform several times faster. in fact, some expressions can be calculated entirely at compilation.
dynamic dispatch still has its virtues, and using dynamic dispatch can also improve your program's speed if used correctly - what you will really need to learn comes down to deciding when to favor one over the other. similar to how a huge function with many variables cannot be optimized very effectively (the result of all that template expansion in a real program), a virtual function call can in fact be a faster, cleaner approach in many situations. as such, they are two separate features, you will need some practice to determine what is right (and many programmers don't take the time to learn this well enough).
in conclusion, they should be regarded as separate features, applicable to different scenarios. these should (imho) have have much less practical overlap than they actually do in the real world.
What about compilation time?
with templates, the compilation and link times during development can be quite high. each time a header/template changes, you will require a compilation on all dependencies -- this can often be a significant boon for favoring dynamic dispatch. you can of course reduce this if you plan ahead and build out appropriately - understanding how is a much more difficult subject to master with templates. with templates, you not only increrase the frequency of large builds, you often increase the time and complexity of large builds. (more notes follow)
What are the design implications of either for interfaces in larger systems (I mainly used A for my inter-module interfaces and I haven't done really really big projects so far)?
it really depends on your program's expectations. i write virtual less every year (and many others as well). among other approaches, templates are becoming more and more common. honestly, i don't understand how B is 'anarchistic'. to me, A is a bit anachronistic as there are plenty of suitable alternatives. it's ultimately a design choice which can take a lot of consideration to architect large systems well. a good system will use a healthy combination of the language's features. history proves no feature in this discussion is necessary to write a nontrivial program, but all features were added because somebody saw better alternatives in some specific uses. you should also expect lambdas to replace virtuals in more than 50% of their current uses in some (not all) teams/codebases.
Generalizations:
templates can be significantly faster to execute, if used correctly.
either can produce larger executables. if used correctly and executable size is important, then the writer will use multiple approaches to reduce executable size while providing nice usable interfaces.
templates can grow very very complex. learning to crawl through and interpret error messages takes time.
templates push several errors into the compilation domain. personally, i favor a compilation error over a runtime error.
reducing compilation times via virtuals is often straightforward (virtuals belong in the .cpp). if your program is huge, then huge template systems that change often can quickly send your rebuild times and counts through the roof because there will be a lot of intermodule visibility and dependency.
deferred and/or selective instantiation with fewer compiled files can be used to reduce compile times.
in larger systems, you'll have to be much more considerate about forcing a nontrivial recompiles for your team/client. using virtuals are one approach to minimize this. as well, a higher percentage of your methods will be defined in the cpp. the alternative is of course that you can hide more of the implementation or provide to the client more expressive ways to use your interfaces.
in larger systems, templates, lambdas/functors, etc. can actually be used to significantly reduce coupling and dependencies.
virtuals increase dependency, often become difficult to maintain, bloat interfaces, and become structurally awkward beasts. template-centric libraries tend to invert that precedence.
all approaches can be used for the wrong reasons.
Bottom Line
a large, well designed modern system will use many paradigms effectively and simultaneously. if you use virtuals most of the time at present, you are (imo) doing it wrong -- especially if that is still the approach once you've had time to absorb c++11. if speed, performance, and/or parallelism are also significant concerns, then templates and lambdas deserve to be your closer friends.
Which is better? It depends. You've focused on the overlap. Better is to focus on where the approaches diverge. You also missed where you need to use both approaches simultaneously.
The biggest advantage of templates is that they offer the ability to cut down, sometimes immensely, on cookie-cutter code. Another advantage of templates is metaprogramming. There are some truly bizarre things you can do thanks to SFINAE.
One disadvantage of templates is that the syntax is a bit clunky. There is no way around this. It is what it is. Another disadvantage of templates is that each instantiation is a different class, completely unrelated to the other classes instantiated from the same template class. There is a way around this: Combine both approaches. Make your template class derive from some non-template base class. Of course, now you have lost some of the run time advantages.
The biggest advantage of polymorphism is that it is dynamic. This can be a huge, huge win. Don't discount it. There is a performance penalty for such polymorphism, but you are going to pay that penalty one way or another if you want to have a collection of objects that obey a common interface but different objects have different implementations for that interface.
I'm looking for a solution for this problem in C or C++.
edit: To clarify. This is on a linux system. Linux-specific solutions are absolutely fine. Cross-plaform is not a concern.
I have a service that runs in its own thread. This service is a class with several methods, some of which need to run in the own service's thread rather than in the caller's thread.
Currently I'm using wrapper methods that create a structure with input and output parameters, insert the structure on a queue and either return (if a "command" is asynchronous) or wait for its execution (if a "command" is synchronous).
On the thread side, the service wakes, pops a structure from the queue, figures out what to execute and calls the appropriate method.
This implementation works but adding new methods is quite cumbersome: define wrapper, structure with parameters, and handler. I was wondering if there is a more straightforward means of coding this kind of model: a class method that executes on the class's own thread, instead of in the caller's thread.
edit - kind of conclusion:
It seems that there's no de facto way to implement what I asked that doesn't involve extra coding effort.
I'll stick with what I came up with, it ensures type safeness, minimizes locking, allows sync and async calls and the overhead it fairly modest.
On the other hand it requires a bit of extra coding and the dispatch mechanism may become bloated as the number of methods increases. Registering the dispatch methods on construction, or having the wrappers do that work seem to solve the issue, remove a bit of overhead and also remove some code.
My standard reference for this problem is here.
Implementing a Thread-Safe Queue using Condition Variables
As #John noted, this uses Boost.Thread.
I'd be careful about the synchronous case you described here. It's easy to get perf problems if the producer (the sending thread) waits for a result from the consumer (the service thread). What happens if you get 1000 async calls, filling up the queue with a backlog, followed by a sync call from each of your producer threads? Your system will 'play dead' until the queue backlog clears, freeing up those sync callers. Try to decouple them using async only, if you can.
There are several ways to achieve this, depending upon the complexity you want to accept. Complexity of the code is directly proportional to the flexibility desired. Here's a simple one (and quite well used):
Define a classes corresponding to each functionality your server exposes.
Each of these classes implements a function called execute and take a basic structure called input args and output args.
Inside the service register these methods classes at the time of initialization.
Once a request comes to the thread, it will have only two args, Input and Ouput, Which are the base classes for more specialized arguments, required by different method classes.
Then you write you service class as mere delegation which takes the incoming request and passes on to the respective method class based on ID or the name of the method (used during initial registration).
I hope it make sense, a very good example of this approach is in the XmlRpc++ (a c++ implementation of XmlRpc, you can get the source code from sourceforge).
To recap:
struct Input {
virtual ~Input () = 0;
};
struct Ouput {
virtual ~Output () = 0;
};
struct MethodInterface {
virtual int32_t execute (Input* __input, Output* __output) = 0;
};
// Write specialized method classes and taking specialized input, output classes
class MyService {
void registerMethod (std::string __method_name, MethodInterface* __method);
//external i/f
int32_t execute (std::string __method, Input* __input, Output* __output);
};
You will still be using the queue mechanism, but you won't need any wrappers.
IMHO, If you want to decouple method execution and thread context, you should use Active Object Pattern (AOP)
However, you need to use ACE Framework, which supports many OSes, e.g. Windows, Linux, VxWorks
You can find detailed information here
Also, AOP is a combination of Command, Proxy and Observer Patterns, if you know the details of them, you may implement your own AOP. Hope it helps
In addition to using Boost.Thread, I would look at boost::function and boost::bind. That said, it seems fair to have untyped (void) arguments passed to the target methods, and let those methods cast to the correct type (a typical idiom for languages like C#).
Hey now Rajivji, I think you have it upside-down. Complexity of code is inversely proportional to flexibility. The more complex your data structures and algorithms are, the more restrictions you are placing on acceptable inputs and behaviour.
To the OP: your description seems perfectly general and the only solution, although there are different encodings of it. The simplest may be to derive a class from:
struct Xqt { virtual void xqt(){} virtual ~Xqt(){} };
and then have a thread-safe queue of pointers to Xqt. The service thread then just pops the queue to px and calls px->xqt(), and then delete px. The most important derived class is this one:
struct Dxqt : Xqt {
xqt *delegate;
Dxqt(xqt *d) : delegate(d) {}
void xqt() { delegate->xqt(); }
};
because "all problems in Computer Science can be solved by one more level of indirection" and in particular this class doesn't delete the delegate. This is much better than using a flag, for example, to determine if the closure object should be deleted by the server thread.
I am entering a realm that is new to me, but basically I need to implement callbacks in C++. I am designing a toolkit for myself to use to simplify my life. Basically it is a .dll plugin that will be exposing a lot of functions to my other .dll plugins.
One of these functions is HookEvent(const char *event_name, void *callback) which will allow me to hook different events that get fired. Here would be an example...
Example_Plugin1.dll does HookEvent("player_spawn", &Plugin1::Event_PlayerSpawn);
Example_Plugin2.dll does HookEvent("player_spawn", &Plugin2::Event_PlayerSpawn);
I need to figure out the best (and preferably easiest) method of setting up a callbacks system that will work well for this. I have been reading up on C++ callbacks for a few hours now, and found quite a few different approaches.
I assume the easiest thing to do would be make a template, and use typedef bool (ClassName::*EventHookCallback)(IGameEvent, bool); After that, I am a bit foggy.
I also read that Delegates or a .NET style events system are other possible approaches. I am already somewhat confused, so I don't want to confuse myself more, but figured it was worth asking.
Here is a link to the C++ .NET style events system I was reading about.
http://cratonica.wordpress.com/2010/02/19/implementing-c-net-events-in-c/
So what do you guys suggest? Any tips as far as implementing it would be most appreciated.
If you want generalized event firing Boost.Signals2 might be applicable.
The Boost.Signals2 library is an
implementation of a managed signals
and slots system. Signals represent
callbacks with multiple targets, and
are also called publishers or events
in similar systems. Signals are
connected to some set of slots, which
are callback receivers (also called
event targets or subscribers), which
are called when the signal is
"emitted."
Even if you don't need this level of flexibility you should be able to simplify the function binding in your code using Boost.Bind, or the C++0x equivalents.
EDIT:
There's an excellent discussion from Herb Sutter of the issues you could face here. You could use this for guidance if you decide you don't need the full Boost feature set, and so roll your own.
How about using Qt Signal and Slot? It does what callbacks do but without the messiness of making anything not part of your callback parameters global.
Boost.Signals would be my choice, combined with things like boost::bind and Boost.Function.
I would use an abstract base class as a plugin interface. (And in fact, I have used a pattern like the one below before.)
Library, PluginIfc.h:
class PluginIfc {
public:
virtual ~PluginIfc() = 0;
virtual bool EventCallback(const char* event_name, IGameEvent, bool) = 0;
};
// For Windows, add dllexport/dllimport magic to this declaration.
// This is the only symbol you will look up from the plugin and invoke.
extern "C" PluginIfc* GetPlugin();
Plugin:
#include <PluginIfc.h>
class Plugin1 : public PluginIfc {
public:
virtual bool EventCallback(const char* event_name, IGameEvent, bool);
Plugin1& get() { return the_plugin_obj; }
bool Event_PlayerSpawn(IGameEvent, bool);
// ...
private:
std::vector<std::string> _some_member;
static Plugin1 the_plugin_obj; // constructed when plugin loaded
};
Plugin1 Plugin1::the_plugin_obj;
PluginIfc* GetPlugin() { return &Plugin1::get(); }
This way, your plugin classes can easily have members, and C++'s virtual call mechanism takes care of giving you a good this pointer in EventCallback.
It may be tempting to make a virtual method per event type, say just make Event_PlayerSpawn and similar methods virtual. But then whenever you want to add an event type, if this means changing class PluginIfc, your old compiled plugins are no longer compatible. So it's safer to use a string event identifier (for extensibility) and have the main callback sort events off to more specific methods.
The major drawback here (as compared to a signal-slot type implementation) is that all callbacks must take the same set of arguments. But your question sounded like that would be adequate. And it's often possible to work within that limitation by making sure the set of arguments is very flexible, using strings to be parsed or Any-style objects.
Sounds like you might be interested in how to build your own plugin framework. The problems you'll encounter are likely the same. Have a look at this nice Dr Dobbs article Building Your Own Plugin Framework.
Hope this helps!
Implementing your own callback system is non-trivial.
My understanding is that your aim is to map event types to specific callback functions.
E.g. if "player_spawn" event is risen the &Plugin1::Event_PlayerSpawn will be called.
So what you should do is the following:
1) Define all the events of interest. Make them as generic as possible. They can
encapsulate any information you need
2) Create a Registrar. I.e. a class that all modules register their interest for specific
methods. E.g. Registrar.register(player_spawn,this,Event_PlayerSpawn);
3) Registrar has a queue of all subscribers.
4) You can also have a uniform interface for the modules. I.e. all module implement a specific function but based on event's data can do different things
5) When an event occurs, all the subscribers interested for the specific event get notified by calling the appropriate function
6)Subscriber can de-register when ever is need
Hope this helps.
Actually, this question seems to have two parts:
How to implement pattern matching?
How to implement send and receive (i.e. the Actor model)?
For the pattern matching part, I've been looking into various projects like App and Prop. These look pretty nice, but couldn't get them to work on a recent version (4.x) of g++. The Felix language also seems to support pattern matching pretty well, but isn't really C++.
As for the Actor model, there are existing implementations like ACT++ and Theron, but I couldn't find anything but papers on the former, and the latter is single-threaded only [see answers].
Personally, I've implemented actors using threading and a thread-safe message queue. Messages are hash-like structures, and used these together with a number of preprocessor macros to implemented simple pattern matching.
Right now, I can use the following code to send a message:
(new Message(this))
->set("foo", "bar")
->set("baz", 123)
->send(recipient);
And the following to do simple pattern matching (qDebug and qPrintable are Qt-specific):
receive_and_match(m)
match_key("foo") { qDebug("foo: %s", qPrintable(m->value("foo").toString())); }
or_match_key("baz") { qDebug("baz: %d", m->value("baz").toInt()); }
or_match_ignore
end_receive
However, this looks a bit hackish to me, and isn't very robust.
How would you do it? Did I miss any existing work?
As for the Actor model, there are
existing implementations like ACT++
and Theron, but I couldn't find
anything but papers on the former, and
the latter is single-threaded only.
As the author of Theron, I was curious why you believe it's single-threaded?
Personally, I've implemented actors
using threading and a thread-safe
message queue
That's how Theron is implemented.. :-)
Ash
One of the important things about erlang is how the features are used to make robust systems.
The send/recieve model is no-sharing, and explicitly copying.
The processes themselves are lightweight threads.
If you did desire the robust properties of the erlang model, you would be best to use real processes and IPC rather than threads.
If you want robust message passing though you may end up wanting to serialize and deserialise the contents. Especially with type safety.
Pattern matching in C++ isn't always pretty but there will be a good pattern for this - you will end up creating a dispatcher object that uses some form of polymorphism to get what you want.
Although if you are not careful you end up with xml over pipes :)
Really, if you want the erlang model you really want to use erlang. If there are slow bits, I'm sure you can augment your program using a foreign function internet.
The problem about re-implementing parts, is you won't get a good cohesive library and solution. The solutions you have already don't look much like C++ anymore.
I'm currently implementing an actor library for C++ called "acedia" (there's nothing yet about it on google) that uses "type matching". The library is a project for my master thesis and you can send any kind of data to an actor with it.
A small snippet:
recipient.send(23, 12.23f);
And on the recipient side you can either analyze the received message like this:
Message msg = receive();
if (msg.match<int, float>() { ... }
... or you can define a rule set that invokes a function or method for you:
void doSomething(int, float);
InvokeRuleSet irs;
irs.add(on<int, float>() >> doSomething);
receiveAndInvoke(irs);
It's also possible to match both on type and on value:
Message msg = receive();
if (msg.match<int, float>(42, WILDCARD) { ... }
else if (msg.match<int, float>() { ... }
The constant "WILDCARD" means, that any value will be acceptet. Pass no arguments is equal set all arguments to "WILDCARD"; meaning that you only want to match the types.
This is certainly a small snippet. Also you can use "case classes" like in Scala. They are comparable to "atomics" in erlang. Here is a more detailed example:
ACEDIA_DECLARE_CASE_CLASS(ShutdownMessage)
ACEDIA_DECLARE_CASE_CLASS(Event1)
ACEDIA_DECLARE_CASE_CLASS(Event2)
To react to the defined case classes you can write an actor like this:
class SomeActor : public Actor
{
void shutdown() { done = true; }
void handleEvent1();
void handleEvent1();
public:
SomeActor() : done(false) { }
virtual void act()
{
InvokeRuleSet irs;
irs
.add(on<ShutdownMessage>() >> method(&SomeActor::shutdown))
.add(on<Event1>() >> method(&SomeActor::handleEvent1))
.add(on<Event2>() >> method(&SomeActor::handleEvent2))
;
while (!done) receiveAndInvoke(irs);
}
};
To create a new actor and start it, all you have to write is:
Acedia::spawn<SomeActor>();
Although the library not even reached beta stadium the shown snippets work and i have a first application running on it. One major goal of the library is to support distributed programming (also across a network).
Your question is a while ago, but if you're interested in it: let me know! :)
You can mimic the behavior using Qt's signal/slot mechanism, especially since Qt's signal/slot supports multithread.
I would definitely be interested in looking at your "acedia" library and would love to help in any way that I could. Erlang has some wonderful constructs and C++ could definitely benefit from such a library.
Today I hostet the library at sourceforge: https://sourceforge.net/projects/acedia/
As I said before it's an early release. But feel free to critique it!
Today, if you want erlang style robust actors in C++, and pattern matching,
maybe Rust is the answer.
Of course this wasn't around publically when the OP asked ~5years ago, and as of april 2014 it still isn't v1.0 yet - but its been progressing very well and is definitely stabilizing, enough of the language core is stable I think.
And ok its not C++, but it has the same approach to memory management as C++, except that it supports lightweight tasks with no shared memory by default (then provides controlled library features for sharing - "Arc");
It can directly call (and directly expose) 'extern C' functions. You can't share templated library headers with C++ - but you can write generics that mimick C++ collection classes (and vica versa) to pass references to data-structures across.