- 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 );
- }
-
-# ifdef CDS_RVALUE_SUPPORT
- /// 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 );
- }
-# endif
-
- /// 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() );
- lock_type& l = m_arrLocks[ nCell ];
- l.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() );
- lock_type& l = m_arrLocks[ nCell ];
- if ( l.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 ( size_t i = 0; i < size(); ++i, ++pLock )
- pLock->lock();
- }
-
- /// Unlock all
- void unlock_all()
- {
- lock_type * pLock = m_arrLocks;
- for ( size_t i = 0; i < size(); ++i, ++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;
- }
- };
-
- /// Specialization \ref scoped_lock for lock::array
- template <typename Lock, typename SelectPolicy, class Alloc>
- class scoped_lock< cds::lock::array< Lock, SelectPolicy, Alloc > >: public cds::details::noncopyable
- {
- public:
- typedef cds::lock::array< Lock, SelectPolicy, Alloc > lock_array_type ; ///< Lock array type
-
- private:
- //@cond
- lock_array_type& m_arrLocks;
- size_t m_nLockGuarded;
-
- static const size_t c_nLockAll = ~size_t(0);
- //@endcond
-
- public:
- /// Onws the lock array \p arrLocks and locks a cell determined by \p hint parameter
- template <typename Q>
- scoped_lock( lock_array_type& arrLocks, Q const& hint )
- : m_arrLocks( arrLocks )
- , m_nLockGuarded( arrLocks.lock( hint ))
- {}
-
- /// Locks all from \p arrLocks array
- scoped_lock( lock_array_type& arrLocks )
- : m_arrLocks( arrLocks )
- , m_nLockGuarded( c_nLockAll )
- {
- arrLocks.lock_all();
- }
-
- ~scoped_lock()
- {
- if ( m_nLockGuarded == c_nLockAll )
- m_arrLocks.unlock_all();
- else
- m_arrLocks.unlock( m_nLockGuarded );
- }
- };