Tsigas' queue: replaced alignment option with padding one
[libcds.git] / cds / opt / options.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
29 */
30
31 #ifndef CDSLIB_OPT_OPTIONS_H
32 #define CDSLIB_OPT_OPTIONS_H
33
34 /*
35     Framework to define template options
36
37     Editions:
38         2011.01.23 khizmax  Created
39 */
40
41 #include <stdlib.h> // rand, srand
42
43 #include <cds/details/aligned_type.h>
44 #include <cds/user_setup/allocator.h>
45 #include <cds/user_setup/cache_line.h>
46 #include <cds/algo/atomic.h>
47
48 namespace cds {
49
50 /// Framework to define template options
51 /**
52     There are two kind of options:
53     - \p type-option - option that determines a data type. The template argument \p Type of the option is a type.
54     - \p value-option - option that determines a value. The template argument \p Value of the option is a value.
55 */
56 namespace opt {
57
58     /// Type indicates that an option is not specified and the default one should be used
59     struct none
60     {
61         //@cond
62         template <class Base> struct pack: public Base
63         {};
64         //@endcond
65     };
66
67     /// Metafunction for selecting default option value
68     /**
69         Template parameters:
70         - \p Option - option value
71         - \p Default - default option value
72         - \p Value - option value if \p Option is not opt::none
73
74         If \p Option is opt::none, the metafunction result is \p Default, otherwise
75         the result is \p Value.
76
77         Examples:
78         \code
79         // default_spin is cds::sync::spin
80         typedef typename cds::opt::select_default< cds::opt::none, cds::sync::spin >::type  default_spin;
81
82         // spin_32bit is cds::sync::reentrant_spin32
83         typedef typename cds::opt::select_default< cds::opt::none, cds::sync::reentrant_spin32 >::type  spin_32bit;
84         \endcode
85     */
86     template <typename Option, typename Default, typename Value = Option>
87     struct select_default
88     {
89         typedef Value type ;   ///< metafunction result
90     };
91     //@cond
92     template <typename Default>
93     struct select_default< none, Default >
94     {
95         typedef Default type;
96     };
97     //@endcond
98
99     /// Metafunction to select option value
100     /**
101         This metafunction is intended for extracting the value of the \p Option option.
102         For example,
103         \code
104         #include <cds/opt/options.h>
105         #include <type_traits> // only for testing purpose (static_assert)
106
107         struct tag_a;
108
109         // Define option
110         typedef cds::opt::tag< tag_a >  tag_option;
111
112         // What is the value of the tag_option?
113         // How we can extract tag_a from tag_option?
114         // Here is a solution:
115         typedef cds::opt::value< tag_option >::tag  tag_option_value;
116
117         // tag_option_value is the same as tag_a
118         static_assert( std::is_same< tag_option_value, tag_a >::value, "Error: tag_option_value != tag_a" );
119
120         \endcode
121     */
122     template <typename Option>
123     struct value: public Option::template pack<none>
124     {};
125
126
127     /// [type-option] Option setter specifies a tag
128     /**
129         Suppose, you have a struct
130         \code
131         struct Feature
132         {  .... };
133         \endcode
134         and you want that your class \p X would be derived from several \p Feature:
135         \code
136             class X: public Feature, public Feature
137             { .... };
138         \endcode
139
140         How can you distinguish one \p Feature from another?
141         You may use a tag option:
142         \code
143             template <typename Tag>
144             struct Feature
145             { .... };
146
147             class tag_a;
148             class tag_b;
149             class X: public Feature< tag_a >, public Feature< tag_b >
150             { .... };
151         \endcode
152         Now you can distinguish one \p Feature from another:
153         \code
154             X x;
155             Feature<tag_a>& fa = static_cast< Feature<tag_a> >( x );
156             Feature<tag_b>& fb = static_cast< Feature<tag_b> >( x );
157         \endcode
158
159         \p tag option setter allows you to do things like this for an option-centric approach:
160         \code
161         template <typename ...Options>
162         struct Feature
163         { .... };
164
165         class tag_a;
166         class tag_b;
167         class X: public Feature< tag<tag_a> >, public Feature< tag<tag_b> >
168         { .... };
169         \endcode
170
171         This option setter is widely used in cds::intrusive containers to distinguish
172         between different intrusive part of container's node.
173
174         An incomplete type can serve as a \p Tag.
175     */
176     template <typename Tag>
177     struct tag {
178         //@cond
179         template<class Base> struct pack: public Base
180         {
181             typedef Tag tag;
182         };
183         //@endcond
184     };
185
186     /// [type-option] Option setter specifies lock class
187     /**
188         Specification of the \p Type class is:
189         \code
190         struct Lock {
191             void lock();
192             void unlock();
193         };
194         \endcode
195     */
196     template <typename Type>
197     struct lock_type {
198         //@cond
199         template<class Base> struct pack: public Base
200         {
201             typedef Type lock_type;
202         };
203         //@endcond
204     };
205
206     /// [type-option] @ref cds_sync_monitor "Monitor" type setter
207     /**
208         This option setter specifyes @ref cds_sync_monitor "synchronization monitor"
209         for blocking container.
210     */
211     template <typename Type>
212     struct sync_monitor {
213         //@cond
214         template <class Base> struct pack : public Base
215         {
216             typedef Type sync_monitor;
217         };
218         //@endcond
219     };
220
221     /// [type-option] Back-off strategy option setter
222     /**
223         Back-off strategy used in some algorithm.
224         See cds::backoff namespace for back-off explanation and supported interface.
225     */
226     template <typename Type>
227     struct back_off {
228         //@cond
229         template <class Base> struct pack: public Base
230         {
231             typedef Type back_off;
232         };
233         //@endcond
234     };
235
236     /// [type-option] Option setter for garbage collecting schema used
237     /**
238         Possible values of \p GC template parameter are:
239         - cds::gc::HP - Hazard Pointer garbage collector
240         - cds::gc::DHP - Dynamic Hazard Pointer garbage collector
241         - cds::gc::none::GC - No garbage collector (not supported for some containers)
242     */
243     template <typename GC>
244     struct gc {
245         //@cond
246         template <class Base> struct pack: public Base
247         {
248             typedef GC gc;
249         };
250         //@endcond
251     };
252
253     /// [type-option] Option setter for an allocator
254     /**
255         \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
256         that, in turn, is \p std::allocator.
257
258         The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
259         you may specify any valid type as std::allocator's template parameter.
260
261         See also opt::node_allocator
262     */
263     template <typename Type>
264     struct allocator {
265         //@cond
266         template <typename Base> struct pack: public Base
267         {
268             typedef Type allocator;
269         };
270         //@endcond
271     };
272
273     /// [type-option] Option setter for node allocator
274     /**
275         \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
276         that, in turn, is \p std::allocator.
277
278         Many node-base containers require an allocator for maintaining data (container's node) and for internal use.
279         Sometimes, this types of allocator should be different for performance reason.
280         For example, we should like to allocate the node from a pool of preallocated nodes.
281         Such pool can be seen as the node allocator.
282
283         Usually, if a container supports \p opt::allocator and \p %opt::node_allocator options
284         and \p opt::node_allocator is not specified the \p %opt::allocator option is used for maintaining the nodes.
285
286         The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
287         you may specify any valid type as std::allocator's template parameter.
288     */
289     template <typename Type>
290     struct node_allocator {
291         //@cond
292             template <typename Base> struct pack: public Base
293             {
294                 typedef Type node_allocator;
295             };
296         //@endcond
297     };
298
299     /// [type-option] Option setter for item counting
300     /**
301         Some data structure (for example, queues) has additional feature for item counting.
302         This option allows to set up appropriate item counting policy for that data structure.
303
304         Predefined option \p Type:
305         - \p atomicity::empty_item_counter - no item counting performed. It is default policy for many
306             containers
307         - \p atomicity::item_counter - the class that provides atomically item counting
308         - \p opt::v::sequential_item_counter - simple non-atomic item counter. This item counter is not intended for
309             concurrent containers and may be used only if it is explicitly noted.
310
311         You may provide other implementation of \p atomicity::item_counter interface for your needs.
312
313         Note, the item counting in lock-free containers cannot be exact; for example, if
314         item counter for a container returns zero it is not mean that the container is empty.
315         Thus, the item counter may be used for statistical purposes only.
316     */
317     template <typename Type>
318     struct item_counter {
319         //@cond
320         template <typename Base> struct pack: public Base
321         {
322             typedef Type item_counter;
323         };
324         //@endcond
325     };
326
327     /// Special alignment constants for \ref cds::opt::alignment option
328     enum special_alignment {
329         no_special_alignment = 0,   ///< no special alignment
330         cache_line_alignment = 1    ///< use cache line size defined in cds/user_setup/cache_line.h
331     };
332
333     /// [value-option] Alignment option setter
334     /**
335         Alignment for some internal data of containers. May be useful to solve false sharing problem.
336         \p Value defines desired alignment and it may be power of two integer or predefined values from
337         \ref special_alignment enum.
338     */
339     template <unsigned int Value>
340     struct alignment {
341         //@cond
342         template <typename Base> struct pack: public Base
343         {
344             enum { alignment = Value };
345         };
346         //@endcond
347     };
348
349     //@cond
350     namespace details {
351         template <typename Type, unsigned int Alignment>
352         struct alignment_setter {
353             typedef typename cds::details::aligned_type< Type, Alignment >::type  type;
354         };
355
356         template <typename Type>
357         struct alignment_setter<Type, no_special_alignment> {
358             typedef Type type;
359         };
360
361         template <typename Type>
362         struct alignment_setter<Type, cache_line_alignment> {
363             typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type  type;
364         };
365     } // namespace details
366     //@endcond
367
368     /// Special padding constants for \p cds::opt::padding option
369     enum special_padding {
370         no_special_padding = 0,   ///< no special padding
371         cache_line_padding = 1,   ///< use cache line size defined in cds/user_setup/cache_line.h
372
373         /// Apply padding only for tiny data when data size is less than required padding
374         /**
375             The flag means that if your data size is less than the casheline size, the padding is applyed.
376             Otherwise no padding will be applyed.
377
378             This flag is applyed for padding value:
379             \code
380             cds::opt::padding< cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only >;
381             cds::opt::padding< 256 | cds::opt::padding_tiny_data_only >;
382             \endcode
383         */
384         padding_tiny_data_only = 0x80000000,
385
386         //@cond
387         padding_flags = padding_tiny_data_only
388         //@endcond
389     };
390
391     /// [value-option] Padding option setter
392     /**
393         The padding for the internal data of some containers. May be useful to solve false sharing problem.
394         \p Value defines desired padding and it may be power of two integer or predefined values from
395         \p special_padding enum.
396     */
397     template <unsigned int Value>
398     struct padding {
399         //@cond
400         template <typename Base> struct pack: public Base
401         {
402             enum { padding = Value };
403         };
404         //@endcond
405     };
406
407     //@cond
408     namespace details {
409         enum padding_vs_datasize {
410             padding_datasize_less,
411             padding_datasize_equal,
412             padding_datasize_greater
413         };
414
415         template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
416         struct apply_padding_helper;
417
418         template <typename T, padding_vs_datasize Relation, bool TinyOnly >
419         struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
420         {
421             struct type {
422                 T   data;
423             };
424             typedef void padding_type;
425         };
426
427         template <typename T, unsigned int Padding, bool TinyOnly >
428         struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
429         {
430             struct type {
431                 T   data;
432             };
433             typedef void padding_type;
434         };
435
436         template <typename T, unsigned int Padding, bool TinyOnly >
437         struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
438         {
439             typedef uint8_t padding_type[Padding - sizeof( T )];
440             struct type {
441                 T data;
442                 padding_type pad_;
443             };
444
445         };
446
447         template <typename T, unsigned int Padding >
448         struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
449         {
450             typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
451             struct type {
452                 T data;
453                 padding_type pad_;
454             };
455         };
456
457         template <typename T, unsigned int Padding >
458         struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
459         {
460             struct type {
461                 T data;
462             };
463             typedef void padding_type;
464         };
465
466         template <typename T, unsigned int Padding >
467         struct apply_padding
468         {
469         private:
470             enum { padding = Padding & ~padding_flags };
471
472         public:
473             static CDS_CONSTEXPR const size_t c_nPadding =
474                 static_cast<unsigned int>(padding) == static_cast<unsigned int>(cache_line_padding) ? cds::c_nCacheLineSize :
475                 static_cast<unsigned int>(padding) == static_cast<unsigned int>(no_special_padding) ? 0 : padding;
476
477             static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
478
479             typedef apply_padding_helper< T,
480                 c_nPadding,
481                 c_nPadding == 0,
482                 sizeof( T ) < c_nPadding ? padding_datasize_less : sizeof( T ) == c_nPadding ? padding_datasize_equal : padding_datasize_greater,
483                 (Padding & padding_tiny_data_only) != 0
484             > result;
485
486             typedef typename result::type type;
487
488             typedef typename std::conditional<
489                 std::is_same< typename result::padding_type, void >::value,
490                 unsigned int,
491                 typename result::padding_type
492             >::type padding_type;
493         };
494
495     } // namespace details
496     //@endcond
497
498
499     /// [type-option] Generic option setter for statisitcs
500     /**
501         This option sets a type to gather statistics.
502         The option is generic - no predefined type(s) is provided.
503         The particular \p Type of statistics depends on internal structure of the object.
504     */
505     template <typename Type>
506     struct stat {
507         //@cond
508         template <typename Base> struct pack: public Base
509         {
510             typedef Type stat;
511         };
512         //@endcond
513     };
514
515     /// [type-option] Option setter for C++ memory model
516     /**
517         The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
518         - \p v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
519             \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
520         - \p v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
521             this mode any memory ordering constraint maps to \p memory_order_seq_cst.
522
523         The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
524
525         You may mix different memory ordering options for different containers: one declare as sequentially consistent,
526         another declare as relaxed.
527         Usually, \p v::relaxed_ordering is the default memory ordering for <b>libcds</b> containers.
528     */
529     template <typename Type>
530     struct memory_model {
531         //@cond
532         template <typename Base> struct pack: public Base
533         {
534             typedef Type memory_model;
535         };
536         //@endcond
537     };
538
539     /// [type-option] Base type traits option setter
540     /**
541         This option setter is intended generally for internal use for type rebinding.
542     */
543     template <typename Type>
544     struct type_traits {
545         //@cond
546         template <typename Base> struct pack: public Base
547         {
548             typedef Type type_traits;
549         };
550         //@endcond
551     };
552
553     /// Resizing policy option
554     /**
555         This option specifies the resizing policy that decides when to resize a container.
556         Used in some containers, for example, in container::StripedHashSet, intrusive::StripedHashSet.
557
558         The real resizing policy specified by \p Type does strongly depend on a container
559         that supports this option, see container documentation about possibly \p Type values.
560     */
561     template <typename Type>
562     struct resizing_policy {
563         //@cond
564         template <typename Base> struct pack: public Base
565         {
566             typedef Type resizing_policy;
567         };
568         //@endcond
569     };
570
571     /// Copy policy option
572     /**
573         The copy policy defines an item copying algorithm which is used, for example, when a container is resized.
574         It is very specific algorithm depending on type of the container.
575     */
576     template <typename Type>
577     struct copy_policy {
578         //@cond
579         template <typename Base> struct pack: public Base
580         {
581             typedef Type copy_policy;
582         };
583         //@endcond
584     };
585
586     /// Swap policy option
587     /**
588         The swap policy specifies an algorithm for swapping two objects.
589         Usually, the default policy is \p std::swap (see opt::v::default_swap_policy):
590
591         @code
592         struct std_swap {
593             template <typename T>
594             void operator ()( T& v1, T& v2 )
595             {
596                 std::swap( v1, v2 );
597             }
598         };
599         @endcode
600     */
601     template <typename Type>
602     struct swap_policy {
603         //@cond
604         template <typename Base> struct pack: public Base
605         {
606             typedef Type swap_policy;
607         };
608         //@endcond
609     };
610
611     /// Move policy option
612     /**
613         The move policy specifies an algorithm for moving object content.
614         In trivial case, it can be simple assignment.
615
616         The move interface is:
617         \code
618         template <typename T>
619         struct move_policy {
620             void operator()( T& dest, T& src );
621         };
622         \endcode
623
624         Note that in move algorithm the \p src source argument can be changed too.
625         So you can use move semantics.
626
627         Usually, the default move policy is opt::v::assignment_move_policy
628     */
629     template <typename Type>
630     struct move_policy {
631         //@cond
632         template <typename Base> struct pack: public Base
633         {
634             typedef Type move_policy;
635         };
636         //@endcond
637     };
638
639     /// [value-option] Enable sorting
640     /**
641         This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
642         sorting of a container.
643     */
644     template <bool Enable>
645     struct sort {
646         //@cond
647         template <typename Base> struct pack: public Base
648         {
649             static bool const sort = Enable;
650         };
651         //@endcond
652     };
653
654     /// [type-option] Concurrent access policy
655     /**
656         This option specifies synchronization strategy for fine-grained lock-based containers.
657         The option has no predefined \p Policy type.
658         For each container that accepts this option the range of available \p Policy types
659         is unique.
660     */
661     template <typename Policy>
662     struct mutex_policy {
663         //@cond
664         template <typename Base> struct pack: public Base
665         {
666             typedef Policy mutex_policy;
667         };
668         //@endcond
669     };
670
671
672     /// [type-option] Random number generator
673     /**
674         The option specifies a random number generator.
675         \p Random can be any STL random number generator producing
676         unsigned integer: \p std::linear_congruential_engine,
677         \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
678         and so on, or \p opt::v::c_rand.
679
680     */
681     template <typename Random>
682     struct random_engine {
683         //@cond
684         template <typename Base> struct pack: public Base
685         {
686             typedef Random random_engine;
687         };
688         //@endcond
689     };
690
691     //@cond
692     // For internal use
693     template <typename Accessor>
694     struct key_accessor {
695         template <typename Base> struct pack: public Base
696         {
697             typedef Accessor key_accessor;
698         };
699     };
700
701     template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
702     struct replace_key_accessor {
703         typedef typename std::conditional<
704             std::is_same< typename Traits::key_accessor, WhatReplace >::value,
705             typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
706             Traits
707         >::type type;
708     };
709     //@endcond
710
711 }}  // namespace cds::opt
712
713
714 // ****************************************************
715 // Options predefined types and values
716
717 namespace cds { namespace opt {
718
719     /// Predefined options value
720     namespace v {
721
722         /// Sequential non-atomic item counter
723         /**
724             This type of \p opt::item_counter option is not intended for concurrent containers
725             and may be used only if it is explicitly noted.
726         */
727         class sequential_item_counter
728         {
729         public:
730             typedef size_t counter_type    ;  ///< Counter type
731         protected:
732             counter_type  m_nCounter ;      ///< Counter
733
734         public:
735             sequential_item_counter()
736                 : m_nCounter(0)
737             {}
738
739             /// Returns current value of the counter
740             counter_type    value() const
741             {
742                 return m_nCounter;
743             }
744
745             /// Same as \ref value() with relaxed memory ordering
746             operator counter_type() const
747             {
748                 return value();
749             }
750
751             /// Increments the counter. Semantics: postincrement
752             counter_type inc()
753             {
754                 return m_nCounter++;
755             }
756
757             /// Decrements the counter. Semantics: postdecrement
758             counter_type dec()
759             {
760                 return m_nCounter--;
761             }
762
763             /// Preincrement
764             counter_type operator ++()
765             {
766                 return inc() + 1;
767             }
768             /// Postincrement
769             counter_type operator ++(int)
770             {
771                 return inc();
772             }
773
774             /// Predecrement
775             counter_type operator --()
776             {
777                 return dec() - 1;
778             }
779             /// Postdecrement
780             counter_type operator --(int)
781             {
782                 return dec();
783             }
784
785             /// Resets count to 0
786             void reset()
787             {
788                 m_nCounter = 0;
789             }
790         };
791
792         /// Relaxed memory ordering \p opt::memory_model
793         /**
794             In this ordering the memory constraints are defined according to C++ Memory Model specification:
795             each constraint is mapped to \p std::memory_order constraints one-to-one
796         */
797         struct relaxed_ordering {
798             //@cond
799             static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_relaxed;
800             static const atomics::memory_order memory_order_consume    = atomics::memory_order_consume;
801             static const atomics::memory_order memory_order_acquire    = atomics::memory_order_acquire;
802             static const atomics::memory_order memory_order_release    = atomics::memory_order_release;
803             static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_acq_rel;
804             static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
805             //@endcond
806         };
807
808         /// Sequential consistent \p opt::memory_memory ordering
809         /**
810             In this memory model any memory constraint is equivalent to \p std::memory_order_seq_cst.
811         */
812         struct sequential_consistent {
813             //@cond
814             static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_seq_cst;
815             static const atomics::memory_order memory_order_consume    = atomics::memory_order_seq_cst;
816             static const atomics::memory_order memory_order_acquire    = atomics::memory_order_seq_cst;
817             static const atomics::memory_order memory_order_release    = atomics::memory_order_seq_cst;
818             static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_seq_cst;
819             static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_seq_cst;
820             //@endcond
821         };
822
823         //@cond
824         /// Totally relaxed \p opt::memory_model ordering (do not use!)
825         /**
826             In this memory model any memory constraint is equivalent to \p std::memory_order_relaxed.
827             @warning Do not use this model! It intended for testing purposes only
828             to verify debugging instruments like Thread Sanitizer.
829         */
830         struct total_relaxed_ordering {
831             static const atomics::memory_order memory_order_relaxed    = atomics::memory_order_relaxed;
832             static const atomics::memory_order memory_order_consume    = atomics::memory_order_relaxed;
833             static const atomics::memory_order memory_order_acquire    = atomics::memory_order_relaxed;
834             static const atomics::memory_order memory_order_release    = atomics::memory_order_relaxed;
835             static const atomics::memory_order memory_order_acq_rel    = atomics::memory_order_relaxed;
836             static const atomics::memory_order memory_order_seq_cst    = atomics::memory_order_relaxed;
837         };
838         //@endcond
839
840
841         /// Default swap policy for \p opt::swap_policy option
842         /**
843             The default swap policy is wrappr around \p std::swap algorithm.
844         */
845         struct default_swap_policy {
846             /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
847             template <typename T>
848             void operator()( T& v1, T& v2 ) const
849             {
850                 std::swap( v1, v2 );
851             }
852         };
853
854         /// \p opt::move_policy based on move-assignment operator
855         struct assignment_move_policy
856         {
857             /// <tt> dest = std::move( src ) </tt>
858             template <typename T>
859             void operator()( T& dest, T&& src ) const
860             {
861                 dest = std::move( src );
862             }
863         };
864
865         /// \p rand() -base random number generator for \p opt::random_engine
866         /**
867             This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
868         */
869         struct c_rand {
870             typedef unsigned int result_type; ///< Result type
871
872             /// Constructor initializes object calling \p srand()
873             c_rand()
874             {
875                 srand(1);
876             }
877
878             /// Returns next random number calling \p rand()
879             result_type operator()()
880             {
881                 return (result_type) rand();
882             }
883         };
884
885     } // namespace v
886
887 }} // namespace cds::opt
888
889
890 // ****************************************************
891 // Options metafunctions
892
893 namespace cds { namespace opt {
894
895     //@cond
896     namespace details {
897         template <typename OptionList, typename Option>
898         struct do_pack
899         {
900             // Use "pack" member template to pack options
901             typedef typename Option::template pack<OptionList> type;
902         };
903
904         template <typename ...T> class typelist;
905
906         template <typename Typelist> struct typelist_head;
907         template <typename Head, typename ...Tail>
908         struct typelist_head< typelist<Head, Tail...> > {
909             typedef Head type;
910         };
911         template <typename Head>
912         struct typelist_head< typelist<Head> > {
913             typedef Head type;
914         };
915
916         template <typename Typelist> struct typelist_tail;
917         template <typename Head, typename ...Tail>
918         struct typelist_tail< typelist<Head, Tail...> > {
919             typedef typelist<Tail...> type;
920         };
921         template <typename Head>
922         struct typelist_tail< typelist<Head> > {
923             typedef typelist<> type;
924         };
925
926         template <typename OptionList, typename Typelist>
927         struct make_options_impl {
928             typedef typename make_options_impl<
929                 typename do_pack<
930                     OptionList,
931                     typename typelist_head< Typelist >::type
932                 >::type,
933                 typename typelist_tail<Typelist>::type
934             >::type type;
935         };
936
937         template <typename OptionList>
938         struct make_options_impl<OptionList, typelist<> > {
939             typedef OptionList type;
940         };
941     }   // namespace details
942     //@endcond
943
944     /// make_options metafunction
945     /** @headerfile cds/opt/options.h
946
947         The metafunction converts option list \p Options to traits structure.
948         The result of metafunction is \p type.
949
950         Template parameter \p OptionList is default option set (default traits).
951         \p Options is option list.
952     */
953     template <typename OptionList, typename... Options>
954     struct make_options {
955 #ifdef CDS_DOXYGEN_INVOKED
956         typedef implementation_defined type ;   ///< Result of the metafunction
957 #else
958         typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
959 #endif
960     };
961
962
963     // *****************************************************************
964     // find_type_traits metafunction
965     // *****************************************************************
966
967     //@cond
968     namespace details {
969         template <typename... Options>
970         struct find_type_traits_option;
971
972         template <>
973         struct find_type_traits_option<> {
974             typedef cds::opt::none  type;
975         };
976
977         template <typename Any>
978         struct find_type_traits_option< Any > {
979             typedef cds::opt::none type;
980         };
981
982         template <typename Any>
983         struct find_type_traits_option< cds::opt::type_traits< Any > > {
984             typedef Any type;
985         };
986
987         template <typename Any, typename... Options>
988         struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
989             typedef Any type;
990         };
991
992         template <typename Any, typename... Options>
993         struct find_type_traits_option< Any, Options... > {
994             typedef typename find_type_traits_option< Options... >::type type;
995         };
996     } // namespace details
997     //@endcond
998
999     /// Metafunction to find opt::type_traits option in \p Options list
1000     /** @headerfile cds/opt/options.h
1001
1002         If \p Options contains \p opt::type_traits option then it is the metafunction result.
1003         Otherwise the result is \p DefaultOptons.
1004     */
1005     template <typename DefaultOptions, typename... Options>
1006     struct find_type_traits {
1007         typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ;  ///< Metafunction result
1008     };
1009
1010
1011     // *****************************************************************
1012     // find_option metafunction
1013     // *****************************************************************
1014
1015     //@cond
1016     namespace details {
1017         template <typename What, typename... Options>
1018         struct find_option;
1019
1020         struct compare_ok;
1021         struct compare_fail;
1022
1023         template <typename A, typename B>
1024         struct compare_option
1025         {
1026             typedef compare_fail type;
1027         };
1028
1029         template <template <typename> class Opt, typename A, typename B>
1030         struct compare_option< Opt<A>, Opt<B> >
1031         {
1032             typedef compare_ok   type;
1033         };
1034
1035         // Specializations for integral type of option
1036 #define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
1037         struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
1038
1039         // For user-defined enum types
1040 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
1041
1042         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
1043         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
1044         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
1045         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
1046         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
1047         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
1048         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
1049         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
1050         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
1051         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
1052         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
1053         CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
1054
1055
1056         template <typename CompResult, typename Ok, typename Fail>
1057         struct select_option
1058         {
1059             typedef Fail    type;
1060         };
1061
1062         template <typename Ok, typename Fail>
1063         struct select_option< compare_ok, Ok, Fail >
1064         {
1065             typedef Ok      type;
1066         };
1067
1068         template <typename What>
1069         struct find_option< What > {
1070             typedef What    type;
1071         };
1072
1073         template <typename What, typename Opt>
1074         struct find_option< What, Opt > {
1075             typedef typename select_option<
1076                 typename compare_option< What, Opt >::type
1077                 ,Opt
1078                 ,What
1079             >::type type;
1080         };
1081
1082         template <typename What, typename Opt, typename... Options>
1083         struct find_option< What, Opt, Options... > {
1084             typedef typename select_option<
1085                 typename compare_option< What, Opt >::type
1086                 ,Opt
1087                 ,typename find_option< What, Options... >::type
1088             >::type type;
1089         };
1090     } // namespace details
1091     //@endcond
1092
1093     /// Metafunction to find \p What option in \p Options list
1094     /** @headerfile cds/opt/options.h
1095
1096         If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
1097         Otherwise the result is \p What.
1098
1099         Example:
1100         \code
1101         #include <cds/opt/options.h>
1102         namespace co = cds::opt;
1103
1104         struct default_tag;
1105         struct tag_a;
1106         struct tag_b;
1107
1108         // Find option co::tag.
1109
1110         // res1 is co::tag< tag_a >
1111         typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
1112
1113         // res2 is default co::tag< default_tag >
1114         typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
1115
1116         // Multiple option co::tag. The first option is selected
1117         // res3 is default co::tag< tag_a >
1118         typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
1119
1120         \endcode
1121     */
1122     template <typename What, typename... Options>
1123     struct find_option {
1124         typedef typename details::find_option<What, Options...>::type   type ;  ///< Metafunction result
1125     };
1126
1127
1128     // *****************************************************************
1129     // select metafunction
1130     // *****************************************************************
1131
1132     //@cond
1133     namespace details {
1134
1135         template <typename What, typename... Pairs>
1136         struct select;
1137
1138         template <typename What, typename Value>
1139         struct select< What, What, Value>
1140         {
1141             typedef Value   type;
1142         };
1143
1144         template <typename What, typename Tag, typename Value>
1145         struct select<What, Tag, Value>
1146         {
1147             typedef What    type;
1148         };
1149
1150         template <typename What, typename Value, typename... Pairs>
1151         struct select< What, What, Value, Pairs...>
1152         {
1153             typedef Value   type;
1154         };
1155
1156         template <typename What, typename Tag, typename Value, typename... Pairs>
1157         struct select< What, Tag, Value, Pairs...>
1158         {
1159             typedef typename select<What, Pairs...>::type   type;
1160         };
1161     }   // namespace details
1162     //@endcond
1163
1164     /// Select option metafunction
1165     /** @headerfile cds/opt/options.h
1166
1167         Pseudocode:
1168         \code
1169         select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
1170             if What == T1 then return R1
1171             if What == T2 then return R2
1172             ...
1173             if What == Tn then return Rn
1174             else return What
1175         \endcode
1176     */
1177     template <typename What, typename... Pairs>
1178     struct select {
1179         typedef typename details::select< What, Pairs...>::type  type    ;   ///< Metafunction result
1180     };
1181
1182 }}  // namespace cds::opt
1183
1184
1185 #endif  // #ifndef CDSLIB_OPT_OPTIONS_H