Moved queue unit tests to gtest framework
authorkhizmax <libcds.dev@gmail.com>
Wed, 3 Feb 2016 18:20:56 +0000 (21:20 +0300)
committerkhizmax <libcds.dev@gmail.com>
Wed, 3 Feb 2016 18:20:56 +0000 (21:20 +0300)
19 files changed:
CMakeLists.txt
cds/intrusive/fcqueue.h
cds/intrusive/segmented_queue.h
projects/Win/vc14/gtest-queue.vcxproj
projects/Win/vc14/gtest-queue.vcxproj.filters
test/unit/queue/CMakeLists.txt
test/unit/queue/intrusive_basket_queue_dhp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_basket_queue_hp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_fcqueue.cpp [new file with mode: 0644]
test/unit/queue/intrusive_moirqueue_dhp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_moirqueue_hp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_msqueue_dhp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_msqueue_hp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_optqueue_dhp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_optqueue_hp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_segmented_queue_dhp.cpp [new file with mode: 0644]
test/unit/queue/intrusive_segmented_queue_hp.cpp [new file with mode: 0644]
test/unit/queue/test_intrusive_msqueue.h [new file with mode: 0644]
test/unit/queue/test_intrusive_segmented_queue.h [new file with mode: 0644]

index c8d253ef8dd276f8ff28d19f2826bd9b985352af..9b6f2bb5549bdfde3ba91f98d3e107ff058fd0db 100644 (file)
@@ -39,9 +39,9 @@ set(CDS_STATIC_LIBRARY ${PROJECT_NAME}-s)
 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
-if(CDS_BIN_ROOT)
-    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/${CDS_BIN_ROOT})
-    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/${CDS_BIN_ROOT})
+if(CDS_BIN_DIR)
+    set(EXECUTABLE_OUTPUT_PATH ${CDS_BIN_DIR})
+    set(LIBRARY_OUTPUT_PATH ${CDS_BIN_DIR})
 else()
     set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
     set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
index c369c371f655f25b289498042327ff8435ce70cf..dae8166584fe2295628fe1db996fe7acc5dae597 100644 (file)
@@ -83,7 +83,7 @@ namespace cds { namespace intrusive {
             \p Options are:
             - \p opt::lock_type - mutex type, default is \p cds::sync::spin
             - \p opt::back_off - back-off strategy, defalt is \p cds::backoff::Default
-            - \p opt::disposer - the functor used for dispose removed items. Default is \p opt::intrusive::v::empty_disposer.
+            - \p opt::disposer - the functor used to dispose removed items. Default is \p opt::intrusive::v::empty_disposer.
                 This option is used only in \p FCQueue::clear() function.
             - \p opt::allocator - allocator type, default is \ref CDS_DEFAULT_ALLOCATOR
             - \p opt::stat - internal statistics, possible type: \p fcqueue::stat, \p fcqueue::empty_stat (the default)
index dfb93882d32f6dd7b313ba87c10d91b68b49d8b7..83cfb1da6c5f51f1ef43283ae006219d59a9e5aa 100644 (file)
@@ -152,7 +152,7 @@ namespace cds { namespace intrusive {
             all other \p %segmented_queue::traits members left unchanged.
 
             \p Options are:
-            - \p opt::disposer - the functor used for dispose removed items.
+            - \p opt::disposer - the functor used to dispose removed items.
             - \p opt::stat - internal statistics, possible type: \p segmented_queue::stat, \p segmented_queue::empty_stat (the default)
             - \p opt::item_counter - item counting feature. Note that \p atomicity::empty_item_counetr is not suitable
                 for segmented queue.
@@ -599,7 +599,7 @@ namespace cds { namespace intrusive {
 
         /// Clear the queue
         /**
-            The function repeatedly calls \ref dequeue until it returns \p nullptr.
+            The function repeatedly calls \p dequeue() until it returns \p nullptr.
             The disposer specified in \p Traits template argument is called for each removed item.
         */
         void clear()
index edb20c69db93b559329d51f4c696ec5e77b07b6c..713f1c8acb27aab8722e2c4769f12bb192524269 100644 (file)
     <ClCompile Include="..\..\..\test\unit\queue\basket_queue_dhp.cpp" />\r
     <ClCompile Include="..\..\..\test\unit\queue\basket_queue_hp.cpp" />\r
     <ClCompile Include="..\..\..\test\unit\queue\fcqueue.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_basket_queue_dhp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_basket_queue_hp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_fcqueue.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_moirqueue_dhp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_moirqueue_hp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_msqueue_dhp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_msqueue_hp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_optqueue_dhp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_optqueue_hp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_segmented_queue_dhp.cpp" />\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_segmented_queue_hp.cpp" />\r
     <ClCompile Include="..\..\..\test\unit\queue\moirqueue_dhp.cpp" />\r
     <ClCompile Include="..\..\..\test\unit\queue\moirqueue_hp.cpp" />\r
     <ClCompile Include="..\..\..\test\unit\queue\msqueue_dhp.cpp" />\r
@@ -48,6 +59,8 @@
   <ItemGroup>\r
     <ClInclude Include="..\..\..\test\unit\queue\test_bounded_queue.h" />\r
     <ClInclude Include="..\..\..\test\unit\queue\test_generic_queue.h" />\r
+    <ClInclude Include="..\..\..\test\unit\queue\test_intrusive_msqueue.h" />\r
+    <ClInclude Include="..\..\..\test\unit\queue\test_intrusive_segmented_queue.h" />\r
     <ClInclude Include="..\..\..\test\unit\queue\test_segmented_queue.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
index 2158a14d7bfe75805dd3c499ca7e6dd6161fb41c..723ac426e7b431aee900e66ff9363ef04980385a 100644 (file)
     <ClCompile Include="..\..\..\test\unit\queue\tsigas_queue.cpp">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_msqueue_hp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_msqueue_dhp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_moirqueue_dhp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_moirqueue_hp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_basket_queue_dhp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_basket_queue_hp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_optqueue_dhp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_optqueue_hp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_fcqueue.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_segmented_queue_hp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\test\unit\queue\intrusive_segmented_queue_dhp.cpp">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\..\..\test\unit\queue\test_generic_queue.h">\r
     <ClInclude Include="..\..\..\test\unit\queue\test_bounded_queue.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\test\unit\queue\test_intrusive_msqueue.h">\r
+      <Filter>Header Files</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\test\unit\queue\test_intrusive_segmented_queue.h">\r
+      <Filter>Header Files</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 163a108266a2f6d834e09e4ac45bb8fed25d90a6..62f6c2c09e187e0b6034bea5599d176113ff7d18 100644 (file)
@@ -16,6 +16,17 @@ set(CDSGTEST_QUEUE_SOURCES
     segmented_queue_dhp.cpp
     tsigas_queue.cpp
     vyukov_mpmc_queue.cpp
+    intrusive_basket_queue_hp.cpp
+    intrusive_basket_queue_dhp.cpp
+    intrusive_fcqueue.cpp
+    intrusive_msqueue_hp.cpp
+    intrusive_msqueue_dhp.cpp
+    intrusive_moirqueue_hp.cpp
+    intrusive_moirqueue_dhp.cpp
+    intrusive_optqueue_hp.cpp
+    intrusive_optqueue_dhp.cpp
+    intrusive_segmented_queue_hp.cpp
+    intrusive_segmented_queue_dhp.cpp
 )
 
 include_directories(
diff --git a/test/unit/queue/intrusive_basket_queue_dhp.cpp b/test/unit/queue/intrusive_basket_queue_dhp.cpp
new file mode 100644 (file)
index 0000000..67f169b
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/basket_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::DHP gc_type;
+
+
+    class IntrusiveBasketQueue_DHP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::basket_queue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::basket_queue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::BasketQueue< gc_type, base_item_type,
+                typename ci::basket_queue::make_traits<
+                    ci::opt::hook< ci::basket_queue::base_hook< ci::opt::gc<gc_type>>>
+                >::type
+            > queue_type;
+
+            cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::dhp::GarbageCollector::Destruct();
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveBasketQueue_DHP, base_hook )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::basket_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_DHP, base_item_counting )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::basket_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_DHP, base_stat )
+    {
+        struct traits : public ci::basket_queue::traits
+        {
+            typedef ci::basket_queue::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::basket_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_DHP, member_hook )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, member_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::basket_queue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_DHP, member_hook_stat )
+    {
+        struct traits : public ci::basket_queue::traits
+        {
+            typedef ci::basket_queue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::basket_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::BasketQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_basket_queue_hp.cpp b/test/unit/queue/intrusive_basket_queue_hp.cpp
new file mode 100644 (file)
index 0000000..2cba55e
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/hp.h>
+#include <cds/intrusive/basket_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::HP gc_type;
+
+
+    class IntrusiveBasketQueue_HP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::basket_queue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::basket_queue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::BasketQueue< gc_type, base_item_type > queue_type;
+
+            cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct( true );
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveBasketQueue_HP, defaulted )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_HP, base_hook )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::basket_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_HP, base_item_counting )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::basket_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_HP, base_stat )
+    {
+        struct traits : public ci::basket_queue::traits
+        {
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::basket_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::BasketQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_HP, member_hook )
+    {
+        typedef cds::intrusive::BasketQueue< gc_type, member_item_type,
+            typename ci::basket_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::basket_queue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveBasketQueue_HP, member_hook_stat )
+    {
+        struct traits : public ci::basket_queue::traits
+        {
+            typedef ci::basket_queue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::basket_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::BasketQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_fcqueue.cpp b/test/unit/queue/intrusive_fcqueue.cpp
new file mode 100644 (file)
index 0000000..9a5fc06
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include <gtest/gtest.h>
+#include <cds/intrusive/fcqueue.h>
+
+#include <vector>
+#include <boost/intrusive/slist.hpp>
+
+namespace {
+
+    class IntrusiveFCQueue : public ::testing::Test
+    {
+    protected:
+        template <typename Hook>
+        struct base_hook_item : public Hook
+        {
+            int nVal;
+            int nDisposeCount;
+
+            base_hook_item()
+                : nDisposeCount( 0 )
+            {}
+        };
+
+        template <typename Hook>
+        struct member_hook_item
+        {
+            int nVal;
+            int nDisposeCount;
+            Hook hMember;
+
+            member_hook_item()
+                : nDisposeCount( 0 )
+            {}
+        };
+
+        struct disposer
+        {
+            template <typename T>
+            void operator ()( T * p )
+            {
+                ++p->nDisposeCount;
+            }
+        };
+
+        template <typename Queue>
+        void test( Queue& q )
+        {
+            typedef typename Queue::value_type value_type;
+
+            size_t const nSize = 100;
+            value_type * pv;
+            std::vector<value_type> arr;
+            arr.resize( nSize );
+            for ( size_t i = 0; i < nSize; ++i )
+                arr[i].nVal = static_cast<int>(i);
+
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            // pop from empty queue
+            pv = q.pop();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            pv = q.dequeue();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            // push/pop test
+            for ( size_t i = 0; i < nSize; ++i ) {
+                if ( i & 1 )
+                    q.push( arr[i] );
+                else
+                    q.enqueue( arr[i] );
+                ASSERT_FALSE( q.empty() );
+                ASSERT_EQ( q.size(), i + 1 );
+            }
+
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_FALSE( q.empty() );
+                ASSERT_EQ( q.size(), nSize - i );
+                if ( i & 1 )
+                    pv = q.pop();
+                else
+                    pv = q.dequeue();
+                ASSERT_FALSE( pv == nullptr );
+                ASSERT_EQ( pv->nVal, static_cast<int>(i) );
+            }
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            // pop() doesn't call disposer
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 0 );
+            }
+
+            // clear with disposer
+            for ( size_t i = 0; i < nSize; ++i )
+                q.push( arr[i] );
+
+            ASSERT_FALSE( q.empty() );
+            ASSERT_EQ( q.size(), nSize );
+
+            q.clear( true );
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 1 );
+            }
+
+            // clear without disposer
+            for ( size_t i = 0; i < nSize; ++i )
+                q.push( arr[i] );
+
+            q.clear();
+            ASSERT_TRUE( q.empty() );
+            ASSERT_EQ( q.size(), 0 );
+
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 1 );
+            }
+        }
+    };
+
+    TEST_F( IntrusiveFCQueue, base )
+    {
+        typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, base_mutex )
+    {
+        typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
+        struct traits : public cds::intrusive::fcqueue::traits
+        {
+            typedef IntrusiveFCQueue::disposer disposer;
+            typedef std::mutex lock_type;
+            typedef cds::intrusive::fcqueue::stat<> stat;
+        };
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >, traits > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, base_elimination )
+    {
+        typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
+        struct traits : public
+            cds::intrusive::fcqueue::make_traits <
+                cds::intrusive::opt::disposer< disposer >
+                , cds::opt::enable_elimination < true >
+            > ::type
+        {};
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >, traits > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, member )
+    {
+        typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
+        typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
+
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, member_mutex )
+    {
+        typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
+        typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
+
+        struct traits : public cds::intrusive::fcqueue::traits
+        {
+            typedef IntrusiveFCQueue::disposer disposer;
+            typedef std::mutex lock_type;
+            typedef cds::intrusive::fcqueue::stat<> stat;
+        };
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >, traits > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, member_elimination )
+    {
+        typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
+        typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
+
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+                ,cds::opt::enable_elimination< true >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, slist_base )
+    {
+        typedef base_hook_item< boost::intrusive::slist_base_hook<>> value_type;
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::slist< value_type, boost::intrusive::cache_last< true >>,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, slist_base_elimination )
+    {
+        typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
+        struct traits : public
+            cds::intrusive::fcqueue::make_traits <
+                cds::intrusive::opt::disposer< disposer >
+                , cds::opt::enable_elimination < true >
+                , cds::opt::lock_type< std::mutex >
+            > ::type
+        {};
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::slist< value_type, boost::intrusive::cache_last< true >>, traits > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, slist_member )
+    {
+        typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
+        typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
+
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::slist< value_type, member_option, boost::intrusive::cache_last< true >>,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, slist_member_elimination )
+    {
+        typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
+        typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
+
+        typedef cds::intrusive::FCQueue< value_type, boost::intrusive::slist< value_type, member_option, boost::intrusive::cache_last< true >>,
+            cds::intrusive::fcqueue::make_traits<
+                cds::intrusive::opt::disposer< disposer >
+                ,cds::opt::enable_elimination< true >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+} // namepace
diff --git a/test/unit/queue/intrusive_moirqueue_dhp.cpp b/test/unit/queue/intrusive_moirqueue_dhp.cpp
new file mode 100644 (file)
index 0000000..8f52f4c
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/moir_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::DHP gc_type;
+
+
+    class IntrusiveMoirQueue_DHP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::msqueue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::msqueue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::MoirQueue< gc_type, base_item_type,
+                typename ci::msqueue::make_traits<
+                    ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+                >::type
+            > queue_type;
+
+            cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::dhp::GarbageCollector::Destruct();
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveMoirQueue_DHP, base_hook )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_DHP, base_item_counting )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_DHP, base_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_DHP, member_hook )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, member_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_DHP, member_hook_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MoirQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_moirqueue_hp.cpp b/test/unit/queue/intrusive_moirqueue_hp.cpp
new file mode 100644 (file)
index 0000000..c172a7f
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/hp.h>
+#include <cds/intrusive/moir_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::HP gc_type;
+
+
+    class IntrusiveMoirQueue_HP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::msqueue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::msqueue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::MoirQueue< gc_type, base_item_type > queue_type;
+
+            cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct( true );
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveMoirQueue_HP, defaulted )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_HP, base_hook )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_HP, base_item_counting )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_HP, base_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MoirQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_HP, member_hook )
+    {
+        typedef cds::intrusive::MoirQueue< gc_type, member_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMoirQueue_HP, member_hook_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MoirQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_msqueue_dhp.cpp b/test/unit/queue/intrusive_msqueue_dhp.cpp
new file mode 100644 (file)
index 0000000..67327a3
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/msqueue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::DHP gc_type;
+
+
+    class IntrusiveMSQueue_DHP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::msqueue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::msqueue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::MSQueue< gc_type, base_item_type,
+                typename ci::msqueue::make_traits<
+                    ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+                >::type
+            > queue_type;
+
+            cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::dhp::GarbageCollector::Destruct();
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveMSQueue_DHP, base_hook )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_DHP, base_item_counting )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_DHP, base_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_DHP, member_hook )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, member_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_DHP, member_hook_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MSQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_msqueue_hp.cpp b/test/unit/queue/intrusive_msqueue_hp.cpp
new file mode 100644 (file)
index 0000000..7a81e66
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/hp.h>
+#include <cds/intrusive/msqueue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::HP gc_type;
+
+
+    class IntrusiveMSQueue_HP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::msqueue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::msqueue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::MSQueue< gc_type, base_item_type > queue_type;
+
+            cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct( true );
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveMSQueue_HP, defaulted )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_HP, base_hook )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_HP, base_item_counting )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::msqueue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_HP, base_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MSQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_HP, member_hook )
+    {
+        typedef cds::intrusive::MSQueue< gc_type, member_item_type,
+            typename ci::msqueue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::msqueue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveMSQueue_HP, member_hook_stat )
+    {
+        struct traits : public ci::msqueue::traits
+        {
+            typedef ci::msqueue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::msqueue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::MSQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_optqueue_dhp.cpp b/test/unit/queue/intrusive_optqueue_dhp.cpp
new file mode 100644 (file)
index 0000000..83d526f
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/optimistic_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::DHP gc_type;
+
+
+    class IntrusiveOptQueue_DHP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::optimistic_queue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::optimistic_queue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::OptimisticQueue< gc_type, base_item_type,
+                typename ci::optimistic_queue::make_traits<
+                    ci::opt::hook< ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>>>
+                >::type
+            > queue_type;
+
+            cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::dhp::GarbageCollector::Destruct();
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveOptQueue_DHP, base_hook )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_DHP, base_item_counting )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_DHP, base_stat )
+    {
+        struct traits : public ci::optimistic_queue::traits
+        {
+            typedef ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::optimistic_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_DHP, member_hook )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, member_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::optimistic_queue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_DHP, member_hook_stat )
+    {
+        struct traits : public ci::optimistic_queue::traits
+        {
+            typedef ci::optimistic_queue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::optimistic_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::OptimisticQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_optqueue_hp.cpp b/test/unit/queue/intrusive_optqueue_hp.cpp
new file mode 100644 (file)
index 0000000..4b1253f
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_msqueue.h"
+
+#include <cds/gc/hp.h>
+#include <cds/intrusive/optimistic_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::HP gc_type;
+
+
+    class IntrusiveOptQueue_HP : public cds_test::intrusive_msqueue
+    {
+        typedef cds_test::intrusive_msqueue base_class;
+
+    protected:
+        typedef typename base_class::base_hook_item< ci::optimistic_queue::node<gc_type>> base_item_type;
+        typedef typename base_class::member_hook_item< ci::optimistic_queue::node<gc_type>> member_item_type;
+
+        void SetUp()
+        {
+            typedef ci::OptimisticQueue< gc_type, base_item_type > queue_type;
+
+            cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct( true );
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size() - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 );
+            }
+            ASSERT_EQ( arr.back().nDisposeCount, 1 );
+        }
+    };
+
+    TEST_F( IntrusiveOptQueue_HP, defaulted )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_HP, base_hook )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_HP, base_item_counting )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                , cds::opt::item_counter< cds::atomicity::item_counter >
+                , ci::opt::hook< ci::optimistic_queue::base_hook< ci::opt::gc<gc_type>>>
+            >::type
+        > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_HP, base_stat )
+    {
+        struct traits : public ci::optimistic_queue::traits
+        {
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::optimistic_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::OptimisticQueue< gc_type, base_item_type, traits > test_queue;
+
+        std::vector<base_item_type> arr;
+        arr.resize(100);
+        {
+            test_queue q;
+            test(q, arr);
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_HP, member_hook )
+    {
+        typedef cds::intrusive::OptimisticQueue< gc_type, member_item_type,
+            typename ci::optimistic_queue::make_traits<
+                ci::opt::disposer< mock_disposer >
+                ,ci::opt::hook< ci::optimistic_queue::member_hook<
+                    offsetof( member_item_type, hMember ),
+                    ci::opt::gc<gc_type>
+                >>
+            >::type
+        > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveOptQueue_HP, member_hook_stat )
+    {
+        struct traits : public ci::optimistic_queue::traits
+        {
+            typedef ci::optimistic_queue::member_hook<
+                offsetof( member_item_type, hMember ),
+                ci::opt::gc<gc_type>
+            > hook;
+            typedef mock_disposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            typedef ci::optimistic_queue::stat<> stat;
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::OptimisticQueue< gc_type, member_item_type, traits > test_queue;
+
+        std::vector<member_item_type> arr;
+        arr.resize( 100 );
+        {
+            test_queue q;
+            test( q, arr );
+        }
+        gc_type::scan();
+        check_array( arr );
+    }
+
+} // namespace
+
diff --git a/test/unit/queue/intrusive_segmented_queue_dhp.cpp b/test/unit/queue/intrusive_segmented_queue_dhp.cpp
new file mode 100644 (file)
index 0000000..f910f98
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_segmented_queue.h"
+
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/segmented_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::DHP gc_type;
+
+    class IntrusiveSegmentedQueue_DHP : public cds_test::intrusive_segmented_queue
+    {
+        typedef cds_test::intrusive_segmented_queue base_class;
+
+    protected:
+        static const size_t c_QuasiFactor = 15;
+
+        void SetUp()
+        {
+            typedef ci::SegmentedQueue< gc_type, item > queue_type;
+
+            cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct();
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size(); ++i ) {
+                EXPECT_EQ( arr[i].nDisposeCount, 2 );
+                EXPECT_EQ( arr[i].nDispose2Count, 1 );
+            }
+        }
+    };
+
+    TEST_F( IntrusiveSegmentedQueue_DHP, defaulted )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_DHP, mutex )
+    {
+        struct queue_traits : public
+            cds::intrusive::segmented_queue::make_traits <
+                cds::intrusive::opt::disposer< Disposer >
+                ,cds::opt::lock_type < std::mutex >
+            > ::type
+        {};
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_DHP, shuffle )
+    {
+        typedef cds::intrusive::SegmentedQueue< gc_type, item,
+            cds::intrusive::segmented_queue::make_traits<
+                cds::intrusive::opt::disposer< Disposer >
+                ,cds::opt::item_counter< cds::atomicity::item_counter >
+                ,cds::opt::permutation_generator< cds::opt::v::random_shuffle_permutation<> >
+            >::type
+        > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_DHP, padding )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+            enum { padding = cds::opt::cache_line_padding };
+            typedef ci::segmented_queue::stat<> stat;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_DHP, bigdata_padding )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+            enum { padding = cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only };
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, big_item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+} // namespace
+\r
diff --git a/test/unit/queue/intrusive_segmented_queue_hp.cpp b/test/unit/queue/intrusive_segmented_queue_hp.cpp
new file mode 100644 (file)
index 0000000..12c951d
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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.     
+*/
+
+#include "test_intrusive_segmented_queue.h"
+
+#include <cds/gc/hp.h>
+#include <cds/intrusive/segmented_queue.h>
+#include <vector>
+
+namespace {
+    namespace ci = cds::intrusive;
+    typedef cds::gc::HP gc_type;
+
+    class IntrusiveSegmentedQueue_HP : public cds_test::intrusive_segmented_queue
+    {
+        typedef cds_test::intrusive_segmented_queue base_class;
+
+    protected:
+        static const size_t c_QuasiFactor = 15;
+
+        void SetUp()
+        {
+            typedef ci::SegmentedQueue< gc_type, item > queue_type;
+
+            cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 );
+            cds::threading::Manager::attachThread();
+        }
+
+        void TearDown()
+        {
+            cds::threading::Manager::detachThread();
+            cds::gc::hp::GarbageCollector::Destruct( true );
+        }
+
+        template <typename V>
+        void check_array( V& arr )
+        {
+            for ( size_t i = 0; i < arr.size(); ++i ) {
+                EXPECT_EQ( arr[i].nDisposeCount, 2 );
+                EXPECT_EQ( arr[i].nDispose2Count, 1 );
+            }
+        }
+    };
+
+    TEST_F( IntrusiveSegmentedQueue_HP, defaulted )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_HP, mutex )
+    {
+        struct queue_traits : public
+            cds::intrusive::segmented_queue::make_traits <
+                cds::intrusive::opt::disposer< Disposer >
+                ,cds::opt::lock_type < std::mutex >
+            > ::type
+        {};
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_HP, shuffle )
+    {
+        typedef cds::intrusive::SegmentedQueue< gc_type, item,
+            cds::intrusive::segmented_queue::make_traits<
+                cds::intrusive::opt::disposer< Disposer >
+                ,cds::opt::item_counter< cds::atomicity::item_counter >
+                ,cds::opt::permutation_generator< cds::opt::v::random_shuffle_permutation<> >
+            >::type
+        > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_HP, padding )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+            enum { padding = cds::opt::cache_line_padding };
+            typedef ci::segmented_queue::stat<> stat;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+    TEST_F( IntrusiveSegmentedQueue_HP, bigdata_padding )
+    {
+        struct queue_traits : public cds::intrusive::segmented_queue::traits
+        {
+            typedef Disposer disposer;
+            enum { padding = cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only };
+            typedef cds::opt::v::sequential_consistent memory_model;
+        };
+        typedef cds::intrusive::SegmentedQueue< gc_type, big_item, queue_traits > queue_type;
+
+        std::vector<typename queue_type::value_type> arr;
+        {
+            queue_type q( c_QuasiFactor );
+            test( q, arr );
+        }
+        queue_type::gc::force_dispose();
+        check_array( arr );
+    }
+
+} // namespace
+\r
diff --git a/test/unit/queue/test_intrusive_msqueue.h b/test/unit/queue/test_intrusive_msqueue.h
new file mode 100644 (file)
index 0000000..677a614
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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 CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
+#define CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
+
+#include <cds_test/check_size.h>
+
+namespace cds_test {
+
+    class intrusive_msqueue : public ::testing::Test
+    {
+    protected:
+        template <typename Base>
+        struct base_hook_item : public Base
+        {
+            int nVal;
+            int nDisposeCount;
+
+            base_hook_item()
+                : nDisposeCount( 0 )
+            {}
+
+            base_hook_item( base_hook_item const& s)
+                : nVal( s.nVal )
+                , nDisposeCount( s.nDisposeCount )
+            {}
+        };
+
+        template <typename Member>
+        struct member_hook_item
+        {
+            int nVal;
+            int nDisposeCount;
+            Member hMember;
+
+            member_hook_item()
+                : nDisposeCount( 0 )
+            {}
+
+            member_hook_item( member_hook_item const& s )
+                : nVal( s.nVal )
+                , nDisposeCount( s.nDisposeCount )
+            {}
+        };
+
+        struct mock_disposer
+        {
+            template <typename T>
+            void operator ()( T * p )
+            {
+                ++p->nDisposeCount;
+            }
+        };
+
+        template <typename Queue, typename Data>
+        void test( Queue& q, Data& arr )
+        {
+            typedef typename Queue::value_type value_type;
+            size_t nSize = arr.size();
+
+            value_type * pv;
+            for ( size_t i = 0; i < nSize; ++i )
+                arr[i].nVal = static_cast<int>(i);
+
+            ASSERT_TRUE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, 0 );
+
+            // pop from empty queue
+            pv = q.pop();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, 0 );
+
+            pv =q.dequeue();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, 0 );
+
+            // push/pop test
+            for ( size_t i = 0; i < nSize; ++i ) {
+                if ( i & 1 )
+                    q.push( arr[i] );
+                else
+                    q.enqueue( arr[i] );
+                ASSERT_FALSE( q.empty());
+                ASSERT_CONTAINER_SIZE( q, i + 1 );
+            }
+
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_FALSE( q.empty() );
+                ASSERT_CONTAINER_SIZE( q, nSize - i );
+                if ( i & 1 )
+                    pv = q.pop();
+                else
+                    pv = q.dequeue();
+                ASSERT_FALSE( pv == nullptr );
+                ASSERT_EQ( pv->nVal, static_cast<int>(i));
+            }
+            ASSERT_TRUE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, 0 );
+
+            Queue::gc::scan();
+            --nSize; // last element of array is in queue yet as a dummy item
+            for ( size_t i = 0; i < nSize; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 1 );
+            }
+            ASSERT_EQ( arr[nSize].nDisposeCount, 0 );
+
+            // clear test
+            for ( size_t i = 0; i < nSize; ++i )
+                q.push( arr[i] );
+
+            ASSERT_FALSE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, nSize );
+
+            q.clear();
+            ASSERT_TRUE( q.empty() );
+            ASSERT_CONTAINER_SIZE( q, 0 );
+
+            Queue::gc::scan();
+            for ( size_t i = 0; i < nSize - 1; ++i ) {
+                ASSERT_EQ( arr[i].nDisposeCount, 2 ) << "i=" << i;
+            }
+            ASSERT_EQ( arr[nSize - 1].nDisposeCount, 1 ); // this element is in the queue yet
+            ASSERT_EQ( arr[nSize].nDisposeCount, 1 );
+        }
+    };
+
+} // namespace cds_test
+
+#endif // CDSUNIT_QUEUE_TEST_INTRUSIVE_MSQUEUE_H
diff --git a/test/unit/queue/test_intrusive_segmented_queue.h b/test/unit/queue/test_intrusive_segmented_queue.h
new file mode 100644 (file)
index 0000000..59fbcfa
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    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 CDSUNIT_QUEUE_TEST_INTRUSIVE_SEGMENTED_QUEUE_H
+#define CDSUNIT_QUEUE_TEST_INTRUSIVE_SEGMENTED_QUEUE_H
+
+#include <cds_test/check_size.h>
+\r
+namespace cds_test {\r
+\r
+    class intrusive_segmented_queue : public ::testing::Test\r
+    {\r
+    protected:\r
+        struct item {
+            int  nValue;
+
+            size_t  nDisposeCount;
+            size_t  nDispose2Count;
+
+            item()
+                : nValue( 0 )
+                , nDisposeCount( 0 )
+                , nDispose2Count( 0 )
+            {}
+
+            item( int nVal )
+                : nValue( nVal )
+                , nDisposeCount( 0 )
+                , nDispose2Count( 0 )
+            {}
+        };
+
+        struct big_item : public item
+        {
+            big_item()
+            {}
+
+            big_item( int nVal )
+                : item( nVal )
+            {}
+
+            int arr[80];
+        };
+
+        struct Disposer
+        {
+            void operator()( item * p )
+            {
+                ++p->nDisposeCount;
+            }
+        };
+
+        struct Disposer2
+        {
+            void operator()( item * p )
+            {
+                ++p->nDispose2Count;
+            }
+        };
+\r
+        template <typename Queue, typename Data>\r
+        void test( Queue& q, Data& val )\r
+        {\r
+            typedef typename Queue::value_type value_type;\r
+            val.resize( 100 );\r
+            for ( int i = 0; i < val.size(); ++i )
+                val[i].nValue = i;
+\r
+            ASSERT_TRUE( q.empty());\r
+            ASSERT_CONTAINER_SIZE( q, 0 );\r
+\r
+            // push/enqueue
+            for ( size_t i = 0; i < val.size(); ++i ) {
+                if ( i & 1 ) {
+                    ASSERT_TRUE( q.push( val[i] ) );
+                }
+                else {
+                    ASSERT_TRUE( q.enqueue( val[i] ) );
+                }
+
+                ASSERT_CONTAINER_SIZE( q, i + 1 );
+            }
+            EXPECT_TRUE( !q.empty() );
+
+            // pop/dequeue
+            size_t nCount = 0;
+            while ( !q.empty() ) {
+                value_type * pVal;
+                if ( nCount & 1 )
+                    pVal = q.pop();
+                else
+                    pVal = q.dequeue();
+
+                ASSERT_TRUE( pVal != nullptr );
+
+                int nSegment = int( nCount / q.quasi_factor() );
+                int nMin = nSegment * int( q.quasi_factor() );
+                int nMax = nMin + int( q.quasi_factor() ) - 1;
+                EXPECT_TRUE( nMin <= pVal->nValue && pVal->nValue <= nMax ) << nMin << " <= " << pVal->nValue << " <= " << nMax;
+
+                ++nCount;
+                EXPECT_CONTAINER_SIZE( q, val.size() - nCount );
+            }
+            EXPECT_EQ( nCount, val.size());
+            EXPECT_TRUE( q.empty() );
+            EXPECT_CONTAINER_SIZE( q, 0 );
+\r
+            // pop from empty queue
+            ASSERT_TRUE( q.pop() == nullptr );
+            EXPECT_TRUE( q.empty() );
+            EXPECT_CONTAINER_SIZE( q, 0 );
+
+            // check that Disposer has not been called
+            Queue::gc::force_dispose();
+            for ( int i = 0; i < val.size(); ++i ) {
+                EXPECT_EQ( val[i].nDisposeCount, 0 );
+                EXPECT_EQ( val[i].nDispose2Count, 0 );
+            }
+\r
+            // clear
+            for ( int i = 0; i < val.size(); ++i )
+                EXPECT_TRUE( q.push( val[i] ) );
+            EXPECT_CONTAINER_SIZE( q, val.size());
+            EXPECT_TRUE( !q.empty() );
+
+            q.clear();
+            EXPECT_CONTAINER_SIZE( q, 0 );
+            EXPECT_TRUE( q.empty() );
+
+            // check if Disposer has been called
+            Queue::gc::force_dispose();
+            for ( size_t i = 0; i < val.size(); ++i ) {
+                EXPECT_EQ( val[i].nDisposeCount, 1 );
+                EXPECT_EQ( val[i].nDispose2Count, 0 );
+            }
+
+            // clear_with
+            for ( size_t i = 0; i < val.size(); ++i )
+                EXPECT_TRUE( q.push( val[i] ) );
+            EXPECT_CONTAINER_SIZE( q, val.size() );
+            EXPECT_TRUE( !q.empty() );
+
+            q.clear_with( Disposer2() );
+            EXPECT_CONTAINER_SIZE( q, 0 );
+            EXPECT_TRUE( q.empty() );
+
+            // check if Disposer has been called
+            Queue::gc::force_dispose();
+            for ( size_t i = 0; i < val.size(); ++i ) {
+                EXPECT_EQ( val[i].nDisposeCount, 1 );
+                EXPECT_EQ( val[i].nDispose2Count, 1 );
+            }\r
+\r
+            // check clear on destruct
+            for ( size_t i = 0; i < val.size(); ++i )
+                EXPECT_TRUE( q.push( val[i] ));
+            EXPECT_CONTAINER_SIZE( q, val.size());
+            EXPECT_TRUE( !q.empty());\r
+        }\r
+    };\r
+\r
+} // namespace cds_test\r
+\r
+#endif // CDSUNIT_QUEUE_TEST_INTRUSIVE_SEGMENTED_QUEUE_H\r