actorpp – simple concurrency in C++
This is the documentation for actorpp, C++ library for implementing concurrent systems with message passing.
actorpp implements a go-like model, in which threads communicate by sharing
Channel objects. Many threads can push data to a channel, while only
one reads from it.
To wait for data on multiple channels, all channels need to share the same
mutex and condition variable. These are stored in an Actor instance,
to which the channels that a thread wants to wait on are associated.
Typically, the way this is used is to subclass Actor to implement the
required functionality for a single thread, and wrap this subclass in
ActorThread to actually run them.
Subclasses of Actor should accept the channels that they will write to
as constructor arguments (since they will be associated with other actors), and
should create and expose the channels which they will receive from (for the
opposite reason).
For example, this class receives integers on one channel (ping), and sends them on another (pong):
class PingPong : public Actor {
public:
PingPong(Channel<int> pong) : ping(*this), do_exit(*this), pong(pong) {}
Channel<int> ping;
protected:
void run() {
while (true) {
switch (wait(ping, do_exit)) {
case 0:
pong.push(ping.pop());
break;
case 1:
if (do_exit.pop())
return;
break;
}
}
}
void exit() { do_exit.push(true); }
private:
Channel<bool> do_exit;
Channel<int> pong;
};
using PingPongThread = ActorThread<PingPong>;
Note how:
pong is passed into the constructor, so it can be associated with another actor
ping and do_exit are associated with this, and are externally accessible
run waits on both ping and do_exit, which may be pushed to from different threads
For simplicity and portability, actorpp doesn’t implement any fancy concurrency model – it just uses plain threads, so is not suitable for any uses that can’t cope with the overhead of one thread per actor.
It really exists to formalise the kind of concurrency which works well and is scalable (in terms of mental/testing overhead) for non-high-performance systems.
This was built as part of the ESHET home automation system; it’s what all concurrency in eshetcpp is implemented with.
The core of actorpp only uses standard C++11 constructs, so should be very portable, while the networking library just uses UNIX sockets. It is regularly used on x86 linux, and ESP32 with freertos.
actorpp is hosted on github at https://github.com/tomjnixon/actorpp.