X-Git-Url: http://plrg.eecs.uci.edu/git/?p=libcds.git;a=blobdiff_plain;f=cds%2Furcu%2Fdetails%2Fgpb.h;h=5ad75d130d202372af6d13f5847a20a658259fa5;hp=94e27b65de3e51feb7d7afe32c7255e0dce5eeaf;hb=HEAD;hpb=c0720d814a5cbb40dcd8f3c278dbc30a833e429b diff --git a/cds/urcu/details/gpb.h b/cds/urcu/details/gpb.h index 94e27b65..5ad75d13 100644 --- a/cds/urcu/details/gpb.h +++ b/cds/urcu/details/gpb.h @@ -1,9 +1,38 @@ -//$$CDS-header$$ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ #ifndef CDSLIB_URCU_DETAILS_GPB_H #define CDSLIB_URCU_DETAILS_GPB_H #include +#include #include #include #include @@ -20,7 +49,7 @@ namespace cds { namespace urcu { i.e. until the RCU quiescent state will come. After that the buffer and all retired objects are freed. This synchronization cycle may be called in any thread that calls \p retire_ptr function. - The \p Buffer contains items of \ref cds_urcu_retired_ptr "retired_ptr" type and it should support a queue interface with + The \p Buffer contains items of \ref cds_urcu_retired_ptr "epoch_retired_ptr" type and it should support a queue interface with three function: - bool push( retired_ptr& p ) - places the retired pointer \p p into queue. If the function returns \p false it means that the buffer is full and RCU synchronization cycle must be processed. @@ -28,13 +57,13 @@ namespace cds { namespace urcu { this function must return \p false - size_t size() - returns queue's item count. - The buffer is considered as full if \p push returns \p false or the buffer size reaches the RCU threshold. + The buffer is considered as full if \p push() returns \p false or the buffer size reaches the RCU threshold. There is a wrapper \ref cds_urcu_general_buffered_gc "gc" for \p %general_buffered class that provides unified RCU interface. You should use this wrapper class instead \p %general_buffered Template arguments: - - \p Buffer - buffer type. Default is cds::container::VyukovMPMCCycleQueue + - \p Buffer - buffer type. Default is \p cds::container::VyukovMPMCCycleQueue - \p Lock - mutex type, default is \p std::mutex - \p Backoff - back-off schema, default is cds::backoff::Default */ @@ -57,7 +86,9 @@ namespace cds { namespace urcu { typedef base_class::thread_gc thread_gc ; ///< Thread-side RCU part typedef typename thread_gc::scoped_lock scoped_lock ; ///< Access lock class - static bool const c_bBuffered = true ; ///< This RCU buffers disposed elements + //@cond + static bool const c_bBuffered = true ; ///< Bufferized RCU + //@endcond protected: //@cond @@ -66,17 +97,17 @@ namespace cds { namespace urcu { protected: //@cond - buffer_type m_Buffer; - atomics::atomic m_nCurEpoch; - lock_type m_Lock; - size_t const m_nCapacity; + buffer_type m_Buffer; + atomics::atomic m_nCurEpoch; + lock_type m_Lock; + size_t const m_nCapacity; //@endcond public: /// Returns singleton instance static general_buffered * instance() { - return static_cast( base_class::instance() ); + return static_cast( base_class::instance()); } /// Checks if the singleton is created and ready to use static bool isUsed() @@ -94,7 +125,7 @@ namespace cds { namespace urcu { ~general_buffered() { - clear_buffer( (uint64_t) -1 ); + clear_buffer( std::numeric_limits< uint64_t >::max()); } void flip_and_wait() @@ -111,17 +142,17 @@ namespace cds { namespace urcu { p.free(); } else { - push_buffer( std::move(p) ); + push_buffer( std::move(p)); break; } } } - // Return: true - synchronize has been called, false - otherwise + // Return: \p true - synchronize has been called, \p false - otherwise bool push_buffer( epoch_retired_ptr&& ep ) { bool bPushed = m_Buffer.push( ep ); - if ( !bPushed || m_Buffer.size() >= capacity() ) { + if ( !bPushed || m_Buffer.size() >= capacity()) { synchronize(); if ( !bPushed ) { ep.free(); @@ -146,8 +177,8 @@ namespace cds { namespace urcu { /// Destroys singleton object static void Destruct( bool bDetachAll = false ) { - if ( isUsed() ) { - instance()->clear_buffer( (uint64_t) -1 ); + if ( isUsed()) { + instance()->clear_buffer( std::numeric_limits< uint64_t >::max()); if ( bDetachAll ) instance()->m_ThreadList.detach_all(); delete instance(); @@ -162,7 +193,7 @@ namespace cds { namespace urcu { When the buffer becomes full \ref synchronize function is called to wait for the end of grace period and then to free all pointers from the buffer. */ - virtual void retire_ptr( retired_ptr& p ) + virtual void retire_ptr( retired_ptr& p ) override { if ( p.m_p ) push_buffer( epoch_retired_ptr( p, m_nCurEpoch.load( atomics::memory_order_relaxed ))); @@ -176,7 +207,7 @@ namespace cds { namespace urcu { while ( itFirst != itLast ) { epoch_retired_ptr ep( *itFirst, nEpoch ); ++itFirst; - push_buffer( std::move(ep) ); + push_buffer( std::move(ep)); } } @@ -203,17 +234,15 @@ namespace cds { namespace urcu { bool synchronize( epoch_retired_ptr& ep ) { uint64_t nEpoch; - atomics::atomic_thread_fence( atomics::memory_order_acquire ); { std::unique_lock sl( m_Lock ); - if ( ep.m_p && m_Buffer.push( ep ) ) + if ( ep.m_p && m_Buffer.push( ep )) return false; nEpoch = m_nCurEpoch.fetch_add( 1, atomics::memory_order_relaxed ); flip_and_wait(); flip_and_wait(); } clear_buffer( nEpoch ); - atomics::atomic_thread_fence( atomics::memory_order_release ); return true; } //@endcond @@ -225,6 +254,17 @@ namespace cds { namespace urcu { } }; + /// User-space general-purpose RCU with deferred (buffered) reclamation (stripped version) + /** + @headerfile cds/urcu/general_buffered.h + + This short version of \p general_buffered is intended for stripping debug info. + If you use \p %general_buffered with default template arguments you may use + this stripped version. All functionality of both classes are identical. + */ + class general_buffered_stripped: public general_buffered<> + {}; + }} // namespace cds::urcu #endif // #ifndef CDSLIB_URCU_DETAILS_GPB_H