SObjectizer
5.7
|
A new feature was introduced in v.5.5.8 – agent’s priorities. Every agent now has a priority. Priority is just an optional mark for dispatchers. Some dispatcher can use this mark for priority-specific events scheduling, some dispatcher can’t.
Several new dispatchers with support for agent’s priorities were added in v.5.5.8. They will be described below.
Agent’s priority is represented as enumeration so_5::priority_t
. There are only 8 priorities: from the lowest (so_5::priority_t::p0) to the highest (so_5::priority_t::p7).
A priority for an agent can be specified during agent’s construction.
Once agent has been constructed the priority cannot be changed.
There is a namespace so_5::prio with some useful helper constants and functions. For example instead of writing so_5::priority_t::p3 it is possible to write so_5::prio::p3. Or even p3 under using namespace so_5::prio
construct.
Version 5.5.8 adds three new dispatchers which support agent’s priorities: prio_one_thread::strictly_ordered, prio_one_thread::quote_round_robin, prio_dedicated_threads::one_per_prio. They do priority-specific handling of agent’s events.
Old dispatchers from previous versions (one_thread, active_obj, active_group, thread_pool, adv_thread_pool) do not support priorities.
There is a principal difference in event handling with respect to agent’s priorities: will all events for agents with different priorities be handled on the same working thread or events with different priorities will be handled on its own, dedicated threads.
Handling of events with different priorities on the context of common working threads allows to do several important things. At first, there is a possibility to strict ordering of events with respect to priorities. It means that event with higher priority will block events with lower priority. At second there is a possibility for easy sharing some data between agents with different priorities. Because all agents will work on the same thread there is no need for synchronize access to shared data.
Those things are impossible when events with different priorities are handled on different threads.
Because of that new dispatchers with priorities support are grouped into two group: prio_one_thread (it means that all events are processed on the same working thread) and prio_dedicated_thread (it means that events will different priorities will be processed on different threads).
Group prio_one_thread consists of two dispatchers: strictly_ordered and quoted_round_robin.
Working Principles
This dispatcher allows for events of high priority agents to block events of low priority agents. It means that events queue is always strictly ordered: events for agents with high priority are placed before events for agents with lower priority.
For example if event queue is (e1(a7),e2(a6),e3(a4),e4(a4)), where a7 means an agent with priority p7, then events will be handled in exact that order. After handling e1 the queue will be (e2(a6),e3(a4),e4(a4)). If e5 for a5 arrived then the queue will become (e2(a6),e5(a5),e3(a4),e4(a4)).
It means that chronological order of events will be preserved only for events of agents with the same priority.
This dispatcher could be useful if there is a necessity of handling some messages before other messages. For example there could be a stream of tasks represented by take_job messages. There also could be a special message for task processor’s reconfiguration: new_config message. It could have a sense to handle new_config as soon as possible.
This can be done by two agents which are bound to single prio_one_thread::strictly_ordered dispatcher. One agent will have priority p1 and will handle new_config message. Second agent will have priority p0 and will handle take_job. Both agents will have common shared data (at least configuration parameters, may be something else). Dispatcher prio_one_thread::strictly_ordered guarantees that new_config will be handled as soon as processing of previous message finished.
Synopsis
The dispatcher is defined in so_5::disp::prio_one_thread::strictly_ordered namespace. There are several traditional functions for dispatcher creation.
Function create_disp creates public dispatcher which should be added to list of named dispatchers:
There is also create_private_disp function for creation of private instance of dispatcher:
Working Principles
Dispatcher prio_one_thread::quoted_round_robin works on round-robin principle. It allows to specify maximum count of events to be processed consequently for the specified priority. After processing that count of events dispatcher switches to processing events of lower priority even if there are yet more events of higher priority to be processed.
Dispatcher uses very simply working scheme: it handles no more than Q7 events of priority p7, then no more than Q6 events of priority p6, ..., then no more than Q0 events of priority p0. If an event of higher priority is arrived during handling a quote for lower priority no switching is performed. For example if dispatcher handles events of priority p5 and event of priority p7 is arrived the dispatcher will continue to handle events of priority p5, then events of priority p4 (if any), ..., then events of priority p0 (if any). And only then the dispatcher will start to process events of priority p7.
Events inside the same priority are handled in chronological order.
This working scheme means that agent’s priorities treated as agent’s weight. A programmer can set bigger quotes for more prioritized (more heavyweight) agents and that agents will receive more resources than less prioritized (less weighted) agents.
A dispatcher of that type can be useful, for example, if there are agents which handles clients of different types. Some clients are VIP clients and they should receive first-class quality of service and there could be other clients with lower demands for service quality. It is possible to assign a high priority to agents for handling VIP-client requests and specify large quote for that priority. All other agents will have lower priority and smaller quote. As result more requests from VIP-clients will be handled but there also will be processing of request from other clients.
Synopsis
The dispatcher is defined in so_5::disp::prio_one_thread::quoted_round_robin namespace. There are several traditional functions for dispatcher creation.
Quotes for priorities must be defined before creation of a dispatcher. It can be done via constructing and tuning of object of type so_5::disp::prio_one_thread::quoted_round_robin::quotes_t. For example:
Construction of quotes_t object can be done during calling a function for dispatcher creation:
Function create_disp creates public dispatcher which should be added to list of named dispatchers:
There is also create_private_disp function for creation of private instance of dispatcher:
Working Principles
This dispatcher creates a single dedicated thread for every priority. It means that events for agents with priority p7 will be handled on different thread than events for agents with, for example, priority p6.
Events inside the same priority are handled in chronological order.
Priority is assigned to an agent, not to a particular events. It means that all events of one agent have the same priority. Because of that all events of that agent will be handled on the same thread. In other words an agent is bound to its working thread once and do not moved from one thread to another.
This working scheme means that agent’s priority is treated as binding to a particular working thread inside a dispatcher instance. It allows to bound agents with different requirements to different working threads.
Synopsis
The dispatcher is defined in so_5::disp::prio_dedicated_threads::one_per_prio namespace. There are several traditional functions for dispatcher creation.
Function create_disp creates public dispatcher which should be added to list of named dispatchers:
There is also create_private_disp function for creation of private instance of dispatcher: