Added sync::Monitor concept
authorkhizmax <khizmax@gmail.com>
Mon, 2 Feb 2015 10:58:50 +0000 (13:58 +0300)
committerkhizmax <khizmax@gmail.com>
Mon, 2 Feb 2015 10:58:50 +0000 (13:58 +0300)
cds/sync/injected_monitor.h
cds/sync/monitor.h [new file with mode: 0644]
projects/Win/vc12/cds.vcxproj
projects/Win/vc12/cds.vcxproj.filters

index 2e567aac4459abf1d36a65ce7d4944aceac72b36..17fbf6665f96e9272c8c7f0b73b7a6e50636de5b 100644 (file)
@@ -5,10 +5,15 @@
 
 namespace cds { namespace sync {
 
-    /// Monitor that injects a lock as a member into a class
+    /// @ref cds_sync_monitor "Monitor" that injects the lock into each node
     /**
+        This monitor injects the lock object of type \p Lock into each node. 
+        The monitor is designed for user-space locking primitives like \ref sync::spin_lock "spin-lock".
+
         Template arguments:
         - Lock - lock type like \p std::mutex or \p cds::sync::spin
+
+
     */
     template <typename Lock>
     class injected_monitor
@@ -60,7 +65,7 @@ namespace cds { namespace sync {
         template <typename T>
         class scoped_lock
         {
-            T const& m_Locked;
+            T const& m_Locked;  ///< Our locked node
 
         public:
             /// Makes exclusive access to object \p p of type T
diff --git a/cds/sync/monitor.h b/cds/sync/monitor.h
new file mode 100644 (file)
index 0000000..cc96d11
--- /dev/null
@@ -0,0 +1,84 @@
+//$$CDS-header$$
+
+#ifndef CDSLIB_SYNC_MONITOR_H
+#define CDSLIB_SYNC_MONITOR_H
+
+namespace cds { namespace sync {
+
+    /**
+        @page cds_sync_monitor Synchronization monitor
+
+        A <a href="http://en.wikipedia.org/wiki/Monitor_%28synchronization%29">monitor</a> is synchronization construct
+        that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true.
+
+        Some blocking data structure algoritms like the trees require per-node locking.
+        For huge trees containing millions of nodes it can be very inefficient to inject
+        the lock object into each node. Moreover, some operating systems may not support
+        the millions of system objects like mutexes per user process.
+
+        The monitor strategy is intended to solve that problem.
+        When the node should be locked, the monitor is called to allocate appropriate
+        lock object for the node if it's needed, and to lock the node.
+        The monitor strategy can significantly reduce the number of system objects
+        required for the data structure.
+
+        <b>Implemetatios</b>
+
+        \p libcds contains several monitor implementations:
+        - \p sync::injected_monitor injects the lock object into each node.
+            That mock monitor is designed for user-space locking primitive like
+            \ref sync::spin_lock "spin-lock".
+
+        <b>How to use</b>
+
+        If you use a container from \p libcds that requires a monitor, you should just
+        specify required monitor type in container's traits. Usually, the monitor 
+        is specified by \p traits::sync_monitor typedef, or by \p cds::opt::sync_monitor
+        option for container's \p make_traits metafunction.
+
+        If you're developing a new container algorithm, you should know internal monitor 
+        interface:
+        \code
+        class Monitor {
+        public:
+            // Monitor's injection into the Node class
+            template <typename Node>
+            struct wrapper;
+
+            // Locks the node 
+            template <typename Node>
+            void lock( Node& node );
+
+            // Unlocks the node
+            template <typename Node>
+            void unlock( Node& node );
+
+            // Scoped lock applyes RAII to Monitor
+            template <typename Node>
+            class scoped_lock 
+            {
+            public:
+                // Locks node by monitor mon
+                scoped_lock( Monitor& mon, Node& node );
+
+                // Unlocks the node locked by ctor
+                ~scoped_lock();
+            };
+        };
+        \endcode
+        The monitor should be a member of your container:
+        \code
+        template <typename GC, typename T, typename Traits>
+        class my_container {
+            // ...
+            typedef typename Traits::sync_monitor   sync_monitor;
+            sync_monitor m_Monitor;
+            //...
+        };
+        \endcode
+    */
+
+}} // namespace cds::sync
+
+#endif // #ifndef CDSLIB_SYNC_MONITOR_H
+
index 2cb16e322ed18525e577d6aed49242d7bf210f02..f20dfaf67267592da0ce60f7eb08367dafeeda18 100644 (file)
     <ClInclude Include="..\..\..\cds\os\posix\timer.h" />\r
     <ClInclude Include="..\..\..\cds\sync\injected_monitor.h" />\r
     <ClInclude Include="..\..\..\cds\sync\lock_array.h" />\r
+    <ClInclude Include="..\..\..\cds\sync\monitor.h" />\r
     <ClInclude Include="..\..\..\cds\sync\spinlock.h" />\r
     <ClInclude Include="..\..\..\cds\threading\details\cxx11.h" />\r
     <ClInclude Include="..\..\..\cds\threading\details\cxx11_manager.h" />\r
index 3d4a7756762d71632a952d09e738d022ac884ad9..205abcda4a272b0df955feacea06eb6bcd03a447 100644 (file)
     <ClInclude Include="..\..\..\cds\sync\lock_array.h">\r
       <Filter>Header Files\cds\sync</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\cds\sync\monitor.h">\r
+      <Filter>Header Files\cds\sync</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file