#ifndef __CDS_INTRUSIVE_TSIGAS_CYCLE_QUEUE_H
#define __CDS_INTRUSIVE_TSIGAS_CYCLE_QUEUE_H
-#include <cds/intrusive/base.h>
+#include <functional> // ref
+#include <cds/intrusive/details/base.h>
#include <cds/cxx11_atomic.h>
#include <cds/details/bounded_container.h>
#include <cds/opt/buffer.h>
-#include <cds/ref.h>
namespace cds { namespace intrusive {
dynamic_queue dynQueue( 1024 );
\endcode
*/
- template <typename T, CDS_DECL_OPTIONS7>
+ template <typename T, typename... Options>
class TsigasCycleQueue: public cds::bounded_container
{
//@cond
public:
//@cond
typedef typename opt::make_options<
- typename cds::opt::find_type_traits< default_options, CDS_OPTIONS7>::type
- ,CDS_OPTIONS7
+ typename cds::opt::find_type_traits< default_options, Options...>::type
+ ,Options...
>::type options;
//@endcond
public:
/// Rebind template arguments
- template <typename T2, CDS_DECL_OTHER_OPTIONS7>
+ template <typename T2, typename... Options2>
struct rebind {
- typedef TsigasCycleQueue< T2, CDS_OTHER_OPTIONS7> other ; ///< Rebinding result
+ typedef TsigasCycleQueue< T2, Options2...> other ; ///< Rebinding result
};
public:
protected:
//@cond
- typedef typename options::buffer::template rebind< CDS_ATOMIC::atomic<value_type *> >::other buffer;
+ typedef typename options::buffer::template rebind< atomics::atomic<value_type *> >::other buffer;
typedef typename opt::details::alignment_setter< buffer, options::alignment >::type aligned_buffer;
typedef size_t index_type;
- typedef typename opt::details::alignment_setter< CDS_ATOMIC::atomic<index_type>, options::alignment >::type aligned_index;
+ typedef typename opt::details::alignment_setter< atomics::atomic<index_type>, options::alignment >::type aligned_index;
//@endcond
protected:
//@cond
static CDS_CONSTEXPR value_type * free0() CDS_NOEXCEPT
{
- return null_ptr<value_type *>();
+ return nullptr;
}
static CDS_CONSTEXPR value_type * free1() CDS_NOEXCEPT
{
}
// help the dequeue to update head
- m_nHead.compare_exchange_strong( temp, ate, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed );
+ m_nHead.compare_exchange_strong( temp, ate, memory_model::memory_order_release, atomics::memory_order_relaxed );
continue;
}
continue;
// get actual tail and try to enqueue new node
- if ( m_buffer[ate].compare_exchange_strong( tt, pNewNode, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed ) ) {
+ if ( m_buffer[ate].compare_exchange_strong( tt, pNewNode, memory_model::memory_order_release, atomics::memory_order_relaxed ) ) {
if ( temp % 2 == 0 )
- m_nTail.compare_exchange_strong( te, temp, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed );
+ m_nTail.compare_exchange_strong( te, temp, memory_model::memory_order_release, atomics::memory_order_relaxed );
++m_ItemCounter;
return true;
}
/// Dequeues item from the queue
/** @anchor cds_intrusive_TsigasQueue_dequeue
- If the queue is empty the function returns \a NULL
+ If the queue is empty the function returns \p nullptr
Dequeue does not call value disposer. You can manually dispose returned value if it is needed.
*/
if ( th != m_nHead.load(memory_model::memory_order_relaxed) )
goto TryAgain;
- // two consecutive NULL means queue empty
+ // two consecutive nullptr means queue empty
if ( temp == m_nTail.load(memory_model::memory_order_acquire) )
- return NULL;
+ return nullptr;
temp = ( temp + 1 ) & nModulo;
tt = m_buffer[ temp ].load(memory_model::memory_order_relaxed);
// check whether the queue is empty
if ( temp == m_nTail.load(memory_model::memory_order_acquire) ) {
// help the enqueue to update end
- m_nTail.compare_exchange_strong( temp, (temp + 1) & nModulo, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed );
+ m_nTail.compare_exchange_strong( temp, (temp + 1) & nModulo, memory_model::memory_order_release, atomics::memory_order_relaxed );
continue;
}
continue;
// Get the actual head, null means empty
- if ( m_buffer[temp].compare_exchange_strong( tt, pNull, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed )) {
+ if ( m_buffer[temp].compare_exchange_strong( tt, pNull, memory_model::memory_order_release, atomics::memory_order_relaxed )) {
if ( temp % 2 == 0 )
- m_nHead.compare_exchange_strong( th, temp, memory_model::memory_order_release, CDS_ATOMIC::memory_order_relaxed );
+ m_nHead.compare_exchange_strong( th, temp, memory_model::memory_order_release, atomics::memory_order_relaxed );
--m_ItemCounter;
return reinterpret_cast<value_type *>(reinterpret_cast<intptr_t>( tt ) & ~intptr_t(1));
}
} while ( bkoff(), true );
// No control path reaches this line!
- return null_ptr<value_type *>();
+ return nullptr;
}
/// Synonym of \ref cds_intrusive_TsigasQueue_enqueue "enqueue"
while ( is_free( tt ) ) {
if ( th != m_nHead.load(memory_model::memory_order_relaxed) )
goto TryAgain;
- // two consecutive NULL means queue empty
+ // two consecutive nullptr means queue empty
if ( temp == m_nTail.load(memory_model::memory_order_relaxed) )
return true;
temp = ( temp + 1 ) & nModulo;
void operator ()( T * val );
};
\endcode
- You can pass \p disposer by reference using \p boost::ref.
+ You can pass \p disposer by reference using \p std::ref.
The disposer will be called immediately for each item.
*/
template <typename Disposer>
void clear( Disposer f )
{
value_type * pv;
- while ( (pv = pop()) != null_ptr<value_type *>() ) {
- unref(f)( pv );
+ while ( (pv = pop()) != nullptr ) {
+ f( pv );
}
}