2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
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 <stdlib.h> // 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 casheline 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 };
409 enum padding_vs_datasize {
410 padding_datasize_less,
411 padding_datasize_equal,
412 padding_datasize_greater
415 template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
416 struct apply_padding_helper;
418 template <typename T, padding_vs_datasize Relation, bool TinyOnly >
419 struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
424 typedef void padding_type;
427 template <typename T, unsigned int Padding, bool TinyOnly >
428 struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
433 typedef void padding_type;
436 template <typename T, unsigned int Padding, bool TinyOnly >
437 struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
439 typedef uint8_t padding_type[Padding - sizeof( T )];
447 template <typename T, unsigned int Padding >
448 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
450 typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
457 template <typename T, unsigned int Padding >
458 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
463 typedef void padding_type;
466 template <typename T, unsigned int Padding >
470 enum { padding = Padding & ~padding_flags };
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;
477 static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
479 typedef apply_padding_helper< T,
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
486 typedef typename result::type type;
488 typedef typename std::conditional<
489 std::is_same< typename result::padding_type, void >::value,
491 typename result::padding_type
492 >::type padding_type;
495 } // namespace details
499 /// [type-option] Generic option setter for statisitcs
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.
505 template <typename Type>
508 template <typename Base> struct pack: public Base
515 /// [type-option] Option setter for C++ memory model
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.
523 The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
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.
529 template <typename Type>
530 struct memory_model {
532 template <typename Base> struct pack: public Base
534 typedef Type memory_model;
539 /// [type-option] Base type traits option setter
541 This option setter is intended generally for internal use for type rebinding.
543 template <typename Type>
546 template <typename Base> struct pack: public Base
548 typedef Type type_traits;
553 /// Resizing policy option
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.
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.
561 template <typename Type>
562 struct resizing_policy {
564 template <typename Base> struct pack: public Base
566 typedef Type resizing_policy;
571 /// Copy policy option
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.
576 template <typename Type>
579 template <typename Base> struct pack: public Base
581 typedef Type copy_policy;
586 /// Swap policy option
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):
593 template <typename T>
594 void operator ()( T& v1, T& v2 )
601 template <typename Type>
604 template <typename Base> struct pack: public Base
606 typedef Type swap_policy;
611 /// Move policy option
613 The move policy specifies an algorithm for moving object content.
614 In trivial case, it can be simple assignment.
616 The move interface is:
618 template <typename T>
620 void operator()( T& dest, T& src );
624 Note that in move algorithm the \p src source argument can be changed too.
625 So you can use move semantics.
627 Usually, the default move policy is opt::v::assignment_move_policy
629 template <typename Type>
632 template <typename Base> struct pack: public Base
634 typedef Type move_policy;
639 /// [value-option] Enable sorting
641 This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
642 sorting of a container.
644 template <bool Enable>
647 template <typename Base> struct pack: public Base
649 static bool const sort = Enable;
654 /// [type-option] Concurrent access policy
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
661 template <typename Policy>
662 struct mutex_policy {
664 template <typename Base> struct pack: public Base
666 typedef Policy mutex_policy;
672 /// [type-option] Random number generator
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.
681 template <typename Random>
682 struct random_engine {
684 template <typename Base> struct pack: public Base
686 typedef Random random_engine;
693 template <typename Accessor>
694 struct key_accessor {
695 template <typename Base> struct pack: public Base
697 typedef Accessor key_accessor;
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 >,
711 }} // namespace cds::opt
714 // ****************************************************
715 // Options predefined types and values
717 namespace cds { namespace opt {
719 /// Predefined options value
722 /// Sequential non-atomic item counter
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.
727 class sequential_item_counter
730 typedef size_t counter_type ; ///< Counter type
732 counter_type m_nCounter ; ///< Counter
735 sequential_item_counter()
739 /// Returns current value of the counter
740 counter_type value() const
745 /// Same as \ref value() with relaxed memory ordering
746 operator counter_type() const
751 /// Increments the counter. Semantics: postincrement
757 /// Decrements the counter. Semantics: postdecrement
764 counter_type operator ++()
769 counter_type operator ++(int)
775 counter_type operator --()
780 counter_type operator --(int)
785 /// Resets count to 0
792 /// Relaxed memory ordering \p opt::memory_model
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
797 struct relaxed_ordering {
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;
808 /// Sequential consistent \p opt::memory_memory ordering
810 In this memory model any memory constraint is equivalent to \p std::memory_order_seq_cst.
812 struct sequential_consistent {
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;
824 /// Totally relaxed \p opt::memory_model ordering (do not use!)
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.
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;
841 /// Default swap policy for \p opt::swap_policy option
843 The default swap policy is wrappr around \p std::swap algorithm.
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
854 /// \p opt::move_policy based on move-assignment operator
855 struct assignment_move_policy
857 /// <tt> dest = std::move( src ) </tt>
858 template <typename T>
859 void operator()( T& dest, T&& src ) const
861 dest = std::move( src );
865 /// \p rand() -base random number generator for \p opt::random_engine
867 This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
870 typedef unsigned int result_type; ///< Result type
872 /// Constructor initializes object calling \p srand()
878 /// Returns next random number calling \p rand()
879 result_type operator()()
881 return (result_type) rand();
887 }} // namespace cds::opt
890 // ****************************************************
891 // Options metafunctions
893 namespace cds { namespace opt {
897 template <typename OptionList, typename Option>
900 // Use "pack" member template to pack options
901 typedef typename Option::template pack<OptionList> type;
904 template <typename ...T> class typelist;
906 template <typename Typelist> struct typelist_head;
907 template <typename Head, typename ...Tail>
908 struct typelist_head< typelist<Head, Tail...> > {
911 template <typename Head>
912 struct typelist_head< typelist<Head> > {
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;
921 template <typename Head>
922 struct typelist_tail< typelist<Head> > {
923 typedef typelist<> type;
926 template <typename OptionList, typename Typelist>
927 struct make_options_impl {
928 typedef typename make_options_impl<
931 typename typelist_head< Typelist >::type
933 typename typelist_tail<Typelist>::type
937 template <typename OptionList>
938 struct make_options_impl<OptionList, typelist<> > {
939 typedef OptionList type;
941 } // namespace details
944 /// make_options metafunction
945 /** @headerfile cds/opt/options.h
947 The metafunction converts option list \p Options to traits structure.
948 The result of metafunction is \p type.
950 Template parameter \p OptionList is default option set (default traits).
951 \p Options is option list.
953 template <typename OptionList, typename... Options>
954 struct make_options {
955 #ifdef CDS_DOXYGEN_INVOKED
956 typedef implementation_defined type ; ///< Result of the metafunction
958 typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
963 // *****************************************************************
964 // find_type_traits metafunction
965 // *****************************************************************
969 template <typename... Options>
970 struct find_type_traits_option;
973 struct find_type_traits_option<> {
974 typedef cds::opt::none type;
977 template <typename Any>
978 struct find_type_traits_option< Any > {
979 typedef cds::opt::none type;
982 template <typename Any>
983 struct find_type_traits_option< cds::opt::type_traits< Any > > {
987 template <typename Any, typename... Options>
988 struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
992 template <typename Any, typename... Options>
993 struct find_type_traits_option< Any, Options... > {
994 typedef typename find_type_traits_option< Options... >::type type;
996 } // namespace details
999 /// Metafunction to find opt::type_traits option in \p Options list
1000 /** @headerfile cds/opt/options.h
1002 If \p Options contains \p opt::type_traits option then it is the metafunction result.
1003 Otherwise the result is \p DefaultOptons.
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
1011 // *****************************************************************
1012 // find_option metafunction
1013 // *****************************************************************
1017 template <typename What, typename... Options>
1021 struct compare_fail;
1023 template <typename A, typename B>
1024 struct compare_option
1026 typedef compare_fail type;
1029 template <template <typename> class Opt, typename A, typename B>
1030 struct compare_option< Opt<A>, Opt<B> >
1032 typedef compare_ok type;
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 ; };
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 ) }}}
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)
1056 template <typename CompResult, typename Ok, typename Fail>
1057 struct select_option
1062 template <typename Ok, typename Fail>
1063 struct select_option< compare_ok, Ok, Fail >
1068 template <typename What>
1069 struct find_option< What > {
1073 template <typename What, typename Opt>
1074 struct find_option< What, Opt > {
1075 typedef typename select_option<
1076 typename compare_option< What, Opt >::type
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
1087 ,typename find_option< What, Options... >::type
1090 } // namespace details
1093 /// Metafunction to find \p What option in \p Options list
1094 /** @headerfile cds/opt/options.h
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.
1101 #include <cds/opt/options.h>
1102 namespace co = cds::opt;
1108 // Find option co::tag.
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;
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;
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;
1122 template <typename What, typename... Options>
1123 struct find_option {
1124 typedef typename details::find_option<What, Options...>::type type ; ///< Metafunction result
1128 // *****************************************************************
1129 // select metafunction
1130 // *****************************************************************
1135 template <typename What, typename... Pairs>
1138 template <typename What, typename Value>
1139 struct select< What, What, Value>
1144 template <typename What, typename Tag, typename Value>
1145 struct select<What, Tag, Value>
1150 template <typename What, typename Value, typename... Pairs>
1151 struct select< What, What, Value, Pairs...>
1156 template <typename What, typename Tag, typename Value, typename... Pairs>
1157 struct select< What, Tag, Value, Pairs...>
1159 typedef typename select<What, Pairs...>::type type;
1161 } // namespace details
1164 /// Select option metafunction
1165 /** @headerfile cds/opt/options.h
1169 select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
1170 if What == T1 then return R1
1171 if What == T2 then return R2
1173 if What == Tn then return Rn
1177 template <typename What, typename... Pairs>
1179 typedef typename details::select< What, Pairs...>::type type ; ///< Metafunction result
1182 }} // namespace cds::opt
1185 #endif // #ifndef CDSLIB_OPT_OPTIONS_H