fixed adding file problem
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / libcds-2.3.2 / cds / intrusive / moir_queue.h
diff --git a/gdax-orderbook-hpp/demo/dependencies/libcds-2.3.2/cds/intrusive/moir_queue.h b/gdax-orderbook-hpp/demo/dependencies/libcds-2.3.2/cds/intrusive/moir_queue.h
new file mode 100644 (file)
index 0000000..70afe03
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSLIB_INTRUSIVE_MOIR_QUEUE_H
+#define CDSLIB_INTRUSIVE_MOIR_QUEUE_H
+
+#include <cds/intrusive/msqueue.h>
+
+namespace cds { namespace intrusive {
+
+    /// A variation of Michael & Scott's lock-free queue (intrusive variant)
+    /** @ingroup cds_intrusive_queue
+        This is slightly optimized Michael & Scott's queue algorithm that overloads \ref dequeue function.
+
+        Source:
+            - [2000] Simon Doherty, Lindsay Groves, Victor Luchangco, Mark Moir
+                "Formal Verification of a practical lock-free queue algorithm"
+
+        Cite from this work about difference from Michael & Scott algo:
+        "Our algorithm differs from Michael and Scott's [MS98] in that we test whether \p Tail points to the header
+        node only <b>after</b> \p Head has been updated, so a dequeuing process reads \p Tail only once. The dequeue in
+        [MS98] performs this test before checking whether the next pointer in the dummy node is null, which
+        means that it reads \p Tail every time a dequeuing process loops. Under high load, when operations retry
+        frequently, our modification will reduce the number of accesses to global memory. This modification, however,
+        introduces the possibility of \p Head and \p Tail 'crossing'."
+
+        Explanation of template arguments see \p intrusive::MSQueue.
+
+        \par Examples
+        \code
+        #include <cds/intrusive/moir_queue.h>
+        #include <cds/gc/hp.h>
+
+        namespace ci = cds::inrtusive;
+        typedef cds::gc::HP hp_gc;
+
+        // MoirQueue with Hazard Pointer garbage collector, base hook + item disposer:
+        struct Foo: public ci::msqueue::node< hp_gc >
+        {
+            // Your data
+            ...
+        };
+
+        // Disposer for Foo struct just deletes the object passed in
+        struct fooDisposer {
+            void operator()( Foo * p )
+            {
+                delete p;
+            }
+        };
+
+        typedef ci::MoirQueue<
+            hp_gc
+            ,Foo
+            typename ci::msqueue::make_traits<
+                ,ci::opt::hook<
+                    ci::msqueue::base_hook< ci::opt::gc<hp_gc> >
+                >
+                ,ci::opt::disposer< fooDisposer >
+            >::type
+        > fooQueue;
+
+        // MoirQueue with Hazard Pointer garbage collector,
+        // member hook + item disposer + item counter,
+        // without padding of internal queue data:
+        struct Bar
+        {
+            // Your data
+            ...
+            ci::msqueue::node< hp_gc > hMember;
+        };
+
+        struct barQueueTraits: public ci::msqueue::traits
+        {
+            typedef ci::msqueue::member_hook< offsetof(Bar, hMember), ,ci::opt::gc<hp_gc> > hook;
+            typedef fooDisposer disposer;
+            typedef cds::atomicity::item_counter item_counter;
+            enum { padding = cds::opt::no_special_padding };
+        };
+        typedef ci::MoirQueue< hp_gc, Bar, barQueueTraits > barQueue;
+        \endcode
+    */
+    template <typename GC, typename T, typename Traits = cds::intrusive::msqueue::traits>
+    class MoirQueue: public MSQueue< GC, T, Traits >
+    {
+        //@cond
+        typedef MSQueue< GC, T, Traits > base_class;
+        typedef typename base_class::node_type node_type;
+        //@endcond
+
+    public:
+        //@cond
+        typedef typename base_class::value_type value_type;
+        typedef typename base_class::back_off   back_off;
+        typedef typename base_class::gc         gc;
+        typedef typename base_class::node_traits node_traits;
+        typedef typename base_class::memory_model   memory_model;
+        //@endcond
+
+        /// Rebind template arguments
+        template < typename GC2, typename T2, typename Traits2 >
+        struct rebind {
+            typedef MoirQueue< GC2, T2, Traits2> other   ;   ///< Rebinding result
+        };
+
+    protected:
+        //@cond
+        typedef typename base_class::dequeue_result dequeue_result;
+
+        bool do_dequeue( dequeue_result& res )
+        {
+            back_off bkoff;
+
+            node_type * pNext;
+            node_type * h;
+            while ( true ) {
+                h = res.guards.protect( 0, base_class::m_pHead, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
+                pNext = res.guards.protect( 1, h->m_pNext, []( node_type * p ) -> value_type * { return node_traits::to_value_ptr( p );});
+
+                if ( pNext == nullptr ) {
+                    base_class::m_Stat.onEmptyDequeue();
+                    return false;    // queue is empty
+                }
+
+                if ( base_class::m_pHead.compare_exchange_strong( h, pNext, memory_model::memory_order_release, atomics::memory_order_relaxed )) {
+                    node_type * t = base_class::m_pTail.load(memory_model::memory_order_acquire);
+                    if ( h == t )
+                        base_class::m_pTail.compare_exchange_strong( t, pNext, memory_model::memory_order_release, atomics::memory_order_relaxed );
+                    break;
+                }
+
+                base_class::m_Stat.onDequeueRace();
+                bkoff();
+            }
+
+            --base_class::m_ItemCounter;
+            base_class::m_Stat.onDequeue();
+
+            res.pHead = h;
+            res.pNext = pNext;
+            return true;
+        }
+        //@endcond
+
+    public:
+        /// Dequeues a value from the queue
+        /** @anchor cds_intrusive_MoirQueue_dequeue
+            See warning about item disposing in \p MSQueue::dequeue.
+        */
+        value_type * dequeue()
+        {
+            dequeue_result res;
+            if ( do_dequeue( res )) {
+                base_class::dispose_result( res );
+                return node_traits::to_value_ptr( *res.pNext );
+            }
+            return nullptr;
+        }
+
+        /// Synonym for \ref cds_intrusive_MoirQueue_dequeue "dequeue" function
+        value_type * pop()
+        {
+            return dequeue();
+        }
+    };
+
+}} // namespace cds::intrusive
+
+#endif // #ifndef CDSLIB_INTRUSIVE_MOIR_QUEUE_H