fixed adding file problem
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / libcds-2.3.2 / test / unit / queue / intrusive_fcqueue.cpp
diff --git a/gdax-orderbook-hpp/demo/dependencies/libcds-2.3.2/test/unit/queue/intrusive_fcqueue.cpp b/gdax-orderbook-hpp/demo/dependencies/libcds-2.3.2/test/unit/queue/intrusive_fcqueue.cpp
new file mode 100644 (file)
index 0000000..4a3a64b
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cds_test/ext_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 )
+            {}
+        };
+
+    public:
+        struct disposer
+        {
+            template <typename T>
+            void operator ()( T * p )
+            {
+                ++p->nDisposeCount;
+            }
+        };
+
+    protected:
+        template <typename Queue>
+        void test( Queue& q )
+        {
+            typedef typename Queue::value_type value_type;
+            typedef typename Queue::container_type underlying_queue_type;
+
+            size_t const nSize = 100;
+            value_type * pv;
+            std::vector<value_type> arr;
+            arr.resize( nSize );
+            int total_sum = 0;
+            for ( size_t i = 0; i < nSize; ++i ) {
+                arr[i].nVal = static_cast<int>( i );
+                total_sum += static_cast<int>( i );
+            }
+
+            ASSERT_TRUE( q.empty());
+            ASSERT_EQ( q.size(), 0u );
+
+            // pop from empty queue
+            pv = q.pop();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty());
+            ASSERT_EQ( q.size(), 0u );
+
+            pv = q.dequeue();
+            ASSERT_TRUE( pv == nullptr );
+            ASSERT_TRUE( q.empty());
+            ASSERT_EQ( q.size(), 0u );
+
+            // 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 );
+            }
+
+            int sum = 0;
+            q.apply( [&sum]( underlying_queue_type& queue )
+            {
+                for ( auto const& el : queue )
+                    sum += el.nVal;
+            } );
+            EXPECT_EQ( sum, total_sum );
+
+
+            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(), 0u );
+
+            // 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(), 0u );
+
+            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(), 0u );
+
+            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_empty_wait_strategy )
+    {
+        typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
+        struct traits: public cds::intrusive::fcqueue::traits
+        {
+            typedef IntrusiveFCQueue::disposer disposer;
+            typedef cds::algo::flat_combining::wait_strategy::empty wait_strategy;
+            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_single_mutex_single_condvar )
+    {
+        typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
+        struct traits: public cds::intrusive::fcqueue::traits
+        {
+            typedef IntrusiveFCQueue::disposer disposer;
+            typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<> wait_strategy;
+            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_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_mutex_single_mutex_multi_condvar )
+    {
+        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::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<> wait_strategy;
+        };
+        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, base_elimination_multi_mutex_multi_condvar )
+    {
+        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 >
+                , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<>>
+            > ::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_empty_wait_strategy )
+    {
+        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::wait_strategy< cds::algo::flat_combining::wait_strategy::empty >
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, member_single_mutex_single_condvar )
+    {
+        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::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<2>>
+            >::type
+        > queue_type;
+
+        queue_type q;
+        test( q );
+    }
+
+    TEST_F( IntrusiveFCQueue, member_multi_mutex_multi_condvar )
+    {
+        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::wait_strategy< cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<>>
+            >::type
+        > 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, member_elimination_single_mutex_multi_condvar )
+    {
+        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 >
+                , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<2>>
+            >::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