SObjectizer
5.7
|
There is a SObjectizer's key feature: states of an agent. An agent can have several states. It allows to handle the same message in every state differently. For example:
It you send a msg
to an agent of type demo
then this agent will print different messages in the dependence of the current agent's state.
This feature is very useful and it is used extensively in the complex applications. But there is the dark side: if an agent has several states and has to handle some message regardless of the current state then it requires much more work from a developer.
There were two ways for implementation of message handling in every state of an agent:
The first one requires subscription of the same event for every state of the agent. Something like:
Or:
But this approach is boring and it is easy to forget to subscribe the event handler in a new state when this state will be added to agent.
The second approach is more flexible and powerful. It is based on hierarchical state machines. There should be one parent state and several child states. An event handler is subscribed only for the parent state:
This approach will work if an user add or remove child states to agent of type demo
. It also allows to have different event handlers for the same message in different states:
But this approach is not always applicable. For example you can have a base agent class which we can't modify and you have to write a derived class with a default event handler for the some message:
It is possible that the base class doesn't use HSM and don't have the top-level parent state. Or all states of base class can be declared as private attributes and you have no access to it in your derived class.
A new thing was introduced in SObjectizer v.5.5.21: a deadletter handler.
Deadletter handler is a like an ordinary message handler. But it is subscribed and unsubscribed by different methods. And the key moment: deadletter is called only when there is no any other event handlers for a message from a specific mbox.
For example:
This example will print:
It is because there is no more event handlers for second_signal
from agent's direct mbox except the deadletter handler. But if we modify the example such way:
The output will be:
It is because the SObjectizer will find an ordinary handler for second_signal
from agent's direct mbox and will call it. The deadletter handler for second_signal
won't be called because there is an ordinary handler.
In other worlds since v.5.5.21 SObjectizer implements a modified algorithm for searching event handlers for a message/signal. SObjectizer does old-way search for a message handler first with respect to the current agent's state. If an event handler is found it will be called and message processing will be finished. But if an event handler for the current state (and all of its parent states) won't be found then SObjectizer will search for deadletter handler for that message and that mbox. It a deadletter handler will be found it will be called for handling of message.
An API for working with deadletter handlers was introduced in v.5.5.21. Class so_5::agent_t
was extended with the following methods.
This method is intended to be used for subscription of deadletter handler. For example:
A event handler which will be passed to so_subscribe_deadletter_handler
must be a pointer to method of agent's class or lambda-function with one of the following formats:
It means that if a deadletter handler has to handle signals then it should has the following format:
For example:
A message type for a deadletter handler can also be a mutable message. For example:
NOTE. so_subscribe_deadletter_handler
throws if a deadletter handler for a specific message type from a specific mbox is already defined.
This method should be used for unsubscription of deadletter handler. For example:
It is safe to call so_drop_deadletter_handler
for deadletter handler which is already removed. There won't be an exception.
NOTE. A deadletter handler will also be removed by so_drop_subscription_for_all_states
(see the corresponding section below).
This method is intended to be used for checking the presence of a deadletter handler for a specific type of message from a specific mbox. For example:
There are also so_create_deadletter_subscription
and so_destroy_deadletter_subscription
. But they are low-level methods intended to be used by libraries writers. Do not use it directly if you don't understand what they are doing and which arguments they require.
Deadletter handlers are just ordinary message handlers. Because of that they can handle service requests. For example:
A deadletter handler can be removed (unsubscribed) not only by so_drop_deadletter_handler
but also by so_drop_subscription_for_all_states
. It means that in that case: