Renamed cds::lock::array to cds::sync::lock_array, moved cds/lock/array.h to cds...
authorkhizmax <libcds.dev@gmail.com>
Sat, 31 Jan 2015 14:36:04 +0000 (17:36 +0300)
committerkhizmax <libcds.dev@gmail.com>
Sat, 31 Jan 2015 14:36:04 +0000 (17:36 +0300)
cds/intrusive/cuckoo_set.h
cds/intrusive/striped_set/striping_policy.h
cds/lock/array.h
cds/lock/spinlock.h
cds/opt/options.h
cds/sync/lock_array.h [new file with mode: 0644]
cds/sync/spinlock.h
projects/Win/vc12/cds.vcxproj
projects/Win/vc12/cds.vcxproj.filters

index 83d438867aeb29299bf87f34dd28f3b830c07649..0fc53d7bc4d6366e891368f60c05d7d03fd925cd 100644 (file)
@@ -10,7 +10,7 @@
 #include <cds/intrusive/details/base.h>
 #include <cds/opt/compare.h>
 #include <cds/opt/hash.h>
-#include <cds/lock/array.h>
+#include <cds/sync/lock_array.h>
 #include <cds/os/thread.h>
 #include <cds/sync/spinlock.h>
 
@@ -376,7 +376,7 @@ namespace cds { namespace intrusive {
             };
             //@endcond
 
-            typedef cds::lock::array< lock_type, cds::lock::pow2_select_policy, allocator_type >    lock_array_type ;   ///< lock array type
+            typedef cds::sync::lock_array< lock_type, cds::sync::pow2_select_policy, allocator_type >    lock_array_type ;   ///< lock array type
 
         protected:
             //@cond
@@ -630,13 +630,13 @@ namespace cds { namespace intrusive {
 
         protected:
             //@cond
-            typedef cds::lock::trivial_select_policy  lock_selection_policy;
+            typedef cds::sync::trivial_select_policy  lock_selection_policy;
 
             class lock_array_type
-                : public cds::lock::array< lock_type, lock_selection_policy, allocator_type >
+                : public cds::sync::lock_array< lock_type, lock_selection_policy, allocator_type >
                 , public std::enable_shared_from_this< lock_array_type >
             {
-                typedef cds::lock::array< lock_type, lock_selection_policy, allocator_type >    lock_array_base;
+                typedef cds::sync::lock_array< lock_type, lock_selection_policy, allocator_type >    lock_array_base;
             public:
                 lock_array_type( size_t nCapacity )
                     : lock_array_base( nCapacity )
index 9c0640702d454abbb8ecfb1baf6bd56dce18e6a0..1655a308f7facadba0ab31b5397390dec4428166 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <memory>
 #include <mutex>
-#include <cds/lock/array.h>
+#include <cds/sync/lock_array.h>
 #include <cds/os/thread.h>
 #include <cds/sync/spinlock.h>
 
@@ -36,7 +36,7 @@ namespace cds { namespace intrusive { namespace striped_set {
         typedef Lock    lock_type       ;   ///< lock type
         typedef Alloc   allocator_type  ;   ///< allocator type
 
-        typedef cds::lock::array< lock_type, cds::lock::pow2_select_policy, allocator_type >    lock_array_type ;   ///< lock array type
+        typedef cds::sync::lock_array< lock_type, cds::sync::pow2_select_policy, allocator_type >    lock_array_type ;   ///< lock array type
 
     protected:
         //@cond
@@ -80,7 +80,7 @@ namespace cds { namespace intrusive { namespace striped_set {
         striping(
             size_t nLockCount   ///< The size of lock array. Must be power of two.
         )
-            : m_Locks( nLockCount, cds::lock::pow2_select_policy( nLockCount ))
+            : m_Locks( nLockCount, cds::sync::pow2_select_policy( nLockCount ))
         {}
 
         /// Returns lock array size
@@ -126,13 +126,13 @@ namespace cds { namespace intrusive { namespace striped_set {
 
     protected:
         //@cond
-        typedef cds::lock::trivial_select_policy  lock_selection_policy;
+        typedef cds::sync::trivial_select_policy  lock_selection_policy;
 
         class lock_array_type
-            : public cds::lock::array< lock_type, lock_selection_policy, allocator_type >
+            : public cds::sync::lock_array< lock_type, lock_selection_policy, allocator_type >
             , public std::enable_shared_from_this< lock_array_type >
         {
-            typedef cds::lock::array< lock_type, lock_selection_policy, allocator_type >    lock_array_base;
+            typedef cds::sync::lock_array< lock_type, lock_selection_policy, allocator_type >    lock_array_base;
         public:
             lock_array_type( size_t nCapacity )
                 : lock_array_base( nCapacity )
index 03249c43750a7de7122fa0f59a4acb706fa87e21..fd87a2db6dc4fb934fdb65409c4387f7d725735d 100644 (file)
-//$$CDS-header$$-2
+//$$CDS-header$$
 
 #ifndef CDSLIB_LOCK_ARRAY_H
 #define CDSLIB_LOCK_ARRAY_H
 
-#include <mutex>    //unique_lock
-#include <cds/details/allocator.h>
-#include <cds/algo/int_algo.h>
+#warning "cds/lock/array.h is deprecated, use cds/sync/lock_array.h instead"
 
-namespace cds { namespace lock {
-
-    /// Trivial lock \ref array selection policy
-    struct trivial_select_policy
-    {
-        /// Returns \p nWhat
-        size_t operator()( size_t nWhat, size_t nCapacity ) const
-        {
-            assert( nWhat < nCapacity );
-            CDS_UNUSED( nCapacity );
-            return nWhat;
-        }
-
-        /// Checks if \p nCapacity is acceptable by policy. For trivial policy, any \p nCapacity is accepted.
-        static bool is_capacity_accepted( size_t nCapacity )
-        {
-            CDS_UNUSED( nCapacity );
-            return true;
-        }
-    };
-
-    /// The lock \ref array cell selection policy "division by modulo"
-    struct mod_select_policy
-    {
-        /// Returns <tt> nWhat % nCapacity </tt>
-        size_t operator()( size_t nWhat, size_t nCapacity ) const
-        {
-            return nWhat % nCapacity;
-        }
-
-        /// Checks if \p nCapacity is acceptable by policy. For modulo policy, any positive \p nCapacity is accepted.
-        static bool is_capacity_accepted( size_t nCapacity )
-        {
-            return nCapacity > 0;
-        }
-    };
-
-    /// The lock \ref array cell selection policy "division by modulo of power of 2"
-    /**
-        This policy may be used if the size of lock array is equal to power of two.
-    */
-    struct pow2_select_policy
-    {
-        //@cond
-        const size_t    m_nMask;
-        //@endcond
-
-        /// Ctor. \p nCapacity must be power of two.
-        pow2_select_policy( size_t nCapacity )
-            : m_nMask( nCapacity - 1 )
-        {
-            assert( is_capacity_accepted( nCapacity ));
-        }
-
-        /// Copy constructor
-        pow2_select_policy( pow2_select_policy const& src )
-            : m_nMask( src.m_nMask )
-        {}
-
-        /// Move constructor
-        pow2_select_policy( pow2_select_policy&& src )
-            : m_nMask( src.m_nMask )
-        {}
-
-        /// Returns <tt>nWhat & (nPow2 - 1)</tt>
-        size_t operator()( size_t nWhat, size_t ) const
-        {
-            return nWhat & m_nMask;
-        }
+#include <cds/sync/lock_array.h>
 
-        /// Checks if \p nCapacity is acceptable by policy. \p nCapacity must be power of two
-        static bool is_capacity_accepted( size_t nCapacity )
-        {
-            return cds::beans::is_power2( nCapacity );
-        }
-    };
-
-    /// Array of locks
-    /**
-        The lock array is useful for building fine-grained lock-based data structure
-        based on striping technique. Instead of locking access to data struct (a hash map, for example)
-        at whole, the striping locks only part of the map (a bucket). So, access to different buckets
-        can be simultaneous.
-
-        Template arguments:
-        - \p Lock - lock type, for example, \p std::mutex, \p cds::sync::spin_lock
-        - \p SelectPolicy - array cell selection policy, the default is \ref mod_select_policy
-             Available policies: \ref trivial_select_policy, \ref pow2_select_policy, \ref mod_select_policy.
-        - \p Alloc - memory allocator for array
+//@cond
+namespace cds { namespace lock {
 
-        To determine array's cell the selection policy \p SelectPolicy functor is used. Two arguments
-        are passed to the policy:
-        \code size_t operator()( size_t nHint, size_t nCapacity ) const \endcode
-        - \p nHint - a hint to calculate cell index in the lock array. Usually, it is a hash value.
-        - \p nCapacity - the size of the lock array
-        The functor should return the index in the lock array.
+    using cds::sync::trivial_select_policy;
+    using cds::sync::mod_select_policy;
+    using cds::sync::pow2_select_policy;
 
-        Note that the type of \p nHint parameter can be any.
-    */
     template <typename Lock
         , typename SelectPolicy = mod_select_policy
         , class Alloc = CDS_DEFAULT_ALLOCATOR
     >
-    class array
-    {
-        //@cond
-        typedef ::cds::details::Allocator< Lock, Alloc > cxx_allocator;
-        //@endcond
-    public:
-        typedef Lock            lock_type           ;   ///< lock type
-        typedef SelectPolicy    select_cell_policy  ;   ///< Cell selection policy functor
-        static size_t const     c_nUnspecifiedCell = (size_t) -1 ;  ///< failed \ref try_lock call result
-
-    protected:
-        lock_type *         m_arrLocks  ;   ///< lock array
-        size_t const        m_nCapacity ;   ///< array capacity
-
-        select_cell_policy  m_SelectCellPolicy  ;   ///< Cell selection policy
-
-    protected:
-        //@cond
-        static lock_type * create_lock_array( size_t nCapacity )
-        {
-            return cxx_allocator().NewArray( nCapacity );
-        }
-        static void delete_lock_array( lock_type * pArr, size_t nCapacity )
-        {
-            if ( pArr )
-                cxx_allocator().Delete( pArr, nCapacity );
-        }
-
-        // Only for internal use!!!
-        array()
-            : m_arrLocks( nullptr )
-            , m_nCapacity(0)
-        {}
-        array( select_cell_policy const& policy )
-            : m_arrLocks( nullptr )
-            , m_nCapacity(0)
-            , m_SelectCellPolicy( policy )
-        {}
-        //@endcond
-
-    public:
-        /// Constructs array of locks
-        /**
-            Allocates the array and initializes all locks as unlocked.
-        */
-        array(
-            size_t nCapacity        ///< [in] Array size
-        )
-        : m_arrLocks( nullptr )
-        , m_nCapacity( nCapacity )
-        {
-            m_arrLocks = create_lock_array( nCapacity );
-        }
-
-        /// Constructs array of lock and copy cell selection policy
-        /**
-            Allocates the array and initializes all locks as unlocked.
-        */
-        array(
-            size_t nCapacity,       ///< [in] Array size
-            select_cell_policy const& policy    ///< Cell selection policy (copy-constructible)
-        )
-        : m_arrLocks( nullptr )
-        , m_nCapacity( nCapacity )
-        , m_SelectCellPolicy( policy )
-        {
-            m_arrLocks = create_lock_array( m_nCapacity );
-        }
-
-        /// Constructs array of lock and move cell selection policy
-        /**
-            Allocates the array and initializes all locks as unlocked.
-        */
-        array(
-            size_t nCapacity,       ///< [in] Array size
-            select_cell_policy&& policy    ///< Cell selection policy (move-constructible)
-        )
-        : m_arrLocks( nullptr )
-        , m_nCapacity( nCapacity )
-        , m_SelectCellPolicy( std::forward<select_cell_policy>( policy ))
-        {
-            m_arrLocks = create_lock_array( m_nCapacity );
-        }
-
-        /// Destructs array of locks and frees used memory
-        ~array()
-        {
-            delete_lock_array( m_arrLocks, m_nCapacity );
-        }
-
-        /// Locks a lock at cell \p hint
-        /**
-            To define real array's cell which should be locked, \ref select_cell_policy is used.
-            The target cell is a result of <tt>select_cell_policy( hint, size() )</tt>.
-
-            Returns the index of locked lock.
-        */
-        template <typename Q>
-        size_t lock( Q const& hint )
-        {
-            size_t nCell = m_SelectCellPolicy( hint, size() );
-            assert( nCell < size() );
-            m_arrLocks[nCell].lock();
-            return nCell;
-        }
-
-        /// Try lock a lock at cell \p hint
-        /**
-            To define real array's cell which should be locked, \ref select_cell_policy is used.
-            The target cell is a result of <tt>select_cell_policy( hint, size() )</tt>.
-
-            Returns the index of locked lock if success, \ref c_nUnspecifiedCell constant otherwise.
-        */
-        template <typename Q>
-        size_t try_lock( Q const& hint )
-        {
-            size_t nCell = m_SelectCellPolicy( hint, size() );
-            assert( nCell < size() );
-            if ( m_arrLocks[nCell].try_lock() )
-                return nCell;
-            return c_nUnspecifiedCell;
-        }
-
-        /// Unlock the lock specified by index \p nCell
-        void unlock( size_t nCell )
-        {
-            assert( nCell < size() );
-            m_arrLocks[nCell].unlock();
-        }
-
-        /// Lock all
-        void lock_all()
-        {
-            lock_type * pLock = m_arrLocks;
-            for ( lock_type * pEnd = m_arrLocks + size(); pLock != pEnd; ++pLock )
-                pLock->lock();
-        }
-
-        /// Unlock all
-        void unlock_all()
-        {
-            lock_type * pLock = m_arrLocks;
-            for ( lock_type * pEnd = m_arrLocks + size(); pLock != pEnd; ++pLock )
-                pLock->unlock();
-        }
-
-        /// Get lock at cell \p nCell.
-        /**
-            Precondition: <tt>nCell < size()</tt>
-        */
-        lock_type& at( size_t nCell ) const
-        {
-            assert( nCell < size() );
-            return m_arrLocks[ nCell ];
-        }
-
-        /// Size of lock array.
-        size_t size() const
-        {
-            return m_nCapacity;
-        }
-    };
+    using array = cds::sync::lock_array< Lock, SelectPolicy, Alloc >;
 
 }} // namespace cds::lock
-
-//@cond
-namespace std {
-
-    /// Specialization \ref scoped_lock for lock::array
-    template <typename Lock, typename SelectPolicy, class Alloc>
-    class unique_lock< cds::lock::array< Lock, SelectPolicy, Alloc > >
-    {
-    public:
-        typedef cds::lock::array< Lock, SelectPolicy, Alloc >   lock_array_type;   ///< Lock array type
-
-    private:
-        lock_array_type&    m_arrLocks;
-        size_t              m_nLockGuarded;
-
-        static const size_t c_nLockAll = ~size_t( 0 );
-
-    public:
-        /// Onws the lock array \p arrLocks and locks a cell determined by \p hint parameter
-        template <typename Q>
-        unique_lock( lock_array_type& arrLocks, Q const& hint )
-            : m_arrLocks( arrLocks )
-            , m_nLockGuarded( arrLocks.lock( hint ) )
-        {}
-
-        /// Locks all from \p arrLocks array
-        unique_lock( lock_array_type& arrLocks )
-            : m_arrLocks( arrLocks )
-            , m_nLockGuarded( c_nLockAll )
-        {
-            arrLocks.lock_all();
-        }
-
-        unique_lock() = delete;
-        unique_lock( unique_lock const& ) = delete;
-
-        ~unique_lock()
-        {
-            if ( m_nLockGuarded == c_nLockAll )
-                m_arrLocks.unlock_all();
-            else
-                m_arrLocks.unlock( m_nLockGuarded );
-        }
-    };
-} // namespace std
 //@endcond
 
 #endif // #ifndef CDSLIB_LOCK_ARRAY_H
index 3986429276f381c4496842bf4d89ebbf1238e8a6..ae594d32f8f8ba06f5557b445f35cae135281936 100644 (file)
@@ -1,4 +1,4 @@
-//$$CDS-header$$-2
+//$$CDS-header$$
 
 #ifndef CDSLIB_LOCK_SPINLOCK_H
 #define CDSLIB_LOCK_SPINLOCK_H
index 72210369b0b0e415cbc17527850303a77a426ca7..34c289eb3b75c9f10696ba6803b0e86e77f7214a 100644 (file)
@@ -54,7 +54,7 @@ namespace opt {
         typedef typename cds::opt::select_default< cds::opt::none, cds::sync::spin >::type  default_spin;
 
         // spin_32bit is cds::sync::reentrant_spin32
-        typedef typename cds::opt::select_default< cds::lock::Spin32, cds::sync::reentrant_spin32 >::type  spin_32bit;
+        typedef typename cds::opt::select_default< cds::opt::none, cds::sync::reentrant_spin32 >::type  spin_32bit;
         \endcode
     */
     template <typename Option, typename Default, typename Value = Option>
diff --git a/cds/sync/lock_array.h b/cds/sync/lock_array.h
new file mode 100644 (file)
index 0000000..6004491
--- /dev/null
@@ -0,0 +1,325 @@
+//$$CDS-header$$
+
+#ifndef CDSLIB_SYNC_LOCK_ARRAY_H
+#define CDSLIB_SYNC_LOCK_ARRAY_H
+
+#include <mutex>    //unique_lock
+#include <cds/details/allocator.h>
+#include <cds/algo/int_algo.h>
+
+namespace cds { namespace sync {
+
+    /// Trivial lock \ref array selection policy
+    struct trivial_select_policy
+    {
+        /// Returns \p nWhat
+        size_t operator()( size_t nWhat, size_t nCapacity ) const
+        {
+            assert( nWhat < nCapacity );
+            CDS_UNUSED( nCapacity );
+            return nWhat;
+        }
+
+        /// Checks if \p nCapacity is acceptable by policy. For trivial policy, any \p nCapacity is accepted.
+        static bool is_capacity_accepted( size_t nCapacity )
+        {
+            CDS_UNUSED( nCapacity );
+            return true;
+        }
+    };
+
+    /// The lock \ref array cell selection policy "division by modulo"
+    struct mod_select_policy
+    {
+        /// Returns <tt> nWhat % nCapacity </tt>
+        size_t operator()( size_t nWhat, size_t nCapacity ) const
+        {
+            return nWhat % nCapacity;
+        }
+
+        /// Checks if \p nCapacity is acceptable by policy. For modulo policy, any positive \p nCapacity is accepted.
+        static bool is_capacity_accepted( size_t nCapacity )
+        {
+            return nCapacity > 0;
+        }
+    };
+
+    /// The lock \ref array cell selection policy "division by modulo of power of 2"
+    /**
+        This policy may be used if the size of lock array is equal to power of two.
+    */
+    struct pow2_select_policy
+    {
+        //@cond
+        const size_t    m_nMask;
+        //@endcond
+
+        /// Ctor. \p nCapacity must be power of two.
+        pow2_select_policy( size_t nCapacity )
+            : m_nMask( nCapacity - 1 )
+        {
+            assert( is_capacity_accepted( nCapacity ));
+        }
+
+        /// Copy constructor
+        pow2_select_policy( pow2_select_policy const& src )
+            : m_nMask( src.m_nMask )
+        {}
+
+        /// Move constructor
+        pow2_select_policy( pow2_select_policy&& src )
+            : m_nMask( src.m_nMask )
+        {}
+
+        /// Returns <tt>nWhat & (nPow2 - 1)</tt>
+        size_t operator()( size_t nWhat, size_t ) const
+        {
+            return nWhat & m_nMask;
+        }
+
+        /// Checks if \p nCapacity is acceptable by policy. \p nCapacity must be power of two
+        static bool is_capacity_accepted( size_t nCapacity )
+        {
+            return cds::beans::is_power2( nCapacity );
+        }
+    };
+
+    /// Array of locks
+    /**
+        The lock array is useful for building fine-grained lock-based data structure
+        based on striping technique. Instead of locking access to data struct (a hash map, for example)
+        at whole, the striping locks only part of the map (a bucket). So, access to different buckets
+        can be simultaneous.
+
+        Template arguments:
+        - \p Lock - lock type, for example, \p std::mutex, \p cds::sync::spin_lock
+        - \p SelectPolicy - array cell selection policy, the default is \ref mod_select_policy
+             Available policies: \ref trivial_select_policy, \ref pow2_select_policy, \ref mod_select_policy.
+        - \p Alloc - memory allocator for array
+
+        To determine array's cell the selection policy \p SelectPolicy functor is used. Two arguments
+        are passed to the policy:
+        \code size_t operator()( size_t nHint, size_t nCapacity ) const \endcode
+        - \p nHint - a hint to calculate cell index in the lock array. Usually, it is a hash value.
+        - \p nCapacity - the size of the lock array
+        The functor should return the index in the lock array.
+
+        Note that the type of \p nHint parameter can be any.
+    */
+    template <typename Lock
+        , typename SelectPolicy = mod_select_policy
+        , class Alloc = CDS_DEFAULT_ALLOCATOR
+    >
+    class lock_array
+    {
+        //@cond
+        typedef ::cds::details::Allocator< Lock, Alloc > cxx_allocator;
+        //@endcond
+    public:
+        typedef Lock            lock_type           ;   ///< lock type
+        typedef SelectPolicy    select_cell_policy  ;   ///< Cell selection policy functor
+        static size_t const     c_nUnspecifiedCell = (size_t) -1 ;  ///< failed \ref try_lock call result
+
+    protected:
+        lock_type *         m_arrLocks  ;   ///< lock array
+        size_t const        m_nCapacity ;   ///< array capacity
+
+        select_cell_policy  m_SelectCellPolicy  ;   ///< Cell selection policy
+
+    protected:
+        //@cond
+        static lock_type * create_lock_array( size_t nCapacity )
+        {
+            return cxx_allocator().NewArray( nCapacity );
+        }
+        static void delete_lock_array( lock_type * pArr, size_t nCapacity )
+        {
+            if ( pArr )
+                cxx_allocator().Delete( pArr, nCapacity );
+        }
+
+        // Only for internal use!!!
+        lock_array()
+            : m_arrLocks( nullptr )
+            , m_nCapacity(0)
+        {}
+
+        lock_array( select_cell_policy const& policy )
+            : m_arrLocks( nullptr )
+            , m_nCapacity(0)
+            , m_SelectCellPolicy( policy )
+        {}
+        //@endcond
+
+    public:
+        /// Constructs array of locks
+        /**
+            Allocates the array and initializes all locks as unlocked.
+        */
+        lock_array(
+            size_t nCapacity        ///< [in] Array size
+        )
+        : m_arrLocks( nullptr )
+        , m_nCapacity( nCapacity )
+        {
+            m_arrLocks = create_lock_array( nCapacity );
+        }
+
+        /// Constructs array of lock and copy cell selection policy
+        /**
+            Allocates the array and initializes all locks as unlocked.
+        */
+        lock_array(
+            size_t nCapacity,       ///< [in] Array size
+            select_cell_policy const& policy    ///< Cell selection policy (copy-constructible)
+        )
+        : m_arrLocks( nullptr )
+        , m_nCapacity( nCapacity )
+        , m_SelectCellPolicy( policy )
+        {
+            m_arrLocks = create_lock_array( m_nCapacity );
+        }
+
+        /// Constructs array of lock and move cell selection policy
+        /**
+            Allocates the array and initializes all locks as unlocked.
+        */
+        lock_array(
+            size_t nCapacity,       ///< [in] Array size
+            select_cell_policy&& policy    ///< Cell selection policy (move-constructible)
+        )
+        : m_arrLocks( nullptr )
+        , m_nCapacity( nCapacity )
+        , m_SelectCellPolicy( std::forward<select_cell_policy>( policy ))
+        {
+            m_arrLocks = create_lock_array( m_nCapacity );
+        }
+
+        /// Destructs array of locks and frees used memory
+        ~lock_array()
+        {
+            delete_lock_array( m_arrLocks, m_nCapacity );
+        }
+
+        /// Locks a lock at cell \p hint
+        /**
+            To define real array's cell which should be locked, \ref select_cell_policy is used.
+            The target cell is a result of <tt>select_cell_policy( hint, size() )</tt>.
+
+            Returns the index of locked lock.
+        */
+        template <typename Q>
+        size_t lock( Q const& hint )
+        {
+            size_t nCell = m_SelectCellPolicy( hint, size() );
+            assert( nCell < size() );
+            m_arrLocks[nCell].lock();
+            return nCell;
+        }
+
+        /// Try lock a lock at cell \p hint
+        /**
+            To define real array's cell which should be locked, \ref select_cell_policy is used.
+            The target cell is a result of <tt>select_cell_policy( hint, size() )</tt>.
+
+            Returns the index of locked lock if success, \ref c_nUnspecifiedCell constant otherwise.
+        */
+        template <typename Q>
+        size_t try_lock( Q const& hint )
+        {
+            size_t nCell = m_SelectCellPolicy( hint, size() );
+            assert( nCell < size() );
+            if ( m_arrLocks[nCell].try_lock() )
+                return nCell;
+            return c_nUnspecifiedCell;
+        }
+
+        /// Unlock the lock specified by index \p nCell
+        void unlock( size_t nCell )
+        {
+            assert( nCell < size() );
+            m_arrLocks[nCell].unlock();
+        }
+
+        /// Lock all
+        void lock_all()
+        {
+            lock_type * pLock = m_arrLocks;
+            for ( lock_type * pEnd = m_arrLocks + size(); pLock != pEnd; ++pLock )
+                pLock->lock();
+        }
+
+        /// Unlock all
+        void unlock_all()
+        {
+            lock_type * pLock = m_arrLocks;
+            for ( lock_type * pEnd = m_arrLocks + size(); pLock != pEnd; ++pLock )
+                pLock->unlock();
+        }
+
+        /// Get lock at cell \p nCell.
+        /**
+            Precondition: <tt>nCell < size()</tt>
+        */
+        lock_type& at( size_t nCell ) const
+        {
+            assert( nCell < size() );
+            return m_arrLocks[ nCell ];
+        }
+
+        /// Size of lock array.
+        size_t size() const
+        {
+            return m_nCapacity;
+        }
+    };
+
+}} // namespace cds::sync
+
+//@cond
+namespace std {
+
+    /// Specialization \p std::unique_lock for \p sync::lock_array
+    template <typename Lock, typename SelectPolicy, class Alloc>
+    class unique_lock< cds::sync::lock_array< Lock, SelectPolicy, Alloc > >
+    {
+    public:
+        typedef cds::sync::lock_array< Lock, SelectPolicy, Alloc >   lock_array_type;   ///< Lock array type
+
+    private:
+        lock_array_type&    m_arrLocks;
+        size_t              m_nLockGuarded;
+
+        static const size_t c_nLockAll = ~size_t( 0 );
+
+    public:
+        /// Onws the lock array \p arrLocks and locks a cell determined by \p hint parameter
+        template <typename Q>
+        unique_lock( lock_array_type& arrLocks, Q const& hint )
+            : m_arrLocks( arrLocks )
+            , m_nLockGuarded( arrLocks.lock( hint ) )
+        {}
+
+        /// Locks all from \p arrLocks array
+        unique_lock( lock_array_type& arrLocks )
+            : m_arrLocks( arrLocks )
+            , m_nLockGuarded( c_nLockAll )
+        {
+            arrLocks.lock_all();
+        }
+
+        unique_lock() = delete;
+        unique_lock( unique_lock const& ) = delete;
+
+        ~unique_lock()
+        {
+            if ( m_nLockGuarded == c_nLockAll )
+                m_arrLocks.unlock_all();
+            else
+                m_arrLocks.unlock( m_nLockGuarded );
+        }
+    };
+} // namespace std
+//@endcond
+
+#endif // #ifndef CDSLIB_SYNC_LOCK_ARRAY_H
index 753fe07e7ae1d98995aa4025889bdaa1fb560ef8..274c82fb1bd4ac4ba1e79157b5124af78d8934e9 100644 (file)
@@ -1,4 +1,4 @@
-//$$CDS-header$$-2
+//$$CDS-header$$
 
 #ifndef CDSLIB_SYNC_SPINLOCK_H
 #define CDSLIB_SYNC_SPINLOCK_H
index 5276d404673445735aefdd1989ad9d53d68ef28d..2cb16e322ed18525e577d6aed49242d7bf210f02 100644 (file)
     <ClInclude Include="..\..\..\cds\os\posix\fake_topology.h" />\r
     <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\spinlock.h" />\r
     <ClInclude Include="..\..\..\cds\threading\details\cxx11.h" />\r
     <ClInclude Include="..\..\..\cds\threading\details\cxx11_manager.h" />\r
index f076002297c742e1266aeb6a5bbaf7c9972b44b5..3d4a7756762d71632a952d09e738d022ac884ad9 100644 (file)
     <ClInclude Include="..\..\..\cds\sync\spinlock.h">\r
       <Filter>Header Files\cds\sync</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\cds\sync\lock_array.h">\r
+      <Filter>Header Files\cds\sync</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file