From: khizmax Date: Sat, 31 Jan 2015 14:36:04 +0000 (+0300) Subject: Renamed cds::lock::array to cds::sync::lock_array, moved cds/lock/array.h to cds... X-Git-Tag: v2.1.0~309 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=5132f0323b7743772f980a095024760f4ec22ff5;p=libcds.git Renamed cds::lock::array to cds::sync::lock_array, moved cds/lock/array.h to cds/sync/lock_array.h --- diff --git a/cds/intrusive/cuckoo_set.h b/cds/intrusive/cuckoo_set.h index ab65aa2f..b9a5e851 100644 --- a/cds/intrusive/cuckoo_set.h +++ b/cds/intrusive/cuckoo_set.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -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 ) diff --git a/cds/intrusive/striped_set/striping_policy.h b/cds/intrusive/striped_set/striping_policy.h index c0f9d807..093df5c0 100644 --- a/cds/intrusive/striped_set/striping_policy.h +++ b/cds/intrusive/striped_set/striping_policy.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include @@ -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 ) diff --git a/cds/lock/array.h b/cds/lock/array.h index 4842582a..d3376cc9 100644 --- a/cds/lock/array.h +++ b/cds/lock/array.h @@ -1,324 +1,26 @@ -//$$CDS-header$$-2 +//$$CDS-header$$ #ifndef __CDS_LOCK_ARRAY_H #define __CDS_LOCK_ARRAY_H -#include //unique_lock -#include -#include +#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 nWhat % nCapacity - 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 nWhat & (nPow2 - 1) - size_t operator()( size_t nWhat, size_t ) const - { - return nWhat & m_nMask; - } +#include - /// 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 - 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( 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 select_cell_policy( hint, size() ). - - Returns the index of locked lock. - */ - template - 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 select_cell_policy( hint, size() ). - - Returns the index of locked lock if success, \ref c_nUnspecifiedCell constant otherwise. - */ - template - 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: nCell < size() - */ - 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 - 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 - 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 __CDS_LOCK_ARRAY_H diff --git a/cds/lock/spinlock.h b/cds/lock/spinlock.h index ee6ad258..da1b6868 100644 --- a/cds/lock/spinlock.h +++ b/cds/lock/spinlock.h @@ -1,4 +1,4 @@ -//$$CDS-header$$-2 +//$$CDS-header$$ #ifndef __CDS_LOCK_SPINLOCK_H #define __CDS_LOCK_SPINLOCK_H diff --git a/cds/opt/options.h b/cds/opt/options.h index 6645adaf..24c9499d 100644 --- a/cds/opt/options.h +++ b/cds/opt/options.h @@ -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 diff --git a/cds/sync/lock_array.h b/cds/sync/lock_array.h new file mode 100644 index 00000000..60044917 --- /dev/null +++ b/cds/sync/lock_array.h @@ -0,0 +1,325 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_SYNC_LOCK_ARRAY_H +#define CDSLIB_SYNC_LOCK_ARRAY_H + +#include //unique_lock +#include +#include + +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 nWhat % nCapacity + 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 nWhat & (nPow2 - 1) + 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 + 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( 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 select_cell_policy( hint, size() ). + + Returns the index of locked lock. + */ + template + 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 select_cell_policy( hint, size() ). + + Returns the index of locked lock if success, \ref c_nUnspecifiedCell constant otherwise. + */ + template + 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: nCell < size() + */ + 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 + 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 + 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 diff --git a/cds/sync/spinlock.h b/cds/sync/spinlock.h index 753fe07e..274c82fb 100644 --- a/cds/sync/spinlock.h +++ b/cds/sync/spinlock.h @@ -1,4 +1,4 @@ -//$$CDS-header$$-2 +//$$CDS-header$$ #ifndef CDSLIB_SYNC_SPINLOCK_H #define CDSLIB_SYNC_SPINLOCK_H diff --git a/projects/Win/vc12/cds.vcxproj b/projects/Win/vc12/cds.vcxproj index 0bdfd121..80376ec7 100644 --- a/projects/Win/vc12/cds.vcxproj +++ b/projects/Win/vc12/cds.vcxproj @@ -794,6 +794,7 @@ + diff --git a/projects/Win/vc12/cds.vcxproj.filters b/projects/Win/vc12/cds.vcxproj.filters index 5cbefad1..4b1c7f4b 100644 --- a/projects/Win/vc12/cds.vcxproj.filters +++ b/projects/Win/vc12/cds.vcxproj.filters @@ -1172,5 +1172,8 @@ Header Files\cds\sync + + Header Files\cds\sync + \ No newline at end of file