User Manual |
To compile libcppa, you will need CMake and a C++11 compiler. To get and compile the sources, open a terminal (on Linux or Mac OS X) and type:
git clone git://github.com/Neverlord/libcppa.git cd libcppa ./configure make make install [as root, optional]
It is recommended to run the unit tests as well:
make test
Please submit a bug report that includes (a) your compiler version, (b) your OS, and (c) the content of the file build/Testing/Temporary/LastTest.log if an error occurs.
The message passing implementation of libcppa uses tuples with call-by-value semantic. Hence, it is not necessary to declare message types, though, libcppa allows users to use user-defined types in messages (see Section 12.1). A call-by-value semantic would cause multiple copies of a tuple if it is send to multiple actors. To avoid unnecessary copying overhead, libcppa uses a copy-on-write tuple implementation. A tuple is implicitly shared between any number of actors, as long as all actors demand only read access. Whenever an actor demands write access, it has to copy the data first if more than one reference to it exists. Thus, race conditions cannot occur and each tuple is copied only if necessary.
The interface of cow_tuple strictly distinguishes between const and non-const access.
The template function get returns an element as immutable value, while get_ref explicitly returns a mutable reference to the required value and detaches the tuple if needed.
We do not provide a const overload for get, because this would cause to unintended, and thus unnecessary, copying overhead.
The class any_tuple represents a tuple without static type information.
All messages send between actors use this tuple type.
The type information can be either explicitly accessed for each element or the original tuple, or a subtuple of it, can be restored using tuple_cast.
Users of libcppa usually do not need to know about
any_tuple, since it is used “behind the scenes”.
However, any_tuple can be created from a cow_tuple
or by using make_any_tuple, as shown below.
The function tuple_cast restores static type information
from an any_tuple object.
It returns an option (see Section 15.1)
for a cow_tuple of the requested types.
The function tuple_cast can be used with wildcards (see Section 3.4) to create a view to a subset of the original data.
No elements are copied, unless the tuple becomes detached.
C++ does not provide pattern matching facilities. A general pattern matching solution for arbitrary data structures would require a language extension. Hence, we decided to restrict our implementation to tuples, to be able to use an internal domain-specific language approach.
A match expression begins with a call to the function on, which returns an intermediate object providing the member function when and operator>>.
The right-hand side of the operator denotes a callback, usually a lambda expression, that should be invoked if a tuple matches the types given to on,
as shown in the example below.
The result of operator>> is a match statement.
A partial function can consist of any number of match statements.
At most one callback is invoked, since the evaluation stops at the first match.
The function “on” can be used in two ways.
Either with template parameters only or with function parameters only.
The latter version deduces all types from its arguments and matches for both type and value.
To match for any value of a given type, “val” can be used, as shown in the following example.
Note: The given callback can have less arguments than the pattern. But it is only allowed to skip arguments from left to right.
arg_match” and “on_arg_match”Our previous examples always used the most verbose form, which is quite redundant, since you have to type the types twice – as template parameter and as argument type for the lambda.
To avoid such redundancy, arg_match can be used as last argument to the function on.
This causes the compiler to deduce all further types from the signature of the given callback.
Note that the second version does call on without template parameters.
Furthermore, arg_match must be passed as last parameter.
If all types should be deduced from the callback signature, on_arg_match can be used.
It is equal to on(arg_match).
Assume an actor provides a mathematical service for integers.
It takes two arguments, performs a predefined operation and returns the result.
It cannot determine an operation, such as multiply or add, by receiving two operands.
Thus, the operation must be encoded into the message.
The Erlang programming language introduced an approach to use non-numerical
constants, so-called atoms, which have an unambiguous, special-purpose type and do not have the runtime overhead of string constants.
Atoms are mapped to integer values at compile time in libcppa.
This mapping is guaranteed to be collision-free and invertible, but limits atom literals to ten characters and prohibits special characters.
Legal characters are “_0-9A-Za-z” and the whitespace character.
Atoms are created using the constexpr function atom, as the following example illustrates.
Note: The compiler cannot enforce the restrictions at compile time, except for a length check.
The assertion atom("!?") != atom("?!") is not true, because each invalid character is mapped to the whitespace character.
The type anything can be used as wildcard to match any number of any types.
A pattern created by on<anything>() or its alias others() is useful to define a default case.
For patterns defined without template parameters, the constexpr value any_vals can be used as function argument.
The constant any_vals is of type anything and is nothing but syntactic sugar for defining patterns.
Guards can be used to constrain a given match statement by using placeholders, as the following example illustrates.
Guard expressions are a lazy evaluation technique.
The placeholder _x1 is substituted with the first value of a given tuple.
All binary comparison and arithmetic operators are supported, as well as && and ||.
In addition, there are three functions designed to be used in guard expressions: gref (“guard reference”), gval (“guard value”), and gcall (“guard function call”).
The function gref creates a reference wrapper, while gval encloses a value.
It is similar to std::ref but it is always const and “lazy”.
A few examples to illustrate some pitfalls:
Statement (5) is evaluated immediately and returns a boolean, whereas statement (4) creates a valid guard expression.
Thus, you should always use gref instead of std::ref to avoid errors.
The second function, gcall, encapsulates a function call.
Its usage is similar to std::bind, but there is also a short version for unary functions: gcall(fun, _x1) is equal to _x1(fun).
Member functions (x represents the value at runtime, y represents an iterable container) | |
size() | Returns x.size() |
empty() | Returns x.empty() |
not_empty() | Returns !x.empty() |
front() | Returns an option (see Section 15.1) to x.front() |
in(y) | Returns true if y contains x, false otherwise |
not_in(y) | Returns !in(y) |
Projections perform type conversions or extract data from a given input. If a callback expects an integer but the received message contains a string, a projection can be used to perform a type conversion on-the-fly. This conversion should be free of side-effects and, in particular, shall not throw exceptions, because a failed projection is not an error. A pattern simply does not match if a projection failed. Let us have a look at a simple example.
The lambda intproj is a string ⇒ int projection, but note that it does not return an integer.
It returns option<int>, because the projection is not guaranteed to always succeed.
An empty option indicates, that a value does not have a valid mapping to an integer.
A pattern does not match if a projection failed.
Note: Functors used as projection must take exactly one argument and must return a value.
The types for the pattern are deduced from the functor’s signature.
If the functor returns an option<T>, then T is deduced.
libcppa provides several actor implementations, each covering a particular use case.
The class local_actor is the base class for all implementations, except for (remote) proxy actors.
Hence, local_actor provides a common interface for actor operations like trapping exit messages or finishing execution.
The default actor implementation in libcppa is event-based.
Event-based actors have a very small memory footprint and are thus very lightweight and scalable.
Context-switching actors are used for actors that make use of the blocking API (see Section 13), but do not need to run in a separate thread.
Context-switching and event-based actors are scheduled cooperatively in a thread pool.
Thread-mapped actors can be used to opt-out of this cooperative scheduling.
The self pointer is an essential ingredient of our design.
It identifies the running actor similar to the implicit this pointer identifying an object within a member function.
Unlike this, though, self is not limited to a particular scope.
The self pointer is used implicitly, whenever an actor calls functions like send or become, but can be accessed to use more advanced actor operations such as linking to another actor, e.g., by calling self->link_to(other).
The self pointer is convertible to actor_ptr and local_actor*, but it is neither copyable nor assignable.
Thus, auto s = self will cause a compiler error, while actor_ptr s = self works as expected.
A thread that accesses self is converted on-the-fly to an actor if needed.
Hence, “everything is an actor” in libcppa.
However, automatically converted actors use an implementation based on the blocking API, which behaves slightly different than the default, i.e., event-based, implementation.
| Member functions | |
quit(uint32_t reason = normal) | Finishes execution of this actor |
| Observers | |
bool trap_exit() | Checks whether this actor traps exit messages |
bool chaining() | Checks whether this actor uses the “chained send” optimization (see Section 5.2) |
any_tuple last_dequeued() | Returns the last message that was dequeued from the actor’s mailbox Note: Only set during callback invocation |
actor_ptr last_sender() | Returns the sender of the last dequeued message Note1: Only set during callback invocation Note2: Used by the function reply (see Section 5.1) |
vector<group_ptr> joined_groups() | Returns all subscribed groups |
| Modifiers | |
void trap_exit(bool enabled) | Enables or disables trapping of exit messages |
void chaining(bool enabled) | Enables or disables chained send |
void join(const group_ptr& g) | Subscribes to group g |
void leave(const group_ptr& g) | Unsubscribes group g |
auto make_response_handle() | Creates a handle that can be used to respond to the last received message later on, e.g., after receiving another message |
void on_sync_failure(auto fun) | Sets a handler, i.e., a functor taking no arguments, for unexpected synchronous response messages (default action is to kill the actor for reason unhandled_sync_failure) |
void on_sync_timeout(auto fun) | Sets a handler, i.e., a functor taking no arguments, for timed_sync_send timeout messages (default action is to kill the actor for reason unhandled_sync_timeout) |
void monitor(actor_ptr whom) | Adds a unidirectional monitor to whom (see Section 8.2) |
void demonitor(actor_ptr whom) | Removes a monitor from whom |
void exec_behavior_stack() | Executes an actor’s behavior stack until it is empty |
bool has_sync_failure_handler() | Checks wheter this actor has a user-defined sync failure handler |
Messages can be sent by using send, send_tuple, or operator<<. The variadic template function send has the following signature.
The variadic template pack what... is converted to a dynamically typed tuple (see Section 2.1) and then enqueued to the mailbox of whom.
The following example shows two equal sends, one using send and the other using operator<<.
Using the function send is more compact, but does not have any other benefit.
However, note that you should not use send if you already have an instance of any_tuple, because it creates a new tuple containing the old one.
The function send_tuple is equal to operator<<.
Choosing one or the other is merely a matter of personal preferences.
During callback invokation, self->last_sender() is set.
This identifies the sender of the received message and is used implicitly by the functions reply and reply_tuple.
Using reply(...) is not equal to send(self->last_sender(), ...).
The function send always uses asynchronous message passing, whereas reply will send a synchronous response message if the received message was a synchronous request (see Section 7).
To delay a response, i.e., reply to a message after receiving another message, actors can use self->make_response_handle().
The functions reply_to and reply_tuple_to then can be used to reply the the original request, as shown in the example below.
In any case, do never reply than more than once. Additional (synchronous) response message will be ignored by the receiver.
Sending a message to a cooperatively scheduled actor usually causes the receiving actor to be put into the scheduler’s job queue if it is currently blocked, i.e., is waiting for a new message. This job queue is accessed by worker threads. The chaining optimization does not cause the receiver to be put into the scheduler’s job queue if it is currently blocked. The receiver is stored as successor of the currently running actor instead. Hence, the active worker thread does not need to access the job queue, which significantly speeds up execution. However, this optimization can be inefficient if an actor first sends a message and then starts computation.
The example above illustrates an inefficient work flow.
The actor other is marked as successor of the foo actor but its execution is delayed until very_long_computation() is done.
In general, actors should follow the work flow receive ⇒compute ⇒ send results.
However, this optimization can be disabled by calling self->chaining(false) if an actor does not match this work flow.
Messages can be delayed, e.g., to implement time-based polling strategies, by using one of delayed_send, delayed_send_tuple, delayed_reply, or delayed_reply_tuple.
The following example illustrates a polling strategy using delayed_send.
The function forward_to forwards the last dequeued message to an other actor.
Forwarding a synchronous message will also transfer responsibility for the request, i.e., the receiver of the forwarded message can reply as usual and the original sender of the message will receive the response.
The following diagram illustrates forwarding of a synchronous message from actor B to actor C.
A B C
| | |
| --(sync_send)--> | |
| | --(forward_to)-> |
| X |---\
| | | compute
| | | result
| |<--/
| <-------------(reply)-------------- |
| X
|---\
| | handle
| | response
|<--/
|
X
The forwarding is completely transparent to actor C, since it will see actor A as sender of the message.
However, actor A will see actor C as sender of the response message instead of actor B and thus could recognize the forwarding by evaluating self->last_sender().
The current behavior of an actor is its response to the next incoming message and includes (a) sending messages to other actors, (b) creation of more actors, and (c) setting a new behavior.
An event-based actor, i.e., the default implementation in libcppa, uses become to set its behavior.
The given behavior is then executed until it is replaced by another call to become or the actor finishes execution.
A class-based actor is a subtype of event_based_actor and must implement the pure virtual member function init.
An implementation of init shall set an initial behavior by using become.
Another way to implement class-based actors is provided by the class sb_actor (“State-Based Actor”).
This base class calls become(init_state) in its init member function.
Hence, a subclass must only provide a member of type behavior named init_state.
Note that sb_actor uses the Curiously Recurring Template Pattern. Thus, the derived class must be given as template parameter.
This technique allows sb_actor to access the init_state member of a derived class.
The following example illustrates a more advanced state-based actor that implements a stack with a fixed maximum number of elements. Note that this example uses non-static member initialization and thus might not compile with some compilers.
become/unbecomeSince become does not block, an actor has to manipulate its behavior stack to achieve nested receive operations.
An actor can set a new behavior by calling become with the keep_behavior policy to be able to return to its previous behavior later on by calling unbecome, as shown in the example below.
An event-based actor finishes execution with normal exit reason if the behavior stack is empty after calling unbecome.
The default policy of become is discard_behavior that causes an actor to override its current behavior.
The policy flag must be the first argument of become.
Note: the message handling in libcppa is consistent among all actor implementations: unmatched messages are never implicitly discarded if no suitable handler was found. Hence, the order of arrival is not important in the example above. This is unlike other event-based implementations of the actor model such as Akka for instance.
A behavior set by become is invoked whenever a new messages arrives.
If no message ever arrives, the actor would wait forever.
This might be desirable if the actor only provides a service and should not do anything else.
But often, we need to be able to recover if an expected messages does not arrive within a certain time period. The following examples illustrates the usage of after to define a timeout.
Callbacks given as timeout handler must have zero arguments.
Any number of patterns can precede the timeout definition, but “after” must always be the final statement.
Using a zero-duration timeout causes the actor to scan its mailbox once and then invoke the timeout immediately if no matching message was found.
libcppa supports timeouts using minutes, seconds, milliseconds and microseconds.
However, note that the precision depends on the operating system and your local work load.
Thus, you should not depend on a certain clock resolution.
Unmatched messages are skipped automatically by libcppa’s runtime system.
This is true for all actor implementations.
To allow actors to skip messages manually, skip_message can be used.
This is in particular useful whenever an actor switches between behaviors, but wants to use a default rule created by others() to filter messages that are not handled by any of its behaviors.
The following example illustrates a simple server actor that dispatches requests to workers.
After receiving an message, it awaits a request that is then forwarded to the idle worker.
Afterwards, the server returns to its initial behavior, i.e., awaits the next 'idle' message.
The server actor will exit for reason 'idle'user_defined whenever it receives a message that is neither a request, nor an idle message.
libcppa uses a future-based API for synchronous communication.
The functions sync_send and sync_send_tuple send synchronous request messages to the receiver and return a future to the response message.
Note that the returned future is actor-local, i.e., only the actor that has send the corresponding request message is able to receive the response identified by such a future.
A synchronous message is sent to the receiving actor’s mailbox like any other asynchronous message. The response message, on the other hand, is treated separately.
The difference between sync_send and timed_sync_send is how timeouts are handled.
The behavior of sync_send is analogous to send, i.e., timeouts are specified by using after(...) statements (see 6.3).
When using timed_sync_send function, after(...) statements are ignored and the actor will receive a message after the given duration instead.'TIMEOUT'
When using synchronous messaging, libcppa’s runtime environment will send ...
{'EXITED', uint32_t exit_reason} if the receiver is not alive
{'VOID'} if the receiver handled the message but did not call reply
{'TIMEOUT'} if a message send by timed_sync_send timed out
The function handle_response can be used to set a one-shot handler receiving the response message send by sync_send.
Similar to become, the function handle_response modifies an actor’s behavior stack.
However, it is used as “one-shot handler” and automatically returns the previous actor behavior afterwards.
It is possible to “stack” multiple handle_response calls.
Each response handler is executed once and then automatically discarded.
An unexpected response message, i.e., a message that is not handled by given behavior, will invoke the actor’s on_sync_failure handler.
The default handler kills the actor by calling self->quit(exit_reason::unhandled_sync_failure).
The handler can be overridden by calling self->on_sync_failure(/*...*/).
Unhandled messages trigger the 'TIMEOUT'on_sync_timeout handler.
The default handler kills the actor for reason exit_reason::unhandled_sync_failure.
It is possible set both error handlers by calling self->on_sync_timeout_or_failure(./*...*)
then to Receive a ResponseOften, an actor sends a synchronous message and then wants to wait for the response.
In this case, using either handle_response is quite verbose.
To allow for a more compact code, message_future provides the member function then.
Using this member function is equal to using handle_response, as illustrated by the following example.
To reduce verbosity, libcppa supports synchronous response handlers without patterns. In this case, the pattern is automatically deduced by the functor’s signature.
libcppa supports continuations to enable chaining of send/receive statements.
The functions handle_response and message_future::then both return a helper object offering continue_with, which takes a functor f without arguments.
After receiving a message, f is invoked if and only if the received messages was handled successfully, i.e., neither sync_failure nor sync_timeout occurred.
libcppa adapts Erlang’s well-established fault propagation model. It allows to build actor subsystem in which either all actors are alive or have collectively failed.
Linked actors monitor each other. An actor sends an exit message to all of its links as part of its termination. The default behavior for actors receiving such an exit message is to die for the same reason, if the exit reason is non-normal. Actors can trap exit messages to handle them manually.
A monitor observes the lifetime of an actor.
Monitored actors send a down message to all observers as part of their termination.
Unlike exit messages, down messages are always treated like any other ordinary message.
An actor will receive one down message for each time it called self->monitor(...), even if it adds a monitor to the same actor multiple times.
All error codes are defined in the namespace cppa::exit_reason.
To obtain a string representation of an error code, use cppa::exit_reason::as_string(uint32_t).
normal | 1 | Actor finished execution without error |
unhandled_exception | 2 | Actor was killed due to an unhandled exception |
unallowed_function_call | 3 | Indicates that an event-based actor tried to use blocking receive calls |
unhandled_sync_failure | 4 | Actor was killed due to an unexpected synchronous response message |
unhandled_sync_timeout | 5 | Actor was killed, because no timeout handler was set and a synchronous message timed out |
remote_link_unreachable | 257 | Indicates that a remote actor became unreachable, e.g., due to connection error |
user_defined | 65536 | Minimum value for user-defined exit codes |
Actors can attach cleanup code to other actors.
This code is executed immediately if the actor has already exited.
Keep in mind that self refers to the currently running actor.
Thus, self refers to the terminating actor and not to the actor that attached a functor to it.
Note: It is possible to attach code to remote actors, but the cleanup code will run on the local machine.
Actors are created using the function spawn.
The easiest way to implement actors is to use functors, e.g., a free function or lambda expression.
The arguments to the functor are passed to spawn as additional arguments.
The function spawn also takes optional flags as template paremeter.
The flag detached causes spawn to create a thread-mapped actor (opt-out of the cooperative scheduling), the flag linked links the newly created actor to its parent, and the flag monitored automatically adds a monitor to the new actor.
Actors that make use of the blocking API (see Section 13) must be spawned using the flag blocking_api.
Flags are concatenated using the operator +, as shown in the examples below.
Note: spawn(fun, arg0, ...) is not the same as spawn(std::bind(fun, arg0, ...))!
For example, a call to spawn(fun, self, ...) will pass a pointer to the calling actor to the newly created actor, as expected, whereas spawn(std::bind(fun, self, ...)) wraps the type of self into the function wrapper and evaluates self on function invocation.
Thus, the actor will end up having a pointer to itself rather than a pointer to its parent.
All actor operations as well as sending messages are network transparent. Remote actors are represented by actor proxies that forward all messages.
The function publish binds an actor to a given port.
It throws network_error if socket related errors occur or bind_failure if the specified port is already in use.
The optional addr parameter can be used to listen only to the given IP address.
Otherwise, the actor accepts all incoming connections (INADDR_ANY).
The function remote_actor connects to the actor at given host and port.
A network_error is thrown if the connection failed.
libcppa supports publish/subscribe-based group communication. Actors can join and leave groups and send messages to groups.
Groups created on-the-fly with group::anonymous() can be used to coordinate a set of workers.
Each call to group::anonymous() returns a new, unique group instance.
The group module creates groups for in-process communication.
For example, a group for GUI related events could be identified by "local"group::get("local", "GUI events").
The group ID uniquely identifies a singleton group instance of the module "GUI events"."local"
The function spawn_in_group can be used to create actors as members of a group.
The function causes the newly created actors to call self->join(...) immediately and before spawn_in_group returns.
The usage of spawn_in_group is equal to spawn, except for an additional group argument.
The group handle is always the first argument, as shown in the examples below.
libcppa provides a fully network transparent communication between actors.
Thus, libcppa needs to serialize and deserialize messages.
Unfortunately, this is not possible using the RTTI system of C++.
libcppa uses its own RTTI based on the class uniform_type_info, since it is not possible to extend std::type_info.
Unlike std::type_info::name(), uniform_type_info::name() is guaranteed to return the same name on all supported platforms. Furthermore, it allows to create an instance of a type by name.
However, you should rarely if ever need to use object or uniform_type_info.
All user-defined types must be explicitly “announced” so that libcppa can (de)serialize them correctly, as shown in the example below.
Without the announce function call, the example program would terminate with an exception, because libcppa rejects all types without available runtime type information.
announce() takes the class as template parameter and pointers to all members (or getter/setter pairs) as arguments.
This works for all primitive data types and STL compliant containers.
See the announce examples 1 – 4 of the standard distribution for more details.
Obviously, there are limitations.
You have to implement serialize/deserialize by yourself if your class does implement an unsupported data structure.
See announce_example_5.cpp in the examples folder.
Besides event-based actors (the default implementation), libcppa also provides context-switching and thread-mapped actors that can make use of the blocking API. Those actor implementations are intended to ease migration of existing applications or to implement actors that need to have access to blocking receive primitives for other reasons.
Event-based actors differ in receiving messages from context-switching and thread-mapped actors: the former define their behavior as a message handler that is invoked whenever a new messages arrives in the actor’s mailbox (by using become), whereas the latter use an explicit, blocking receive function.
The function receive sequentially iterates over all elements in the mailbox beginning with the first.
It takes a partial function that is applied to the elements in the mailbox until an element was matched by the partial function.
An actor calling receive is blocked until it successfully dequeued a message from its mailbox or an optional timeout occurs.
The code snippet above illustrates the use of receive.
Note that the partial function passed to receive is a temporary object at runtime.
Hence, using receive inside a loop would cause creation of a new partial function on each iteration.
libcppa provides three predefined receive loops to provide a more efficient but yet convenient way of defining receive loops.
| |
for (;;) {
receive (
// ...
);
} | receive_loop (
// ...
); |
std::vector<int> results;
for (size_t i = 0; i < 10; ++i) {
receive (
on<int>() >> [&](int value) {
results.push_back(value);
}
);
} | std::vector<int> results;
size_t i = 0;
receive_for(i, 10) (
on<int>() >> [&](int value) {
results.push_back(value);
}
); |
size_t received = 0;
do {
receive (
others() >> [&]() {
++received;
}
);
} while (received < 10); | size_t received = 0;
do_receive (
others() >> [&]() {
++received;
}
).until(gref(received) >= 10); |
The examples above illustrate the correct usage of the three loops receive_loop, receive_for and do_receive(...).until.
It is possible to nest receives and receive loops.
become and handle_response do not block, i.e., always return immediately.
Thus, you should always capture by value in event-based actors, because all references on the stack will cause undefined behavior if a lambda is executed.
receive will throw an exception if accessed from an event-based actor.
become API.
Whenever a non-event-based actor calls become() for the first time, it will create a behavior stack and execute it until the behavior stack is empty.
Thus, the initial become blocks until the behavior stack is empty, whereas all subsequent calls to become will return immediately.
Related functions, e.g., sync_send(...).then(...), behave the same, as they manipulate the behavior stack as well.
send(self->last_sender(), ...) is not equal to reply(...).
The two functions receive_response and handle_response will only recognize messages send via either reply or reply_tuple.sync_send represents exactly one response message.
Therefore, it is not possible to receive more than one response message.
Calling reply more than once will result in lost messages and calling handle_response or receive_response more than once on a future will throw an exception.sync_send is bound to the calling actor.
It is not possible to transfer such a future to another actor.
Calling receive_response or handle_response for a future bound to another actor is undefined behavior.send(whom, ...) is syntactic sugar for whom << make_any_tuple(...).
Hence, a message sent via send(whom, self->last_dequeued()) will not yield the expected result, since it wraps self->last_dequeued() into another any_tuple instance.
The correct way of forwarding messages is self->forward_to(whom).std::shared_ptr.
Nevertheless, the recommended way of sharing informations is message passing.
Sending data to multiple actors does not result in copying the data several times.
Read Section 2 to learn more about libcppa’s copy-on-write optimization for tuples.
self does not point to this. It points to the invoking actor instead.
Defined in header ."cppa/option.hpp"
Represents an optional value.
| Member types | |
| Member type | Definition |
type | T |
| Member functions | |
option() | Constructs an empty option |
option(T value) | Initializes this with value |
option(const option&)option(option&&) | Copy/move construction |
option& operator=(const option&)option& operator=(option&&) | Copy/move assignment |
| Observers | |
bool valid()explicit operator bool() | Returns true if this has a value |
bool empty()bool operator!() | Returns true if this does not has a value |
const T& get()const T& operator*() | Access stored value |
const T& get_or_else(const T& x) | Returns get() if valid, x otherwise |
| Modifiers | |
T& get()T& operator*() | Access stored value |
When using cout from multiple actors, output often appears interleaved.
Moreover, using cout from multiple actors – and thus multiple threads – in parallel should be avoided, since the standard does not guarantee a thread-safe implementation.
By replacing std::cout with cppa::aout, actors can achieve a concurrency-safe text output.
The header cppa/cppa.hpp also defines overloads for std::endl and std::flush for aout, but does not support the full range of ostream operations (yet).
Each write operation to aout sends a message to a ‘hidden’ actor (keep in mind, sending messages from actor constructors is not safe).
This actor only prints lines, unless output is forced using flush.
This document was translated from LATEX by HEVEA.