Fixed a bug
[libcds.git] / cds / opt / options.h
index 9b34428adcc708f990dc16a4ed53c78ab6573a69..70faba7178a6c1a36a4630730072d2cc666aeb31 100644 (file)
@@ -1,7 +1,35 @@
-//$$CDS-header$$
+/*
+    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 __CDS_OPT_OPTIONS_H
-#define __CDS_OPT_OPTIONS_H
+#ifndef CDSLIB_OPT_OPTIONS_H
+#define CDSLIB_OPT_OPTIONS_H
 
 /*
     Framework to define template options
         2011.01.23 khizmax  Created
 */
 
+#include <cstdlib> // rand, srand
+
 #include <cds/details/aligned_type.h>
 #include <cds/user_setup/allocator.h>
 #include <cds/user_setup/cache_line.h>
-#include <cds/cxx11_atomic.h>
-#include <cds/details/void_selector.h>
-#include <stdlib.h> // rand, srand
+#include <cds/algo/atomic.h>
 
 namespace cds {
 
@@ -27,9 +55,6 @@ namespace cds {
 */
 namespace opt {
 
-    /// Predefined options value (generally, for the options that determine the data types)
-    namespace v {}
-
     /// Type indicates that an option is not specified and the default one should be used
     struct none
     {
@@ -51,11 +76,11 @@ namespace opt {
 
         Examples:
         \code
-        // default_spin is cds::lock::Spin
-        typedef typename cds::opt::select_default< cds::opt::none, cds::lock::Spin >::type  default_spin;
+        // default_spin is cds::sync::spin
+        typedef typename cds::opt::select_default< cds::opt::none, cds::sync::spin >::type  default_spin;
 
-        // spin_32bit is cds::lock::Spin32
-        typedef typename cds::opt::select_default< cds::lock::Spin32, cds::lock::Spin >::type  spin_32bit;
+        // spin_32bit is cds::sync::reentrant_spin32
+        typedef typename cds::opt::select_default< cds::opt::none, cds::sync::reentrant_spin32 >::type  spin_32bit;
         \endcode
     */
     template <typename Option, typename Default, typename Value = Option>
@@ -178,6 +203,21 @@ namespace opt {
         //@endcond
     };
 
+    /// [type-option] @ref cds_sync_monitor "Monitor" type setter
+    /**
+        This option setter specifyes @ref cds_sync_monitor "synchronization monitor"
+        for blocking container.
+    */
+    template <typename Type>
+    struct sync_monitor {
+        //@cond
+        template <class Base> struct pack : public Base
+        {
+            typedef Type sync_monitor;
+        };
+        //@endcond
+    };
+
     /// [type-option] Back-off strategy option setter
     /**
         Back-off strategy used in some algorithm.
@@ -197,8 +237,7 @@ namespace opt {
     /**
         Possible values of \p GC template parameter are:
         - cds::gc::HP - Hazard Pointer garbage collector
-        - cds::gc::HRC - Gidenstam's garbage collector
-        - cds::gc::PTB - Pass-the-Buck garbage collector
+        - cds::gc::DHP - Dynamic Hazard Pointer garbage collector
         - cds::gc::none::GC - No garbage collector (not supported for some containers)
     */
     template <typename GC>
@@ -263,17 +302,18 @@ namespace opt {
         This option allows to set up appropriate item counting policy for that data structure.
 
         Predefined option \p Type:
-        - atomicity::empty_item_counter - no item counting performed. It is default policy for many
+        - \p atomicity::empty_item_counter - no item counting performed. It is default policy for many
             containers
-        - atomicity::item_counter - the class that provides atomically item counting
-        - opt::v::sequential_item_counter - simple non-atomic item counter. This item counter is not intended for
+        - \p atomicity::item_counter - the class that provides atomic item counting
+        - \p atomicity::cache_friendly_item_counter - cache-friendly atomic item counter
+        - \p opt::v::sequential_item_counter - simple non-atomic item counter. This counter is not intended for
             concurrent containers and may be used only if it is explicitly noted.
 
-        You may provide other implementation of atomicity::item_counter interface for your needs.
+        You may provide other implementation of \p atomicity::item_counter interface for your needs.
 
         Note, the item counting in lock-free containers cannot be exact; for example, if
         item counter for a container returns zero it is not mean that the container is empty.
-        Thus, item counter may be used for statistical purposes only.
+        So, the item counter may be used for statistical purposes only.
     */
     template <typename Type>
     struct item_counter {
@@ -285,78 +325,6 @@ namespace opt {
         //@endcond
     };
 
-    namespace v {
-        /// Sequential non-atomic item counter
-        /**
-            This type of item counter is not intended for concurrent containers
-            and may be used only if it is explicitly noted.
-        */
-        class sequential_item_counter
-        {
-        public:
-            typedef size_t counter_type    ;  ///< Counter type
-        protected:
-            counter_type  m_nCounter ;      ///< Counter
-
-        public:
-            sequential_item_counter()
-                : m_nCounter(0)
-            {}
-
-            /// Returns current value of the counter
-            counter_type    value() const
-            {
-                return m_nCounter;
-            }
-
-            /// Same as \ref value() with relaxed memory ordering
-            operator counter_type() const
-            {
-                return value();
-            }
-
-            /// Increments the counter. Semantics: postincrement
-            counter_type inc()
-            {
-                return m_nCounter++;
-            }
-
-            /// Decrements the counter. Semantics: postdecrement
-            counter_type dec()
-            {
-                return m_nCounter--;
-            }
-
-            /// Preincrement
-            counter_type operator ++()
-            {
-                return inc() + 1;
-            }
-            /// Postincrement
-            counter_type operator ++(int)
-            {
-                return inc();
-            }
-
-            /// Predecrement
-            counter_type operator --()
-            {
-                return dec() - 1;
-            }
-            /// Postdecrement
-            counter_type operator --(int)
-            {
-                return dec();
-            }
-
-            /// Resets count to 0
-            void reset()
-            {
-                m_nCounter = 0;
-            }
-        };
-    } // namespace v
-
     /// Special alignment constants for \ref cds::opt::alignment option
     enum special_alignment {
         no_special_alignment = 0,   ///< no special alignment
@@ -395,10 +363,160 @@ namespace opt {
         struct alignment_setter<Type, cache_line_alignment> {
             typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type  type;
         };
+    } // namespace details
+    //@endcond
+
+    /// Special padding constants for \p cds::opt::padding option
+    enum special_padding {
+        no_special_padding = 0,   ///< no special padding
+        cache_line_padding = 1,   ///< use cache line size defined in cds/user_setup/cache_line.h
+
+        /// Apply padding only for tiny data when data size is less than required padding
+        /**
+            The flag means that if your data size is less than the cacheline size, the padding is applyed.
+            Otherwise no padding will be applyed.
+
+            This flag is applyed for padding value:
+            \code
+            cds::opt::padding< cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only >;
+            cds::opt::padding< 256 | cds::opt::padding_tiny_data_only >;
+            \endcode
+        */
+        padding_tiny_data_only = 0x80000000,
+
+        //@cond
+        padding_flags = padding_tiny_data_only
+        //@endcond
+    };
+
+    /// [value-option] Padding option setter
+    /**
+        The padding for the internal data of some containers. May be useful to solve false sharing problem.
+        \p Value defines desired padding and it may be power of two integer or predefined values from
+        \p special_padding enum.
+    */
+    template <unsigned int Value>
+    struct padding {
+        //@cond
+        template <typename Base> struct pack: public Base
+        {
+            enum { padding = Value };
+        };
+        //@endcond
+    };
+
+    //@cond
+    template <unsigned Padding>
+    struct actual_padding
+    {
+        enum { value = Padding & ~padding_flags };
+    };
+
+    template <>
+    struct actual_padding<cache_line_padding>
+    {
+        enum { value = cds::c_nCacheLineSize };
+    };
+
+    template <>
+    struct actual_padding<cache_line_padding| padding_tiny_data_only>
+    {
+        enum { value = cds::c_nCacheLineSize };
+    };
+    //@endcond
+
+    //@cond
+    namespace details {
+        enum padding_vs_datasize {
+            padding_datasize_less,
+            padding_datasize_equal,
+            padding_datasize_greater
+        };
+
+        template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
+        struct apply_padding_helper;
+
+        template <typename T, padding_vs_datasize Relation, bool TinyOnly >
+        struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
+        {
+            struct type {
+                T   data;
+            };
+            typedef void padding_type;
+        };
+
+        template <typename T, unsigned int Padding, bool TinyOnly >
+        struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
+        {
+            struct type {
+                T   data;
+            };
+            typedef void padding_type;
+        };
+
+        template <typename T, unsigned int Padding, bool TinyOnly >
+        struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
+        {
+            typedef uint8_t padding_type[Padding - sizeof( T )];
+            struct type {
+                T data;
+                padding_type pad_;
+            };
+
+        };
+
+        template <typename T, unsigned int Padding >
+        struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
+        {
+            typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
+            struct type {
+                T data;
+                padding_type pad_;
+            };
+        };
+
+        template <typename T, unsigned int Padding >
+        struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
+        {
+            struct type {
+                T data;
+            };
+            typedef void padding_type;
+        };
+
+        template <typename T, unsigned int Padding >
+        struct apply_padding
+        {
+        private:
+            enum { padding = Padding & ~padding_flags };
+
+        public:
+            static CDS_CONSTEXPR const size_t c_nPadding =
+                static_cast<unsigned int>(padding) == static_cast<unsigned int>(cache_line_padding) ? cds::c_nCacheLineSize :
+                static_cast<unsigned int>(padding) == static_cast<unsigned int>(no_special_padding) ? 0 : padding;
+
+            static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
+
+            typedef apply_padding_helper< T,
+                c_nPadding,
+                c_nPadding == 0,
+                sizeof( T ) < c_nPadding ? padding_datasize_less : sizeof( T ) == c_nPadding ? padding_datasize_equal : padding_datasize_greater,
+                (Padding & padding_tiny_data_only) != 0
+            > result;
+
+            typedef typename result::type type;
+
+            typedef typename std::conditional<
+                std::is_same< typename result::padding_type, void >::value,
+                unsigned int,
+                typename result::padding_type
+            >::type padding_type;
+        };
 
     } // namespace details
     //@endcond
 
+
     /// [type-option] Generic option setter for statisitcs
     /**
         This option sets a type to gather statistics.
@@ -418,16 +536,16 @@ namespace opt {
     /// [type-option] Option setter for C++ memory model
     /**
         The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
-        - v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
+        - \p v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
             \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
-        - v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
+        - \p v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
             this mode any memory ordering constraint maps to \p memory_order_seq_cst.
 
-        The \p Type template parameter can be v::relaxed_ordering or v::sequential_consistent.
+        The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
 
         You may mix different memory ordering options for different containers: one declare as sequentially consistent,
         another declare as relaxed.
-        Usually, v::relaxed_ordering is the default memory ordering for <b>cds</b> containers.
+        Usually, \p v::relaxed_ordering is the default memory ordering for <b>libcds</b> containers.
     */
     template <typename Type>
     struct memory_model {
@@ -439,46 +557,6 @@ namespace opt {
         //@endcond
     };
 
-    namespace v {
-        /// Relaxed memory ordering model
-        /**
-            In this memory model the memory constraints are defined according to C++ Memory Model specification.
-
-            See opt::memory_model for explanations
-        */
-        struct relaxed_ordering {
-            //@cond
-
-            // For new C++11 (cds-1.1.0)
-            static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_relaxed;
-            static const atomics::memory_order memory_order_consume    = atomics::memory_order_consume;
-            static const atomics::memory_order memory_order_acquire    = atomics::memory_order_acquire;
-            static const atomics::memory_order memory_order_release    = atomics::memory_order_release;
-            static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_acq_rel;
-            static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
-            //@endcond
-        };
-
-        /// Sequential consistent memory ordering model
-        /**
-            In this memory model any memory constraint is equivalent to \p memory_order_seq_cst.
-
-            See opt::memory_model for explanations
-        */
-        struct sequential_consistent {
-            //@cond
-
-            // For new C++11 (cds-1.1.0)
-            static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_seq_cst;
-            static const atomics::memory_order memory_order_consume    = atomics::memory_order_seq_cst;
-            static const atomics::memory_order memory_order_acquire    = atomics::memory_order_seq_cst;
-            static const atomics::memory_order memory_order_release    = atomics::memory_order_seq_cst;
-            static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_seq_cst;
-            static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
-            //@endcond
-        };
-    } // namespace v
-
     /// [type-option] Base type traits option setter
     /**
         This option setter is intended generally for internal use for type rebinding.
@@ -551,22 +629,6 @@ namespace opt {
         //@endcond
     };
 
-    namespace v {
-
-        /// Default swap policy (see opt::swap_policy option)
-        /**
-            The default swap policy is wrappr around \p std::swap algorithm.
-        */
-        struct default_swap_policy {
-            /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
-            template <typename T>
-            void operator()( T& v1, T& v2 ) const
-            {
-                std::swap( v1, v2 );
-            }
-        };
-    } // namespace v
-
     /// Move policy option
     /**
         The move policy specifies an algorithm for moving object content.
@@ -595,19 +657,6 @@ namespace opt {
         //@endcond
     };
 
-    namespace v {
-        /// \ref opt::move_policy "Move policy" based on assignment operator
-        struct assignment_move_policy
-        {
-            /// <tt> dest = src </tt>
-            template <typename T>
-            void operator()( T& dest, T const& src ) const
-            {
-                dest = src;
-            }
-        };
-    } // namespace v
-
     /// [value-option] Enable sorting
     /**
         This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
@@ -647,7 +696,7 @@ namespace opt {
         \p Random can be any STL random number generator producing
         unsigned integer: \p std::linear_congruential_engine,
         \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
-        and so on, or opt::v::c_rand.
+        and so on, or \p opt::v::c_rand.
 
     */
     template <typename Random>
@@ -660,54 +709,511 @@ namespace opt {
         //@endcond
     };
 
+    /// [type-option] Free-list implementation
+    /**
+        See \p cds::intrusive::FreeList for free-list interface
+    */
+    template <typename FreeList>
+    struct free_list {
+        //@cond
+        template <typename Base> struct pack: public Base
+        {
+            typedef FreeList free_list;
+        };
+        //@endcond
+    };
+
+    //@cond
+    // For internal use
+    template <typename Accessor>
+    struct key_accessor {
+        template <typename Base> struct pack: public Base
+        {
+            typedef Accessor key_accessor;
+        };
+    };
+
+    template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
+    struct replace_key_accessor {
+        typedef typename std::conditional<
+            std::is_same< typename Traits::key_accessor, WhatReplace >::value,
+            typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
+            Traits
+        >::type type;
+    };
+    //@endcond
+
+}}  // namespace cds::opt
+
+
+// ****************************************************
+// Options predefined types and values
+
+namespace cds { namespace opt {
+
+    /// Predefined options value
     namespace v {
-        /// \p rand() -base random number generator
+
+        /// Sequential non-atomic item counter
+        /**
+            This type of \p opt::item_counter option is not intended for concurrent containers
+            and may be used only if it is explicitly noted.
+        */
+        class sequential_item_counter
+        {
+        public:
+            typedef size_t counter_type    ;  ///< Counter type
+        protected:
+            counter_type  m_nCounter ;      ///< Counter
+
+        public:
+            sequential_item_counter()
+                : m_nCounter(0)
+            {}
+
+            /// Returns current value of the counter
+            counter_type    value() const
+            {
+                return m_nCounter;
+            }
+
+            /// Same as \ref value() with relaxed memory ordering
+            operator counter_type() const
+            {
+                return value();
+            }
+
+            /// Increments the counter. Semantics: postincrement
+            counter_type inc()
+            {
+                return m_nCounter++;
+            }
+
+            /// Decrements the counter. Semantics: postdecrement
+            counter_type dec()
+            {
+                return m_nCounter--;
+            }
+
+            /// Preincrement
+            counter_type operator ++()
+            {
+                return inc() + 1;
+            }
+            /// Postincrement
+            counter_type operator ++(int)
+            {
+                return inc();
+            }
+
+            /// Predecrement
+            counter_type operator --()
+            {
+                return dec() - 1;
+            }
+            /// Postdecrement
+            counter_type operator --(int)
+            {
+                return dec();
+            }
+
+            /// Resets count to 0
+            void reset()
+            {
+                m_nCounter = 0;
+            }
+        };
+
+        /// Relaxed memory ordering \p opt::memory_model
+        /**
+            In this ordering the memory constraints are defined according to C++ Memory Model specification:
+            each constraint is mapped to \p std::memory_order constraints one-to-one
+        */
+        struct relaxed_ordering {
+            //@cond
+            static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_consume    = atomics::memory_order_consume;
+            static const atomics::memory_order memory_order_acquire    = atomics::memory_order_acquire;
+            static const atomics::memory_order memory_order_release    = atomics::memory_order_release;
+            static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_acq_rel;
+            static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
+            //@endcond
+        };
+
+        /// Sequential consistent \p opt::memory_memory ordering
+        /**
+            In this memory model any memory constraint is equivalent to \p std::memory_order_seq_cst.
+        */
+        struct sequential_consistent {
+            //@cond
+            static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_seq_cst;
+            static const atomics::memory_order memory_order_consume    = atomics::memory_order_seq_cst;
+            static const atomics::memory_order memory_order_acquire    = atomics::memory_order_seq_cst;
+            static const atomics::memory_order memory_order_release    = atomics::memory_order_seq_cst;
+            static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_seq_cst;
+            static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
+            //@endcond
+        };
+
+        //@cond
+        /// Totally relaxed \p opt::memory_model ordering (do not use!)
+        /**
+            In this memory model any memory constraint is equivalent to \p std::memory_order_relaxed.
+            @warning Do not use this model! It intended for testing purposes only
+            to verify debugging instruments like Thread Sanitizer.
+        */
+        struct total_relaxed_ordering {
+            static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_consume    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_acquire    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_release    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_relaxed;
+            static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_relaxed;
+        };
+        //@endcond
+
+
+        /// Default swap policy for \p opt::swap_policy option
+        /**
+            The default swap policy is wrappr around \p std::swap algorithm.
+        */
+        struct default_swap_policy {
+            /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
+            template <typename T>
+            void operator()( T& v1, T& v2 ) const
+            {
+                std::swap( v1, v2 );
+            }
+        };
+
+        /// \p opt::move_policy based on move-assignment operator
+        struct assignment_move_policy
+        {
+            /// <tt> dest = std::move( src ) </tt>
+            template <typename T>
+            void operator()( T& dest, T&& src ) const
+            {
+                dest = std::move( src );
+            }
+        };
+
+        /// \p rand() -base random number generator for \p opt::random_engine
         /**
             This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
         */
         struct c_rand {
             typedef unsigned int result_type; ///< Result type
 
-            /// Constructor initializes object calling \p srand()
+            /// Constructor initializes object calling \p std::srand()
             c_rand()
             {
-                srand(1);
+                std::srand(1);
             }
 
-            /// Returns next random number calling \p rand()
+            /// Returns next random number calling \p std::rand()
             result_type operator()()
             {
-                return (result_type) rand();
+                return (result_type) std::rand();
             }
         };
     } // namespace v
 
+}} // namespace cds::opt
+
+
+// ****************************************************
+// Options metafunctions
+
+namespace cds { namespace opt {
+
     //@cond
-    // For internal use
-    template <typename Accessor>
-    struct key_accessor {
-        template <typename Base> struct pack: public Base
+    namespace details {
+        template <typename OptionList, typename Option>
+        struct do_pack
         {
-            typedef Accessor key_accessor;
+            // Use "pack" member template to pack options
+            typedef typename Option::template pack<OptionList> type;
+        };
+
+        template <typename ...T> class typelist;
+
+        template <typename Typelist> struct typelist_head;
+        template <typename Head, typename ...Tail>
+        struct typelist_head< typelist<Head, Tail...> > {
+            typedef Head type;
+        };
+        template <typename Head>
+        struct typelist_head< typelist<Head> > {
+            typedef Head type;
+        };
+
+        template <typename Typelist> struct typelist_tail;
+        template <typename Head, typename ...Tail>
+        struct typelist_tail< typelist<Head, Tail...> > {
+            typedef typelist<Tail...> type;
         };
+        template <typename Head>
+        struct typelist_tail< typelist<Head> > {
+            typedef typelist<> type;
+        };
+
+        template <typename OptionList, typename Typelist>
+        struct make_options_impl {
+            typedef typename make_options_impl<
+                typename do_pack<
+                    OptionList,
+                    typename typelist_head< Typelist >::type
+                >::type,
+                typename typelist_tail<Typelist>::type
+            >::type type;
+        };
+
+        template <typename OptionList>
+        struct make_options_impl<OptionList, typelist<> > {
+            typedef OptionList type;
+        };
+    }   // namespace details
+    //@endcond
+
+    /// make_options metafunction
+    /** @headerfile cds/opt/options.h
+
+        The metafunction converts option list \p Options to traits structure.
+        The result of metafunction is \p type.
+
+        Template parameter \p OptionList is default option set (default traits).
+        \p Options is option list.
+    */
+    template <typename OptionList, typename... Options>
+    struct make_options {
+#ifdef CDS_DOXYGEN_INVOKED
+        typedef implementation_defined type ;   ///< Result of the metafunction
+#else
+        typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
+#endif
     };
 
-    template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
-    struct replace_key_accessor {
-        typedef typename std::conditional<
-            std::is_same< typename Traits::key_accessor, WhatReplace >::value,
-            typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
-            Traits
-        >::type type;
+
+    // *****************************************************************
+    // find_type_traits metafunction
+    // *****************************************************************
+
+    //@cond
+    namespace details {
+        template <typename... Options>
+        struct find_type_traits_option;
+
+        template <>
+        struct find_type_traits_option<> {
+            typedef cds::opt::none  type;
+        };
+
+        template <typename Any>
+        struct find_type_traits_option< Any > {
+            typedef cds::opt::none type;
+        };
+
+        template <typename Any>
+        struct find_type_traits_option< cds::opt::type_traits< Any > > {
+            typedef Any type;
+        };
+
+        template <typename Any, typename... Options>
+        struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
+            typedef Any type;
+        };
+
+        template <typename Any, typename... Options>
+        struct find_type_traits_option< Any, Options... > {
+            typedef typename find_type_traits_option< Options... >::type type;
+        };
+    } // namespace details
+    //@endcond
+
+    /// Metafunction to find opt::type_traits option in \p Options list
+    /** @headerfile cds/opt/options.h
+
+        If \p Options contains \p opt::type_traits option then it is the metafunction result.
+        Otherwise the result is \p DefaultOptons.
+    */
+    template <typename DefaultOptions, typename... Options>
+    struct find_type_traits {
+        typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ;  ///< Metafunction result
     };
+
+
+    // *****************************************************************
+    // find_option metafunction
+    // *****************************************************************
+
+    //@cond
+    namespace details {
+        template <typename What, typename... Options>
+        struct find_option;
+
+        struct compare_ok;
+        struct compare_fail;
+
+        template <typename A, typename B>
+        struct compare_option
+        {
+            typedef compare_fail type;
+        };
+
+        template <template <typename> class Opt, typename A, typename B>
+        struct compare_option< Opt<A>, Opt<B> >
+        {
+            typedef compare_ok   type;
+        };
+
+        // Specializations for integral type of option
+#define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
+        struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
+
+        // For user-defined enum types
+#define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
+
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
+        CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
+
+
+        template <typename CompResult, typename Ok, typename Fail>
+        struct select_option
+        {
+            typedef Fail    type;
+        };
+
+        template <typename Ok, typename Fail>
+        struct select_option< compare_ok, Ok, Fail >
+        {
+            typedef Ok      type;
+        };
+
+        template <typename What>
+        struct find_option< What > {
+            typedef What    type;
+        };
+
+        template <typename What, typename Opt>
+        struct find_option< What, Opt > {
+            typedef typename select_option<
+                typename compare_option< What, Opt >::type
+                ,Opt
+                ,What
+            >::type type;
+        };
+
+        template <typename What, typename Opt, typename... Options>
+        struct find_option< What, Opt, Options... > {
+            typedef typename select_option<
+                typename compare_option< What, Opt >::type
+                ,Opt
+                ,typename find_option< What, Options... >::type
+            >::type type;
+        };
+    } // namespace details
+    //@endcond
+
+    /// Metafunction to find \p What option in \p Options list
+    /** @headerfile cds/opt/options.h
+
+        If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
+        Otherwise the result is \p What.
+
+        Example:
+        \code
+        #include <cds/opt/options.h>
+        namespace co = cds::opt;
+
+        struct default_tag;
+        struct tag_a;
+        struct tag_b;
+
+        // Find option co::tag.
+
+        // res1 is co::tag< tag_a >
+        typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
+
+        // res2 is default co::tag< default_tag >
+        typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
+
+        // Multiple option co::tag. The first option is selected
+        // res3 is default co::tag< tag_a >
+        typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
+
+        \endcode
+    */
+    template <typename What, typename... Options>
+    struct find_option {
+        typedef typename details::find_option<What, Options...>::type   type ;  ///< Metafunction result
+    };
+
+
+    // *****************************************************************
+    // select metafunction
+    // *****************************************************************
+
+    //@cond
+    namespace details {
+
+        template <typename What, typename... Pairs>
+        struct select;
+
+        template <typename What, typename Value>
+        struct select< What, What, Value>
+        {
+            typedef Value   type;
+        };
+
+        template <typename What, typename Tag, typename Value>
+        struct select<What, Tag, Value>
+        {
+            typedef What    type;
+        };
+
+        template <typename What, typename Value, typename... Pairs>
+        struct select< What, What, Value, Pairs...>
+        {
+            typedef Value   type;
+        };
+
+        template <typename What, typename Tag, typename Value, typename... Pairs>
+        struct select< What, Tag, Value, Pairs...>
+        {
+            typedef typename select<What, Pairs...>::type   type;
+        };
+    }   // namespace details
     //@endcond
 
+    /// Select option metafunction
+    /** @headerfile cds/opt/options.h
+
+        Pseudocode:
+        \code
+        select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
+            if What == T1 then return R1
+            if What == T2 then return R2
+            ...
+            if What == Tn then return Rn
+            else return What
+        \endcode
+    */
+    template <typename What, typename... Pairs>
+    struct select {
+        typedef typename details::select< What, Pairs...>::type  type    ;   ///< Metafunction result
+    };
+
 }}  // namespace cds::opt
 
-#ifdef CDS_CXX11_VARIADIC_TEMPLATE_SUPPORT
-#   include <cds/opt/make_options_var.h>
-#else
-#   include <cds/opt/make_options_std.h>
-#endif
 
-#endif  // #ifndef __CDS_OPT_OPTIONS_H
+#endif  // #ifndef CDSLIB_OPT_OPTIONS_H