From 07b09b4f01527e786dfc83520a9ac996dcc23367 Mon Sep 17 00:00:00 2001 From: gidabite Date: Mon, 24 Dec 2018 16:12:21 +0300 Subject: [PATCH 1/3] Williams lock-free queue (impl by @FatherOctber) --- cds/container/williams_queue.h | 550 ++++++++++++++++++ projects/Win/vc141/cds.vcxproj | 3 +- projects/Win/vc141/cds.vcxproj.filters | 5 +- projects/Win/vc141/gtest-queue.vcxproj | 3 +- .../Win/vc141/gtest-queue.vcxproj.filters | 5 +- test/stress/queue/pop.cpp | 1 + test/stress/queue/push.cpp | 1 + test/stress/queue/push_pop.cpp | 1 + test/stress/queue/queue_type.h | 15 + test/stress/queue/random.cpp | 1 + test/unit/queue/CMakeLists.txt | 3 +- test/unit/queue/williams_queue.cpp | 51 ++ 12 files changed, 634 insertions(+), 5 deletions(-) create mode 100644 cds/container/williams_queue.h create mode 100644 test/unit/queue/williams_queue.cpp diff --git a/cds/container/williams_queue.h b/cds/container/williams_queue.h new file mode 100644 index 000000000..5408b78eb --- /dev/null +++ b/cds/container/williams_queue.h @@ -0,0 +1,550 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_WILLIAMS_QUEUE_H +#define CDSLIB_CONTAINER_WILLIAMS_QUEUE_H + +#include +#include + +#ifdef UNICODE +#define tstring std::wstring +#define tostringstream std::wostringstream +#else +#define tstring std::string +#define tostringstream std::ostringstream +#endif +#define FMTDBGSTR(stream) ((tostringstream&)(tostringstream() << tstring() << stream)).str().c_str() + +#if defined(__LP64__) || defined(_M_IA64) +#else +#define BITS_PTR 24 +#define BITS_COUNTER 8 +#define BITS_INTERNAL_COUNT 30 +#endif + + + +namespace cds { + namespace container { + /// Anthony Williams' queue + /** @ingroup cds_nonintrusive_helper + */ + namespace williams_queue { + /// WilliamsQueue default type traits + struct traits + { + /// Node allocator + typedef CDS_DEFAULT_ALLOCATOR allocator; + + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + typedef atomicity::empty_item_counter item_counter; + }; + + /// Metafunction converting option list to \p williams_queue::traits + /** + Supported \p Options are: + - \p opt::allocator - allocator (like \p std::allocator) used for allocating queue nodes. Default is \ref CDS_DEFAULT_ALLOCATOR + - \p opt::item_counter - the type of item counting feature. Default is \p cds::atomicity::empty_item_counter (item counting disabled) + To enable item counting use \p cds::atomicity::item_counter + + Example: declare \p %WilliamsQueue with item counting + \code + typedef cds::container::WilliamsQueue< Foo, + typename cds::container::williams_queue::make_traits< + cds::opt::item_counter< cds::atomicity::item_counter > > + >::type + > williamsQueue; + \endcode + */ + template + struct make_traits { +#ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type; ///< Metafunction result +#else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + , Options... + >::type type; +#endif + }; + } // namespace williams_queue + + /// Williams lock-free queue + /** @ingroup cds_nonintrusive_queue + The queue uses in-built internal and external reference counting for each node. + The queue does not require any garbage collector. + + Source + - [2012] Anthony Williams "C++ Concurrency in Action" + + Template arguments: + - \p T is a type stored in the queue. + - \p Traits - queue traits, default is \p williams_queue::traits. You can use \p williams_queue::make_traits + metafunction to make your traits or just derive your traits from \p %williams_queue::traits: + \code + struct myTraits: public cds::container::williams_queue::traits { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::WilliamsQueue< Foo, myTraits > myQueue; + + // Equivalent make_traits example: + typedef cds::container::WilliamsQueue< Foo, + typename cds::container::williams_queue::make_traits< + cds::opt::item_counter< cds::atomicity::item_counter > + >::type + > myQueue; + \endcode + */ + template + class WilliamsQueue + { + public: + /// Rebing template arguments + template + struct rebind { + typedef WilliamsQueue< T2, Traits2 > other; ///< Rebinding result + }; + + typedef T value_type; ///< The value type to be stored in the queue + typedef Traits traits; ///< Queue traits + + typedef typename traits::item_counter item_counter; ///< Item counting policy used + + protected: + //@cond + struct node_type; + /// Wraps external count together with the node_type pointer + +#if defined(__LP64__) || defined(_M_IA64) +#define BITS_PTR 48 +#define BITS_COUNTER 16 +#define BITS_INTERNAL_COUNT 62 + const static uintptr_t MASK = ~((uintptr_t)1 << BITS_PTR); + + struct counted_node_ptr + { + uintptr_t ptr_and_external_count; + + int get_external_count(){ + return (int)((uintptr_t)ptr_and_external_count >> BITS_PTR); + + } + void set_external_count(int exCount){ + intptr_t tmpPtr = (ptr_and_external_count << BITS_COUNTER) >> BITS_COUNTER; + ptr_and_external_count = ((uintptr_t)tmpPtr | ((unsigned long long)exCount << BITS_PTR)); + } + node_type* get_ptr(){ + intptr_t tmpPtr = (ptr_and_external_count << BITS_COUNTER) >> BITS_COUNTER; + return (node_type *)tmpPtr; + } + void set_ptr(node_type * ptr){ + uintptr_t tmpExtCount = ptr_and_external_count >> BITS_PTR; + ptr_and_external_count = (((uintptr_t)ptr & MASK) | (tmpExtCount << BITS_PTR)); + } + }; +#else +#define BITS_INTERNAL_COUNT 30 + struct counted_node_ptr + { + int external_count; + node_type * ptr; + + int get_external_count(){ + return external_count; + } + void set_external_count(int exCount){ + external_count = exCount; + } + node_type* get_ptr(){ + return ptr; + } + void set_ptr(node_type * _ptr){ + ptr = _ptr; + } + }; +#endif + /** + Note that we need only 2 bits for the external_counters + because there are at most two such counters. + By using a bit field for this and specifying + internal_count as a 30-bit value, we keep + the total counter size to 32 bits. This gives + us plenty of scope for large internal count values + while ensuring that the whole structure fits + inside a machine word on 32-bit and 64-bit machines. + It�s important to update these counts together as a + single entity in order to avoid race conditions + */ + struct node_counter + { + size_t internal_count : BITS_INTERNAL_COUNT; + size_t external_counters : 2; + }; + + /// Node type + struct node_type + { + atomics::atomic< value_type* > m_value; ///< Value stored in the node + atomics::atomic< node_counter > m_count; ///< Internal and external reference counter + atomics::atomic< counted_node_ptr > m_next; ///< Pointer to the next node in the queue + + node_type() : m_value(nullptr) + { + node_counter new_count; + new_count.internal_count = 0; + new_count.external_counters = 2; + m_count.store(new_count); + + counted_node_ptr new_next = { 0 }; + m_next.store(new_next); + } + }; + + atomics::atomic< counted_node_ptr > m_Head; + atomics::atomic< counted_node_ptr > m_Tail; + + item_counter m_ItemCounter; + //@endcond + + public: + typedef typename traits::allocator::template rebind< node_type >::other allocator_type; ///< Allocator type used for allocate/deallocate the queue nodes + + protected: + //@cond + typedef cds::details::Allocator< node_type, allocator_type > node_allocator; + typedef std::unique_ptr< value_type > scoped_value_ptr; + + static node_type * alloc_node() + { + return node_allocator().New(); + } + static node_type * alloc_node(value_type * const val) + { + node_type * new_node = alloc_node(); + new_node->m_value.store(val, atomics::memory_order_relaxed); + return new_node; + } + static node_type * alloc_node(value_type const& val) + { + scoped_value_ptr new_value(new value_type(val)); + node_type * new_node = alloc_node(new_value.get()); + new_value.release(); + return new_node; + } + template + static node_type * alloc_node_move(Args&&... args) + { + scoped_value_ptr new_value(new value_type(std::forward(args)...)); + node_type * new_node = alloc_node(new_value.get()); + new_value.release(); + return new_node; + } + static void free_node(node_type * p) + { + node_allocator().Delete(p); + } + + static void release_ref(node_type * p) + { + node_counter old_counter = p->m_count.load(atomics::memory_order_relaxed); + node_counter new_counter; + + do + { + new_counter = old_counter; + --new_counter.internal_count; + } while (!p->m_count.compare_exchange_strong( + old_counter, new_counter, + atomics::memory_order_acquire, atomics::memory_order_relaxed)); + + if (!new_counter.internal_count && !new_counter.external_counters) { + p->m_value.exchange(nullptr); + free_node(p); + } + } + static void increase_external_count(atomics::atomic& counter, counted_node_ptr& old_counter) + { + counted_node_ptr new_counter; + + do + { + new_counter = old_counter; + new_counter.set_external_count(new_counter.get_external_count() + 1); + } while (!counter.compare_exchange_strong( + old_counter, new_counter, + atomics::memory_order_acquire, atomics::memory_order_relaxed)); + old_counter.set_external_count(new_counter.get_external_count()); + } + static void free_external_counter(counted_node_ptr& old_node_ptr) + { + node_type * const ptr = old_node_ptr.get_ptr(); + int const count_increase = old_node_ptr.get_external_count() - 2; + //old_node_ptr.set_external_count(old_node_ptr.get_external_count() - 2); + + node_counter old_counter = ptr->m_count.load(atomics::memory_order_relaxed); + node_counter new_counter; + + do + { + new_counter = old_counter; + --new_counter.external_counters; + new_counter.internal_count += count_increase; + } while (!ptr->m_count.compare_exchange_strong( + old_counter, new_counter, + atomics::memory_order_acquire, atomics::memory_order_relaxed)); + + if (!new_counter.internal_count && !new_counter.external_counters) { + free_node(ptr); + } + } + void set_new_tail(counted_node_ptr& old_tail, counted_node_ptr const& new_tail) + { + node_type * const current_tail_ptr = old_tail.get_ptr(); + while (!m_Tail.compare_exchange_weak(old_tail, new_tail) + && old_tail.get_ptr() == current_tail_ptr); + if (old_tail.get_ptr() == current_tail_ptr) + free_external_counter(old_tail); + else + release_ref(current_tail_ptr); + } + bool enqueue_value_ptr(scoped_value_ptr& value_ptr) + { + counted_node_ptr new_next; + new_next.set_ptr(alloc_node()); + new_next.set_external_count(1); + + counted_node_ptr old_tail = m_Tail.load(); + + while (true) + { + increase_external_count(m_Tail, old_tail); + value_type * old_value = nullptr; + node_type * n = old_tail.get_ptr(); + if (n->m_value.compare_exchange_strong(old_value, value_ptr.get())) + { + + counted_node_ptr old_next = { 0 }; + if (!old_tail.get_ptr()->m_next.compare_exchange_strong(old_next, new_next)) + { + free_node(new_next.get_ptr()); + new_next = old_next; + } + set_new_tail(old_tail, new_next); + value_ptr.release(); + break; + } + else + { + counted_node_ptr old_next = { 0 }; + if (old_tail.get_ptr()->m_next.compare_exchange_strong(old_next, new_next)) + { + old_next = new_next; + new_next.set_ptr(alloc_node()); + } + set_new_tail(old_tail, old_next); + } + } + + ++m_ItemCounter; + return true; + } + struct node_disposer + { + void operator()(node_type * p) + { + free_node(p); + } + }; + //@endcond + + public: + /// Initializes empty queue + WilliamsQueue() + { + counted_node_ptr dummy_node; + dummy_node.set_ptr(alloc_node()); + dummy_node.set_external_count(1); + + m_Head.store(dummy_node); + m_Tail.store(dummy_node); + } + + /// Destructor clears the queue + ~WilliamsQueue() + { + clear(); + assert(m_Head.load().get_ptr() == m_Tail.load().get_ptr()); + free_node(m_Head.load().get_ptr()); + } + + //@cond + WilliamsQueue(const WilliamsQueue& other) = delete; + WilliamsQueue& operator=(const WilliamsQueue& other) = delete; + //@endcond + + /// Enqueues \p val value into the queue. Always returns \a true + bool enqueue(value_type const& val) + { + scoped_value_ptr new_value_ptr(new value_type(val)); + return enqueue_value_ptr(new_value_ptr); + } + + /// Enqueues \p data, move semantics + bool enqueue(value_type&& data) + { + scoped_value_ptr new_value_ptr(new value_type(std::forward(data))); + return enqueue_value_ptr(new_value_ptr); + } + + /// Enqueues data to the queue using a functor + /** + \p Func is a functor called to create node. + The functor \p f takes one argument - a reference to a new node of type \ref value_type : + \code + cds::container::WilliamsQueue< Foo > myQueue; + Bar bar; + myQueue.enqueue_with( [&bar]( Foo& dest ) { dest = bar; } ); + \endcode + */ + template + bool enqueue_with(Func f) + { + value_type val; + f(val); + return enqueue(val); + } + + /// Enqueues data of type \ref value_type constructed from std::forward(args)... + template + bool emplace(Args&&... args) + { + value_type val(std::forward(args)...); + return enqueue(val); + } + + /// Synonym for \p enqueue() function + bool push(value_type const& val) + { + return enqueue(val); + } + + /// Synonym for \p enqueue( value_type&& ) function + bool push(value_type&& val) + { + return enqueue(std::move(val)); + } + + /// Synonym for \p enqueue_with() function + template + bool push_with(Func f) + { + return enqueue_with(f); + } + + /// Dequeues a value from the queue + /** + If queue is not empty, the function returns \p true, \p dest contains copy of + dequeued value. The assignment operator for type \ref value_type is invoked. + If queue is empty, the function returns \p false, \p dest is unchanged. + */ + bool dequeue(value_type& dest) + { + return dequeue_with([&dest](value_type& src) { dest = src; }); + } + + /// Dequeues a value using a functor + /** + \p Func is a functor called to copy dequeued value. + The functor takes one argument - a reference to removed node: + \code + cds:container::WilliamsQueue< Foo > myQueue; + Bar bar; + myQueue.dequeue_with( [&bar]( Foo& src ) { bar = std::move( src );}); + \endcode + The functor is called only if the queue is not empty. + */ + template + bool dequeue_with(Func f) + { + counted_node_ptr old_head = m_Head.load(atomics::memory_order_relaxed); + + while (true) + { + increase_external_count(m_Head, old_head); + node_type * const p = old_head.get_ptr(); + if (p == m_Tail.load().get_ptr()) + { + release_ref(p); + return false; + } + counted_node_ptr next = p->m_next.load(); + if (m_Head.compare_exchange_strong(old_head, next)) + { + scoped_value_ptr res(p->m_value.load()); + free_external_counter(old_head); + --m_ItemCounter; + f(*res.get()); + //std::cout << old_head.get_external_count() << std::endl; + //old_head.get_ptr()->m_count.load().external_counters; + //old_head.get_ptr()->m_count.load().internal_count; + return true; + } + release_ref(p); + } + } + + /// Synonym for \p dequeue() function + bool pop(value_type& dest) + { + return dequeue(dest); + } + + /// Synonym for \p dequeue_with() function + template + bool pop_with(Func f) + { + return dequeue_with(f); + } + + /// Clear the queue + /** + The function repeatedly calls \ref dequeue until it returns \a false. + */ + void clear() + { + value_type v; + while (dequeue(v)); + } + + /// Checks whether the queue is empty + bool empty() const + { + return m_Head.load().get_ptr() == m_Tail.load().get_ptr(); + } + + /// Returns queue's item count + /** + The value returned depends on \p williams_queue::traits::item_counter. + For \p atomicity::empty_item_counter, this function always returns 0. + + @note Even if you use real item counter and it returns 0, this fact is not + mean that the queue is empty. To check queue emptyness use \p empty() instead. + */ + size_t size() const + { + return m_ItemCounter.value(); + } + + //@cond + /// The class has no internal statistics. For test consistency only + std::nullptr_t statistics() const + { + return nullptr; + } + //@endcond + }; + + } +} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_WILLIAMS_QUEUE_H \ No newline at end of file diff --git a/projects/Win/vc141/cds.vcxproj b/projects/Win/vc141/cds.vcxproj index 9b904397c..0d4ea052f 100644 --- a/projects/Win/vc141/cds.vcxproj +++ b/projects/Win/vc141/cds.vcxproj @@ -1140,6 +1140,7 @@ + @@ -1374,4 +1375,4 @@ - \ No newline at end of file + diff --git a/projects/Win/vc141/cds.vcxproj.filters b/projects/Win/vc141/cds.vcxproj.filters index d9c34bb92..68054aead 100644 --- a/projects/Win/vc141/cds.vcxproj.filters +++ b/projects/Win/vc141/cds.vcxproj.filters @@ -1258,5 +1258,8 @@ Header Files\cds\details + + Header Files\cds\container + - \ No newline at end of file + diff --git a/projects/Win/vc141/gtest-queue.vcxproj b/projects/Win/vc141/gtest-queue.vcxproj index 69fbcce73..c244b041d 100644 --- a/projects/Win/vc141/gtest-queue.vcxproj +++ b/projects/Win/vc141/gtest-queue.vcxproj @@ -106,6 +106,7 @@ + @@ -726,4 +727,4 @@ - \ No newline at end of file + diff --git a/projects/Win/vc141/gtest-queue.vcxproj.filters b/projects/Win/vc141/gtest-queue.vcxproj.filters index 692356f3e..6adf090e9 100644 --- a/projects/Win/vc141/gtest-queue.vcxproj.filters +++ b/projects/Win/vc141/gtest-queue.vcxproj.filters @@ -89,6 +89,9 @@ Source Files + + Source Files + Source Files @@ -113,4 +116,4 @@ Header Files - \ No newline at end of file + diff --git a/test/stress/queue/pop.cpp b/test/stress/queue/pop.cpp index 5dbb72cd5..be32c1e08 100644 --- a/test/stress/queue/pop.cpp +++ b/test/stress/queue/pop.cpp @@ -149,6 +149,7 @@ namespace { CDSSTRESS_FCDeque( queue_pop ) CDSSTRESS_RWQueue( queue_pop ) CDSSTRESS_StdQueue( queue_pop ) + CDSSTRESS_WilliamsQueue( queue_pop ) #undef CDSSTRESS_Queue_F #define CDSSTRESS_Queue_F( test_fixture, type_name ) \ diff --git a/test/stress/queue/push.cpp b/test/stress/queue/push.cpp index c2e80bba2..5d3a972d9 100644 --- a/test/stress/queue/push.cpp +++ b/test/stress/queue/push.cpp @@ -152,6 +152,7 @@ namespace { CDSSTRESS_FCDeque( queue_push ) CDSSTRESS_RWQueue( queue_push ) CDSSTRESS_StdQueue( queue_push ) + CDSSTRESS_WilliamsQueue( queue_push ) #undef CDSSTRESS_Queue_F #define CDSSTRESS_Queue_F( test_fixture, type_name ) \ diff --git a/test/stress/queue/push_pop.cpp b/test/stress/queue/push_pop.cpp index 4803f5238..f683703d0 100644 --- a/test/stress/queue/push_pop.cpp +++ b/test/stress/queue/push_pop.cpp @@ -329,6 +329,7 @@ namespace { CDSSTRESS_FCDeque_HeavyValue( fc_with_heavy_value ) CDSSTRESS_RWQueue( simple_queue_push_pop ) CDSSTRESS_StdQueue( simple_queue_push_pop ) + CDSSTRESS_WilliamsQueue( simple_queue_push_pop ) #undef CDSSTRESS_Queue_F #define CDSSTRESS_Queue_F( test_fixture, type_name ) \ diff --git a/test/stress/queue/queue_type.h b/test/stress/queue/queue_type.h index 4dd0f454b..dc170bf83 100644 --- a/test/stress/queue/queue_type.h +++ b/test/stress/queue/queue_type.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -398,6 +399,16 @@ namespace fc_details{ {}; typedef cds::container::RWQueue< Value, traits_RWQueue_mutex > RWQueue_mutex; + // WilliamsQueue + typedef cds::container::WilliamsQueue< Value > WilliamsQueue_default; + + struct traits_WilliamsQueue_ic : public cds::container::williams_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::WilliamsQueue< Value, traits_WilliamsQueue_ic > WilliamsQueue_ic; + + // FCQueue struct traits_FCQueue_stat: public cds::container::fcqueue::make_traits< @@ -836,6 +847,10 @@ namespace cds_test { CDSSTRESS_Queue_F( test_fixture, RWQueue_mutex ) \ CDSSTRESS_RWQueue_1( test_fixture ) +#define CDSSTRESS_WilliamsQueue( test_fixture ) \ + CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_default, 0 ) \ + CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_ic, 1 ) + #define CDSSTRESS_SegmentedQueue( test_fixture ) \ CDSSTRESS_Queue_F( test_fixture, SegmentedQueue_HP_spin ) \ CDSSTRESS_Queue_F( test_fixture, SegmentedQueue_HP_spin_padding ) \ diff --git a/test/stress/queue/random.cpp b/test/stress/queue/random.cpp index 357737d9e..51cfeb098 100644 --- a/test/stress/queue/random.cpp +++ b/test/stress/queue/random.cpp @@ -216,6 +216,7 @@ namespace { CDSSTRESS_FCDeque( queue_random ) CDSSTRESS_RWQueue( queue_random ) CDSSTRESS_StdQueue( queue_random ) + CDSSTRESS_WilliamsQueue( queue_random ) #undef CDSSTRESS_Queue_F #define CDSSTRESS_Queue_F( test_fixture, type_name ) \ diff --git a/test/unit/queue/CMakeLists.txt b/test/unit/queue/CMakeLists.txt index aea3e81f4..d8811b9e3 100644 --- a/test/unit/queue/CMakeLists.txt +++ b/test/unit/queue/CMakeLists.txt @@ -28,6 +28,7 @@ set(CDSGTEST_QUEUE_SOURCES intrusive_segmented_queue_hp.cpp intrusive_segmented_queue_dhp.cpp intrusive_vyukov_queue.cpp + williams_queue.cpp ) include_directories( @@ -37,4 +38,4 @@ include_directories( add_executable(${PACKAGE_NAME} ${CDSGTEST_QUEUE_SOURCES}) target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES}) -add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) \ No newline at end of file +add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) diff --git a/test/unit/queue/williams_queue.cpp b/test/unit/queue/williams_queue.cpp new file mode 100644 index 000000000..084b9f744 --- /dev/null +++ b/test/unit/queue/williams_queue.cpp @@ -0,0 +1,51 @@ +#include "test_generic_queue.h" + + #include + + namespace { + namespace cc = cds::container; + + class WilliamsQueue : public cds_test::generic_queue + {}; + + TEST_F(WilliamsQueue, defaulted) + { + typedef cds::container::WilliamsQueue< int > test_queue; + + test_queue q; + test(q); + } + + TEST_F(WilliamsQueue, item_counting) + { + typedef cds::container::WilliamsQueue< int, + typename cds::container::williams_queue::make_traits < + cds::opt::item_counter< cds::atomicity::item_counter > + > ::type + > test_queue; + + test_queue q; + test(q); + } + + TEST_F(WilliamsQueue, move) + { + typedef cds::container::WilliamsQueue< std::string > test_queue; + + test_queue q; + test_string(q); + } + + TEST_F(WilliamsQueue, move_item_counting) + { + struct traits : public cc::williams_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::WilliamsQueue< std::string, traits > test_queue; + + test_queue q; + test_string(q); + } + + } // namespace From 7113c2b8f5ef94572415b67bdc1dd2210ba3767c Mon Sep 17 00:00:00 2001 From: gidabite Date: Thu, 27 Dec 2018 22:28:56 +0300 Subject: [PATCH 2/3] fix stress tests --- test/stress/queue/queue_type.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stress/queue/queue_type.h b/test/stress/queue/queue_type.h index dc170bf83..ef1f27992 100644 --- a/test/stress/queue/queue_type.h +++ b/test/stress/queue/queue_type.h @@ -848,8 +848,8 @@ namespace cds_test { CDSSTRESS_RWQueue_1( test_fixture ) #define CDSSTRESS_WilliamsQueue( test_fixture ) \ - CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_default, 0 ) \ - CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_ic, 1 ) + CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_default) \ + CDSSTRESS_Queue_F( test_fixture, WilliamsQueue_ic) #define CDSSTRESS_SegmentedQueue( test_fixture ) \ CDSSTRESS_Queue_F( test_fixture, SegmentedQueue_HP_spin ) \ From 57c49e211c1c53594e136f646a136ffa21809645 Mon Sep 17 00:00:00 2001 From: gidabite Date: Sat, 29 Dec 2018 11:59:26 +0300 Subject: [PATCH 3/3] delete comments --- cds/container/williams_queue.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/cds/container/williams_queue.h b/cds/container/williams_queue.h index 5408b78eb..d6de6e819 100644 --- a/cds/container/williams_queue.h +++ b/cds/container/williams_queue.h @@ -15,14 +15,6 @@ #endif #define FMTDBGSTR(stream) ((tostringstream&)(tostringstream() << tstring() << stream)).str().c_str() -#if defined(__LP64__) || defined(_M_IA64) -#else -#define BITS_PTR 24 -#define BITS_COUNTER 8 -#define BITS_INTERNAL_COUNT 30 -#endif - - namespace cds { namespace container { @@ -279,7 +271,6 @@ namespace cds { { node_type * const ptr = old_node_ptr.get_ptr(); int const count_increase = old_node_ptr.get_external_count() - 2; - //old_node_ptr.set_external_count(old_node_ptr.get_external_count() - 2); node_counter old_counter = ptr->m_count.load(atomics::memory_order_relaxed); node_counter new_counter; @@ -484,9 +475,6 @@ namespace cds { free_external_counter(old_head); --m_ItemCounter; f(*res.get()); - //std::cout << old_head.get_external_count() << std::endl; - //old_head.get_ptr()->m_count.load().external_counters; - //old_head.get_ptr()->m_count.load().internal_count; return true; } release_ref(p); @@ -547,4 +535,4 @@ namespace cds { } } // namespace cds::container -#endif // #ifndef CDSLIB_CONTAINER_WILLIAMS_QUEUE_H \ No newline at end of file +#endif // #ifndef CDSLIB_CONTAINER_WILLIAMS_QUEUE_H