2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSLIB_OPT_OPTIONS_H
32 #define CDSLIB_OPT_OPTIONS_H
35 Framework to define template options
38 2011.01.23 khizmax Created
41 #include <cstdlib> // rand, srand
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>
50 /// Framework to define template options
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.
58 /// Type indicates that an option is not specified and the default one should be used
62 template <class Base> struct pack: public Base
67 /// Metafunction for selecting default option value
70 - \p Option - option value
71 - \p Default - default option value
72 - \p Value - option value if \p Option is not opt::none
74 If \p Option is opt::none, the metafunction result is \p Default, otherwise
75 the result is \p Value.
79 // default_spin is cds::sync::spin
80 typedef typename cds::opt::select_default< cds::opt::none, cds::sync::spin >::type default_spin;
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;
86 template <typename Option, typename Default, typename Value = Option>
89 typedef Value type ; ///< metafunction result
92 template <typename Default>
93 struct select_default< none, Default >
99 /// Metafunction to select option value
101 This metafunction is intended for extracting the value of the \p Option option.
104 #include <cds/opt/options.h>
105 #include <type_traits> // only for testing purpose (static_assert)
110 typedef cds::opt::tag< tag_a > tag_option;
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;
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" );
122 template <typename Option>
123 struct value: public Option::template pack<none>
127 /// [type-option] Option setter specifies a tag
129 Suppose, you have a struct
134 and you want that your class \p X would be derived from several \p Feature:
136 class X: public Feature, public Feature
140 How can you distinguish one \p Feature from another?
141 You may use a tag option:
143 template <typename Tag>
149 class X: public Feature< tag_a >, public Feature< tag_b >
152 Now you can distinguish one \p Feature from another:
155 Feature<tag_a>& fa = static_cast< Feature<tag_a> >( x );
156 Feature<tag_b>& fb = static_cast< Feature<tag_b> >( x );
159 \p tag option setter allows you to do things like this for an option-centric approach:
161 template <typename ...Options>
167 class X: public Feature< tag<tag_a> >, public Feature< tag<tag_b> >
171 This option setter is widely used in cds::intrusive containers to distinguish
172 between different intrusive part of container's node.
174 An incomplete type can serve as a \p Tag.
176 template <typename Tag>
179 template<class Base> struct pack: public Base
186 /// [type-option] Option setter specifies lock class
188 Specification of the \p Type class is:
196 template <typename Type>
199 template<class Base> struct pack: public Base
201 typedef Type lock_type;
206 /// [type-option] @ref cds_sync_monitor "Monitor" type setter
208 This option setter specifyes @ref cds_sync_monitor "synchronization monitor"
209 for blocking container.
211 template <typename Type>
212 struct sync_monitor {
214 template <class Base> struct pack : public Base
216 typedef Type sync_monitor;
221 /// [type-option] Back-off strategy option setter
223 Back-off strategy used in some algorithm.
224 See cds::backoff namespace for back-off explanation and supported interface.
226 template <typename Type>
229 template <class Base> struct pack: public Base
231 typedef Type back_off;
236 /// [type-option] Option setter for garbage collecting schema used
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)
243 template <typename GC>
246 template <class Base> struct pack: public Base
253 /// [type-option] Option setter for an allocator
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.
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.
261 See also opt::node_allocator
263 template <typename Type>
266 template <typename Base> struct pack: public Base
268 typedef Type allocator;
273 /// [type-option] Option setter for node allocator
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.
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.
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.
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.
289 template <typename Type>
290 struct node_allocator {
292 template <typename Base> struct pack: public Base
294 typedef Type node_allocator;
299 /// [type-option] Option setter for item counting
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.
304 Predefined option \p Type:
305 - \p atomicity::empty_item_counter - no item counting performed. It is default policy for many
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.
311 You may provide other implementation of \p atomicity::item_counter interface for your needs.
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.
317 template <typename Type>
318 struct item_counter {
320 template <typename Base> struct pack: public Base
322 typedef Type item_counter;
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
333 /// [value-option] Alignment option setter
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.
339 template <unsigned int Value>
342 template <typename Base> struct pack: public Base
344 enum { alignment = Value };
351 template <typename Type, unsigned int Alignment>
352 struct alignment_setter {
353 typedef typename cds::details::aligned_type< Type, Alignment >::type type;
356 template <typename Type>
357 struct alignment_setter<Type, no_special_alignment> {
361 template <typename Type>
362 struct alignment_setter<Type, cache_line_alignment> {
363 typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type type;
365 } // namespace details
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
373 /// Apply padding only for tiny data when data size is less than required padding
375 The flag means that if your data size is less than the cacheline size, the padding is applyed.
376 Otherwise no padding will be applyed.
378 This flag is applyed for padding value:
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 >;
384 padding_tiny_data_only = 0x80000000,
387 padding_flags = padding_tiny_data_only
391 /// [value-option] Padding option setter
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.
397 template <unsigned int Value>
400 template <typename Base> struct pack: public Base
402 enum { padding = Value };
408 template <unsigned Padding>
409 struct actual_padding
411 enum { value = Padding & ~padding_flags };
415 struct actual_padding<cache_line_padding>
417 enum { value = cds::c_nCacheLineSize };
421 struct actual_padding<cache_line_padding| padding_tiny_data_only>
423 enum { value = cds::c_nCacheLineSize };
429 enum padding_vs_datasize {
430 padding_datasize_less,
431 padding_datasize_equal,
432 padding_datasize_greater
435 template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
436 struct apply_padding_helper;
438 template <typename T, padding_vs_datasize Relation, bool TinyOnly >
439 struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
444 typedef void padding_type;
447 template <typename T, unsigned int Padding, bool TinyOnly >
448 struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
453 typedef void padding_type;
456 template <typename T, unsigned int Padding, bool TinyOnly >
457 struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
459 typedef uint8_t padding_type[Padding - sizeof( T )];
467 template <typename T, unsigned int Padding >
468 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
470 typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
477 template <typename T, unsigned int Padding >
478 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
483 typedef void padding_type;
486 template <typename T, unsigned int Padding >
490 enum { padding = Padding & ~padding_flags };
493 static CDS_CONSTEXPR const size_t c_nPadding =
494 static_cast<unsigned int>(padding) == static_cast<unsigned int>(cache_line_padding) ? cds::c_nCacheLineSize :
495 static_cast<unsigned int>(padding) == static_cast<unsigned int>(no_special_padding) ? 0 : padding;
497 static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
499 typedef apply_padding_helper< T,
502 sizeof( T ) < c_nPadding ? padding_datasize_less : sizeof( T ) == c_nPadding ? padding_datasize_equal : padding_datasize_greater,
503 (Padding & padding_tiny_data_only) != 0
506 typedef typename result::type type;
508 typedef typename std::conditional<
509 std::is_same< typename result::padding_type, void >::value,
511 typename result::padding_type
512 >::type padding_type;
515 } // namespace details
519 /// [type-option] Generic option setter for statisitcs
521 This option sets a type to gather statistics.
522 The option is generic - no predefined type(s) is provided.
523 The particular \p Type of statistics depends on internal structure of the object.
525 template <typename Type>
528 template <typename Base> struct pack: public Base
535 /// [type-option] Option setter for C++ memory model
537 The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
538 - \p v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
539 \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
540 - \p v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
541 this mode any memory ordering constraint maps to \p memory_order_seq_cst.
543 The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
545 You may mix different memory ordering options for different containers: one declare as sequentially consistent,
546 another declare as relaxed.
547 Usually, \p v::relaxed_ordering is the default memory ordering for <b>libcds</b> containers.
549 template <typename Type>
550 struct memory_model {
552 template <typename Base> struct pack: public Base
554 typedef Type memory_model;
559 /// [type-option] Base type traits option setter
561 This option setter is intended generally for internal use for type rebinding.
563 template <typename Type>
566 template <typename Base> struct pack: public Base
568 typedef Type type_traits;
573 /// Resizing policy option
575 This option specifies the resizing policy that decides when to resize a container.
576 Used in some containers, for example, in container::StripedHashSet, intrusive::StripedHashSet.
578 The real resizing policy specified by \p Type does strongly depend on a container
579 that supports this option, see container documentation about possibly \p Type values.
581 template <typename Type>
582 struct resizing_policy {
584 template <typename Base> struct pack: public Base
586 typedef Type resizing_policy;
591 /// Copy policy option
593 The copy policy defines an item copying algorithm which is used, for example, when a container is resized.
594 It is very specific algorithm depending on type of the container.
596 template <typename Type>
599 template <typename Base> struct pack: public Base
601 typedef Type copy_policy;
606 /// Swap policy option
608 The swap policy specifies an algorithm for swapping two objects.
609 Usually, the default policy is \p std::swap (see opt::v::default_swap_policy):
613 template <typename T>
614 void operator ()( T& v1, T& v2 )
621 template <typename Type>
624 template <typename Base> struct pack: public Base
626 typedef Type swap_policy;
631 /// Move policy option
633 The move policy specifies an algorithm for moving object content.
634 In trivial case, it can be simple assignment.
636 The move interface is:
638 template <typename T>
640 void operator()( T& dest, T& src );
644 Note that in move algorithm the \p src source argument can be changed too.
645 So you can use move semantics.
647 Usually, the default move policy is opt::v::assignment_move_policy
649 template <typename Type>
652 template <typename Base> struct pack: public Base
654 typedef Type move_policy;
659 /// [value-option] Enable sorting
661 This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
662 sorting of a container.
664 template <bool Enable>
667 template <typename Base> struct pack: public Base
669 static bool const sort = Enable;
674 /// [type-option] Concurrent access policy
676 This option specifies synchronization strategy for fine-grained lock-based containers.
677 The option has no predefined \p Policy type.
678 For each container that accepts this option the range of available \p Policy types
681 template <typename Policy>
682 struct mutex_policy {
684 template <typename Base> struct pack: public Base
686 typedef Policy mutex_policy;
692 /// [type-option] Random number generator
694 The option specifies a random number generator.
695 \p Random can be any STL random number generator producing
696 unsigned integer: \p std::linear_congruential_engine,
697 \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
698 and so on, or \p opt::v::c_rand.
701 template <typename Random>
702 struct random_engine {
704 template <typename Base> struct pack: public Base
706 typedef Random random_engine;
711 /// [type-option] Free-list implementation
713 See \p cds::intrusive::FreeList for free-list interface
715 template <typename FreeList>
718 template <typename Base> struct pack: public Base
720 typedef FreeList free_list;
727 template <typename Accessor>
728 struct key_accessor {
729 template <typename Base> struct pack: public Base
731 typedef Accessor key_accessor;
735 template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
736 struct replace_key_accessor {
737 typedef typename std::conditional<
738 std::is_same< typename Traits::key_accessor, WhatReplace >::value,
739 typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
745 }} // namespace cds::opt
748 // ****************************************************
749 // Options predefined types and values
751 namespace cds { namespace opt {
753 /// Predefined options value
756 /// Sequential non-atomic item counter
758 This type of \p opt::item_counter option is not intended for concurrent containers
759 and may be used only if it is explicitly noted.
761 class sequential_item_counter
764 typedef size_t counter_type ; ///< Counter type
766 counter_type m_nCounter ; ///< Counter
769 sequential_item_counter()
773 /// Returns current value of the counter
774 counter_type value() const
779 /// Same as \ref value() with relaxed memory ordering
780 operator counter_type() const
785 /// Increments the counter. Semantics: postincrement
791 /// Decrements the counter. Semantics: postdecrement
798 counter_type operator ++()
803 counter_type operator ++(int)
809 counter_type operator --()
814 counter_type operator --(int)
819 /// Resets count to 0
826 /// Relaxed memory ordering \p opt::memory_model
828 In this ordering the memory constraints are defined according to C++ Memory Model specification:
829 each constraint is mapped to \p std::memory_order constraints one-to-one
831 struct relaxed_ordering {
833 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
834 static const atomics::memory_order memory_order_consume = atomics::memory_order_consume;
835 static const atomics::memory_order memory_order_acquire = atomics::memory_order_acquire;
836 static const atomics::memory_order memory_order_release = atomics::memory_order_release;
837 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_acq_rel;
838 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
842 /// Sequential consistent \p opt::memory_memory ordering
844 In this memory model any memory constraint is equivalent to \p std::memory_order_seq_cst.
846 struct sequential_consistent {
848 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_seq_cst;
849 static const atomics::memory_order memory_order_consume = atomics::memory_order_seq_cst;
850 static const atomics::memory_order memory_order_acquire = atomics::memory_order_seq_cst;
851 static const atomics::memory_order memory_order_release = atomics::memory_order_seq_cst;
852 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_seq_cst;
853 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
858 /// Totally relaxed \p opt::memory_model ordering (do not use!)
860 In this memory model any memory constraint is equivalent to \p std::memory_order_relaxed.
861 @warning Do not use this model! It intended for testing purposes only
862 to verify debugging instruments like Thread Sanitizer.
864 struct total_relaxed_ordering {
865 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
866 static const atomics::memory_order memory_order_consume = atomics::memory_order_relaxed;
867 static const atomics::memory_order memory_order_acquire = atomics::memory_order_relaxed;
868 static const atomics::memory_order memory_order_release = atomics::memory_order_relaxed;
869 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_relaxed;
870 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_relaxed;
875 /// Default swap policy for \p opt::swap_policy option
877 The default swap policy is wrappr around \p std::swap algorithm.
879 struct default_swap_policy {
880 /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
881 template <typename T>
882 void operator()( T& v1, T& v2 ) const
888 /// \p opt::move_policy based on move-assignment operator
889 struct assignment_move_policy
891 /// <tt> dest = std::move( src ) </tt>
892 template <typename T>
893 void operator()( T& dest, T&& src ) const
895 dest = std::move( src );
899 /// \p rand() -base random number generator for \p opt::random_engine
901 This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
904 typedef unsigned int result_type; ///< Result type
906 /// Constructor initializes object calling \p std::srand()
912 /// Returns next random number calling \p std::rand()
913 result_type operator()()
915 return (result_type) std::rand();
920 }} // namespace cds::opt
923 // ****************************************************
924 // Options metafunctions
926 namespace cds { namespace opt {
930 template <typename OptionList, typename Option>
933 // Use "pack" member template to pack options
934 typedef typename Option::template pack<OptionList> type;
937 template <typename ...T> class typelist;
939 template <typename Typelist> struct typelist_head;
940 template <typename Head, typename ...Tail>
941 struct typelist_head< typelist<Head, Tail...> > {
944 template <typename Head>
945 struct typelist_head< typelist<Head> > {
949 template <typename Typelist> struct typelist_tail;
950 template <typename Head, typename ...Tail>
951 struct typelist_tail< typelist<Head, Tail...> > {
952 typedef typelist<Tail...> type;
954 template <typename Head>
955 struct typelist_tail< typelist<Head> > {
956 typedef typelist<> type;
959 template <typename OptionList, typename Typelist>
960 struct make_options_impl {
961 typedef typename make_options_impl<
964 typename typelist_head< Typelist >::type
966 typename typelist_tail<Typelist>::type
970 template <typename OptionList>
971 struct make_options_impl<OptionList, typelist<> > {
972 typedef OptionList type;
974 } // namespace details
977 /// make_options metafunction
978 /** @headerfile cds/opt/options.h
980 The metafunction converts option list \p Options to traits structure.
981 The result of metafunction is \p type.
983 Template parameter \p OptionList is default option set (default traits).
984 \p Options is option list.
986 template <typename OptionList, typename... Options>
987 struct make_options {
988 #ifdef CDS_DOXYGEN_INVOKED
989 typedef implementation_defined type ; ///< Result of the metafunction
991 typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
996 // *****************************************************************
997 // find_type_traits metafunction
998 // *****************************************************************
1002 template <typename... Options>
1003 struct find_type_traits_option;
1006 struct find_type_traits_option<> {
1007 typedef cds::opt::none type;
1010 template <typename Any>
1011 struct find_type_traits_option< Any > {
1012 typedef cds::opt::none type;
1015 template <typename Any>
1016 struct find_type_traits_option< cds::opt::type_traits< Any > > {
1020 template <typename Any, typename... Options>
1021 struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
1025 template <typename Any, typename... Options>
1026 struct find_type_traits_option< Any, Options... > {
1027 typedef typename find_type_traits_option< Options... >::type type;
1029 } // namespace details
1032 /// Metafunction to find opt::type_traits option in \p Options list
1033 /** @headerfile cds/opt/options.h
1035 If \p Options contains \p opt::type_traits option then it is the metafunction result.
1036 Otherwise the result is \p DefaultOptons.
1038 template <typename DefaultOptions, typename... Options>
1039 struct find_type_traits {
1040 typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ; ///< Metafunction result
1044 // *****************************************************************
1045 // find_option metafunction
1046 // *****************************************************************
1050 template <typename What, typename... Options>
1054 struct compare_fail;
1056 template <typename A, typename B>
1057 struct compare_option
1059 typedef compare_fail type;
1062 template <template <typename> class Opt, typename A, typename B>
1063 struct compare_option< Opt<A>, Opt<B> >
1065 typedef compare_ok type;
1068 // Specializations for integral type of option
1069 #define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
1070 struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
1072 // For user-defined enum types
1073 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
1075 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
1076 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
1077 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
1078 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
1079 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
1080 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
1081 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
1082 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
1083 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
1084 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
1085 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
1086 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
1089 template <typename CompResult, typename Ok, typename Fail>
1090 struct select_option
1095 template <typename Ok, typename Fail>
1096 struct select_option< compare_ok, Ok, Fail >
1101 template <typename What>
1102 struct find_option< What > {
1106 template <typename What, typename Opt>
1107 struct find_option< What, Opt > {
1108 typedef typename select_option<
1109 typename compare_option< What, Opt >::type
1115 template <typename What, typename Opt, typename... Options>
1116 struct find_option< What, Opt, Options... > {
1117 typedef typename select_option<
1118 typename compare_option< What, Opt >::type
1120 ,typename find_option< What, Options... >::type
1123 } // namespace details
1126 /// Metafunction to find \p What option in \p Options list
1127 /** @headerfile cds/opt/options.h
1129 If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
1130 Otherwise the result is \p What.
1134 #include <cds/opt/options.h>
1135 namespace co = cds::opt;
1141 // Find option co::tag.
1143 // res1 is co::tag< tag_a >
1144 typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
1146 // res2 is default co::tag< default_tag >
1147 typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
1149 // Multiple option co::tag. The first option is selected
1150 // res3 is default co::tag< tag_a >
1151 typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
1155 template <typename What, typename... Options>
1156 struct find_option {
1157 typedef typename details::find_option<What, Options...>::type type ; ///< Metafunction result
1161 // *****************************************************************
1162 // select metafunction
1163 // *****************************************************************
1168 template <typename What, typename... Pairs>
1171 template <typename What, typename Value>
1172 struct select< What, What, Value>
1177 template <typename What, typename Tag, typename Value>
1178 struct select<What, Tag, Value>
1183 template <typename What, typename Value, typename... Pairs>
1184 struct select< What, What, Value, Pairs...>
1189 template <typename What, typename Tag, typename Value, typename... Pairs>
1190 struct select< What, Tag, Value, Pairs...>
1192 typedef typename select<What, Pairs...>::type type;
1194 } // namespace details
1197 /// Select option metafunction
1198 /** @headerfile cds/opt/options.h
1202 select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
1203 if What == T1 then return R1
1204 if What == T2 then return R2
1206 if What == Tn then return Rn
1210 template <typename What, typename... Pairs>
1212 typedef typename details::select< What, Pairs...>::type type ; ///< Metafunction result
1215 }} // namespace cds::opt
1218 #endif // #ifndef CDSLIB_OPT_OPTIONS_H