Formatting issues
[libcds.git] / cds / sync / monitor.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_SYNC_MONITOR_H
4 #define CDSLIB_SYNC_MONITOR_H
5
6 #include <cds/details/defs.h>
7
8 namespace cds { namespace sync {
9     /**
10         @page cds_sync_monitor Synchronization monitor
11         A <a href="http://en.wikipedia.org/wiki/Monitor_%28synchronization%29">monitor</a> is synchronization construct
12         that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true.
13         Some blocking data structure algoritms like the trees require per-node locking.
14         For huge trees containing millions of nodes it can be very inefficient to inject
15         the lock object into each node. Moreover, some operating systems may not support
16         the millions of system objects like mutexes per user process.
17         The monitor strategy is intended to solve that problem.
18         When the node should be locked, the monitor is called to allocate appropriate
19         lock object for the node if needed, and to lock the node.
20         The monitor strategy can significantly reduce the number of system objects
21         required for data structure.
22
23         <b>Implemetations</b>
24
25         \p libcds contains several monitor implementations:
26         - \p sync::injecting_monitor injects the lock object into each node.
27             That mock monitor is designed for user-space locking primitive like
28             \ref sync::spin_lock "spin-lock".
29         - \p sync::pool_monitor is the monitor that allocates a lock object
30             for a node from the pool when needed. When the node is unlocked
31             the lock assigned to it is given back to the pool if no thread
32             references to that node.
33
34         <b>How to use</b>
35
36         If you use a container from \p libcds that requires a monitor, you should just
37         specify required monitor type in container's traits. Usually, the monitor
38         is specified by \p traits::sync_monitor typedef, or by \p cds::opt::sync_monitor
39         option for container's \p make_traits metafunction.
40
41         If you're developing a new container algorithm, you should know internal monitor
42         interface:
43         \code
44         class Monitor {
45         public:
46             // Monitor's injection into the Node class
47             template <typename Node>
48             struct node_injection: public Node
49             {
50                 // Monitor data to inject into container's node
51                 // ...
52             };
53             // Locks the node
54             template <typename Node>
55             void lock( Node& node );
56             // Unlocks the node
57             template <typename Node>
58             void unlock( Node& node );
59             // Scoped lock applyes RAII to Monitor
60             template <typename Node>
61             using scoped_lock = monitor_scoped_lock< pool_monitor, Node >;
62         };
63         \endcode
64         Monitor's data must be inject into container's node as \p m_SyncMonitorInjection data member:
65         \code
66         template <typename SyncMonitor>
67         struct my_node
68         {
69             // ...
70             typename SyncMonitor::node_injection m_SyncMonitorInjection;
71         };
72         \endcode
73         The monitor must be a member of your container:
74         \code
75         template <typename GC, typename T, typename Traits>
76         class my_container {
77             // ...
78             typedef typename Traits::sync_monitor   sync_monitor;
79             typedef my_node<sync_monitor> node_type;
80             sync_monitor m_Monitor;
81             //...
82         };
83         \endcode
84     */
85     /// Monitor scoped lock (RAII)
86     /**
87         Template arguments:
88         - \p Monitor - monitor type
89         - \p Node - node type
90     */
91     template <typename Monitor, typename Node>
92     struct monitor_scoped_lock
93     {
94     public:
95         typedef Monitor monitor_type;   ///< Monitor type
96         typedef Node    node_type;      ///< Node type
97     private:
98         //@cond
99         monitor_type&    m_Monitor; ///< Monitor
100         node_type const& m_Node;    ///< Our locked node
101         //@endcond
102     public:
103         /// Makes exclusive access to the node \p p by \p monitor
104         monitor_scoped_lock( monitor_type& monitor, node_type const& p )
105             : m_Monitor( monitor )
106             , m_Node( p )
107         {
108             monitor.lock( p );
109         }
110         /// Unlocks the node
111         ~monitor_scoped_lock()
112         {
113             m_Monitor.unlock( m_Node );
114         }
115     };
116 }} // namespace cds::sync
117 #endif // #ifndef CDSLIB_SYNC_MONITOR_H
118