Use of custom rwlock instead of ACE_RW_Thread_Mutex.
Use some kind of lock-free data structures for storing subscriptions dictionaries. NOTE. Delayed for the future versions of SObjectizer (may be SO-5.5?).
Standard samples for SO-5 must be reviewed. A usage of agent_t::so_direct_mbox() must be implemented where appropriate. DONE
There must be a description of mpsc_mbox-es (in SF Wiki, in Doxygen).
There is a new benchmark test/so_5/bench/parallel_send_to_same_mbox which shows that some kind of shared mutex is very important to efficiency of parallel sending to the same mbox from several threads. DONE Spinlocks are used now.
It is very inefficient to create many ACE_RW_Thread_Mutex instances in the application (the performance is degraded significally). And there is no standard alternative to ACE_RW_Thread_Mutex yet. For more detail see this post in Russian. DONE Very efficient and lightweight spinlocks are used now.
There are two queue: an agent's queue and working thread's queue. It is overkill for simple dispatchers like one_thread, active_obj and active_group.
There must be forms of so_drop_subscription/so_drop_subscription_for_all_states which are supported event handler in the format:
void evt_handler( const MESSAGE & ); void evt_handler(); // Type of signal must be specified as so_5::signal<MSG>
Implemented as so_5::rt::impl::mpsc_mbox_t.
Access to mpsc_mbox_t is only via agent_t::so_direct_mbox() method.
mbox_t::query_name() return name only for named mbox. It creates difficulties to debugging applications with anonymous mboxes. May be it is better to return some value for every type of mbox. For example:
named_mbox.query_name() // "Some name" anon_mbox.query_name() // <mbox:type=MPMC:id=1245> direct_mbox.query_name() // <mbox:type=MPSC:id=1246:consumer:0x837638373648>
But there is a problem: prototype of query_name() method. This method returns const std::string &
and it means that actual mbox name must be stored somewhere.
May be it is better to change prototype of query_name() to:
std::string query_name() const;
Allows to distribute agents between several threads. Every agent works only on a single thread. DONE.
Allows to an agent to work on several threads in parallel. Every event is handled only on a single thread. Synchronization of the agent state is a problem of agent, not dispatcher. DONE. This is adv_thread_pool dispatcher.
All executables must have names which are starting from _test.bench.so_5. DONE.
Create around 100K mboxes or more and subscribe a few agents to every of those mboxes. DONE. This is test/so_5/bench/many_mboxes
, count of mboxes and agents are set via command-line arguments.
Note. This task has the lowest possible priority.
It is only need for one benchmark which is rarely used now. Either this benchmark must be removed or rewritten without cls-3.
DONE Old benchmark work_thread_speed removed.
event_queue_proxy must use default_rw_spinlock_t. DONE.
For state_t object initialization simplification (as shown here). DONE.
For most cases so_environment must be stopped if there is no more cooperations. But now so_environment must be stopped explicitly. It would be better if so_environment can watch on count of live cooperations and automatically stopped when this count is become zero.
DONE. Implemented as autoshutdown feature which is turned on by default (could be turned off by so_environment_params_t::disable_autoshutdown())
A helper method 'so_finish_agent_work' for agent_t which is a shorthand for:
so_environment().deregister_coop( so_coop_name() );
DONE. Implemented as helper methods so_deregister_agent_coop() and so_deregister_agent_coop_normally()
Until v5.4 dispatchers must be registered only before start of the SO Environment. But sometimes it is too strict constrain. It will be useful to have ability to add new dispatcher at the run-time.
For example: it is makes possible to register additional dispatcher for so_sysconf in sysconf-scripts.
DONE. There is a new method so_environment_t::add_dispatcher_if_not_exists.
It is better to change usage of ACE_DEBUG/ACE_ERROR to usage of some abstract interface with possibility to adapt that interface for various logging frameworks.
A new sample which shows user-defined dispatcher. For example it is a dispatcher for one agent. This dispatcher allows to process various types of messages on different threads.
It seems like not very useful feature. Which could confuse user.
Sample of usage:
env.make_coop( "test", []( so_5::rt::agent_coop_t & coop ) { coop.add_agent(...); coop.add_agent(...); coop.define_agent(...); } ); // AUTOMATICALLY REGISTERED HERE!
Postponed to next SObjectizer released.
Reference Big Question: Is it really useful?
It is requires a lot of rewriting in tests/samples without actual profit.
For example, something like this:
#include <so_5/so.hpp> ... int main() { so_5::internals_initializer_t so5_initializer(); ... }
All ACE-related stuff will be hidden somewhere inside internals_initializer_t's constructor.
There is no real projects where this feature will be used right now.