3 #ifndef CDSLIB_SYNC_MONITOR_H
4 #define CDSLIB_SYNC_MONITOR_H
6 #include <cds/details/defs.h>
8 namespace cds { namespace sync {
11 @page cds_sync_monitor Synchronization monitor
13 A <a href="http://en.wikipedia.org/wiki/Monitor_%28synchronization%29">monitor</a> is synchronization construct
14 that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true.
16 Some blocking data structure algoritms like the trees require per-node locking.
17 For huge trees containing millions of nodes it can be very inefficient to inject
18 the lock object into each node. Moreover, some operating systems may not support
19 the millions of system objects like mutexes per user process.
20 The monitor strategy is intended to solve that problem.
21 When the node should be locked, the monitor is called to allocate appropriate
22 lock object for the node if needed, and to lock the node.
23 The monitor strategy can significantly reduce the number of system objects
24 required for data structure.
28 \p libcds contains several monitor implementations:
29 - \p sync::injecting_monitor injects the lock object into each node.
30 That mock monitor is designed for user-space locking primitive like
31 \ref sync::spin_lock "spin-lock".
32 - \p sync::pool_monitor is the monitor that allocates the lock object
33 for the node from the pool when needed. When the node is unlocked
34 the lock assigned to it is given back to the pool if no thread
35 references to that node.
39 If you use a container from \p libcds that requires a monitor, you should just
40 specify required monitor type in container's traits. Usually, the monitor
41 is specified by \p traits::sync_monitor typedef, or by \p cds::opt::sync_monitor
42 option for container's \p make_traits metafunction.
44 If you're developing a new container algorithm, you should know internal monitor
49 // Monitor's injection into the Node class
50 template <typename Node>
51 struct node_injection: public Node
53 // Monitor data to inject into container's node
58 template <typename Node>
59 void lock( Node& node );
62 template <typename Node>
63 void unlock( Node& node );
65 // Scoped lock applyes RAII to Monitor
66 template <typename Node>
67 using scoped_lock = monitor_scoped_lock< pool_monitor, Node >;
71 Monitor's data should be inject into container's node as \p m_SyncMonitorInjection data member:
73 template <typename SyncMonitor>
76 typename SyncMonitor::node_injection m_SyncMonitorInjection;
80 The monitor should be a member of your container:
82 template <typename GC, typename T, typename Traits>
85 typedef typename Traits::sync_monitor sync_monitor;
86 typedef my_node<sync_monitor> node_type;
87 sync_monitor m_Monitor;
94 /// Monitor scoped lock (RAII)
97 - \p Monitor - monitor type
100 template <typename Monitor, typename Node>
101 struct monitor_scoped_lock
104 typedef Monitor monitor_type; ///< Monitor type
105 typedef Node node_type; ///< Node type
109 monitor_type& m_Monitor; ///< Monitor
110 node_type const& m_Node; ///< Our locked node
114 /// Makes exclusive access to the node \p p by \p monitor
115 monitor_scoped_lock( monitor_type& monitor, node_type const& p )
116 : m_Monitor( monitor )
123 ~monitor_scoped_lock()
125 m_Monitor.unlock( m_Node );
129 }} // namespace cds::sync
131 #endif // #ifndef CDSLIB_SYNC_MONITOR_H