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 atomic item counting
308 - \p atomicity::cache_friendly_item_counter - cache-friendly atomic item counter
309 - \p opt::v::sequential_item_counter - simple non-atomic item counter. This counter is not intended for
310 concurrent containers and may be used only if it is explicitly noted.
312 You may provide other implementation of \p atomicity::item_counter interface for your needs.
314 Note, the item counting in lock-free containers cannot be exact; for example, if
315 item counter for a container returns zero it is not mean that the container is empty.
316 So, the item counter may be used for statistical purposes only.
318 template <typename Type>
319 struct item_counter {
321 template <typename Base> struct pack: public Base
323 typedef Type item_counter;
328 /// Special alignment constants for \ref cds::opt::alignment option
329 enum special_alignment {
330 no_special_alignment = 0, ///< no special alignment
331 cache_line_alignment = 1 ///< use cache line size defined in cds/user_setup/cache_line.h
334 /// [value-option] Alignment option setter
336 Alignment for some internal data of containers. May be useful to solve false sharing problem.
337 \p Value defines desired alignment and it may be power of two integer or predefined values from
338 \ref special_alignment enum.
340 template <unsigned int Value>
343 template <typename Base> struct pack: public Base
345 enum { alignment = Value };
352 template <typename Type, unsigned int Alignment>
353 struct alignment_setter {
354 typedef typename cds::details::aligned_type< Type, Alignment >::type type;
357 template <typename Type>
358 struct alignment_setter<Type, no_special_alignment> {
362 template <typename Type>
363 struct alignment_setter<Type, cache_line_alignment> {
364 typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type type;
366 } // namespace details
369 /// Special padding constants for \p cds::opt::padding option
370 enum special_padding {
371 no_special_padding = 0, ///< no special padding
372 cache_line_padding = 1, ///< use cache line size defined in cds/user_setup/cache_line.h
374 /// Apply padding only for tiny data when data size is less than required padding
376 The flag means that if your data size is less than the cacheline size, the padding is applyed.
377 Otherwise no padding will be applyed.
379 This flag is applyed for padding value:
381 cds::opt::padding< cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only >;
382 cds::opt::padding< 256 | cds::opt::padding_tiny_data_only >;
385 padding_tiny_data_only = 0x80000000,
388 padding_flags = padding_tiny_data_only
392 /// [value-option] Padding option setter
394 The padding for the internal data of some containers. May be useful to solve false sharing problem.
395 \p Value defines desired padding and it may be power of two integer or predefined values from
396 \p special_padding enum.
398 template <unsigned int Value>
401 template <typename Base> struct pack: public Base
403 enum { padding = Value };
409 template <unsigned Padding>
410 struct actual_padding
412 enum { value = Padding & ~padding_flags };
416 struct actual_padding<cache_line_padding>
418 enum { value = cds::c_nCacheLineSize };
422 struct actual_padding<cache_line_padding| padding_tiny_data_only>
424 enum { value = cds::c_nCacheLineSize };
430 enum padding_vs_datasize {
431 padding_datasize_less,
432 padding_datasize_equal,
433 padding_datasize_greater
436 template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
437 struct apply_padding_helper;
439 template <typename T, padding_vs_datasize Relation, bool TinyOnly >
440 struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
445 typedef void padding_type;
448 template <typename T, unsigned int Padding, bool TinyOnly >
449 struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
454 typedef void padding_type;
457 template <typename T, unsigned int Padding, bool TinyOnly >
458 struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
460 typedef uint8_t padding_type[Padding - sizeof( T )];
468 template <typename T, unsigned int Padding >
469 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
471 typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
478 template <typename T, unsigned int Padding >
479 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
484 typedef void padding_type;
487 template <typename T, unsigned int Padding >
491 enum { padding = Padding & ~padding_flags };
494 static CDS_CONSTEXPR const size_t c_nPadding =
495 static_cast<unsigned int>(padding) == static_cast<unsigned int>(cache_line_padding) ? cds::c_nCacheLineSize :
496 static_cast<unsigned int>(padding) == static_cast<unsigned int>(no_special_padding) ? 0 : padding;
498 static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
500 typedef apply_padding_helper< T,
503 sizeof( T ) < c_nPadding ? padding_datasize_less : sizeof( T ) == c_nPadding ? padding_datasize_equal : padding_datasize_greater,
504 (Padding & padding_tiny_data_only) != 0
507 typedef typename result::type type;
509 typedef typename std::conditional<
510 std::is_same< typename result::padding_type, void >::value,
512 typename result::padding_type
513 >::type padding_type;
516 } // namespace details
520 /// [type-option] Generic option setter for statisitcs
522 This option sets a type to gather statistics.
523 The option is generic - no predefined type(s) is provided.
524 The particular \p Type of statistics depends on internal structure of the object.
526 template <typename Type>
529 template <typename Base> struct pack: public Base
536 /// [type-option] Option setter for C++ memory model
538 The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
539 - \p v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
540 \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
541 - \p v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
542 this mode any memory ordering constraint maps to \p memory_order_seq_cst.
544 The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
546 You may mix different memory ordering options for different containers: one declare as sequentially consistent,
547 another declare as relaxed.
548 Usually, \p v::relaxed_ordering is the default memory ordering for <b>libcds</b> containers.
550 template <typename Type>
551 struct memory_model {
553 template <typename Base> struct pack: public Base
555 typedef Type memory_model;
560 /// [type-option] Base type traits option setter
562 This option setter is intended generally for internal use for type rebinding.
564 template <typename Type>
567 template <typename Base> struct pack: public Base
569 typedef Type type_traits;
574 /// Resizing policy option
576 This option specifies the resizing policy that decides when to resize a container.
577 Used in some containers, for example, in container::StripedHashSet, intrusive::StripedHashSet.
579 The real resizing policy specified by \p Type does strongly depend on a container
580 that supports this option, see container documentation about possibly \p Type values.
582 template <typename Type>
583 struct resizing_policy {
585 template <typename Base> struct pack: public Base
587 typedef Type resizing_policy;
592 /// Copy policy option
594 The copy policy defines an item copying algorithm which is used, for example, when a container is resized.
595 It is very specific algorithm depending on type of the container.
597 template <typename Type>
600 template <typename Base> struct pack: public Base
602 typedef Type copy_policy;
607 /// Swap policy option
609 The swap policy specifies an algorithm for swapping two objects.
610 Usually, the default policy is \p std::swap (see opt::v::default_swap_policy):
614 template <typename T>
615 void operator ()( T& v1, T& v2 )
622 template <typename Type>
625 template <typename Base> struct pack: public Base
627 typedef Type swap_policy;
632 /// Move policy option
634 The move policy specifies an algorithm for moving object content.
635 In trivial case, it can be simple assignment.
637 The move interface is:
639 template <typename T>
641 void operator()( T& dest, T& src );
645 Note that in move algorithm the \p src source argument can be changed too.
646 So you can use move semantics.
648 Usually, the default move policy is opt::v::assignment_move_policy
650 template <typename Type>
653 template <typename Base> struct pack: public Base
655 typedef Type move_policy;
660 /// [value-option] Enable sorting
662 This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
663 sorting of a container.
665 template <bool Enable>
668 template <typename Base> struct pack: public Base
670 static bool const sort = Enable;
675 /// [type-option] Concurrent access policy
677 This option specifies synchronization strategy for fine-grained lock-based containers.
678 The option has no predefined \p Policy type.
679 For each container that accepts this option the range of available \p Policy types
682 template <typename Policy>
683 struct mutex_policy {
685 template <typename Base> struct pack: public Base
687 typedef Policy mutex_policy;
693 /// [type-option] Random number generator
695 The option specifies a random number generator.
696 \p Random can be any STL random number generator producing
697 unsigned integer: \p std::linear_congruential_engine,
698 \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
699 and so on, or \p opt::v::c_rand.
702 template <typename Random>
703 struct random_engine {
705 template <typename Base> struct pack: public Base
707 typedef Random random_engine;
712 /// [type-option] Free-list implementation
714 See \p cds::intrusive::FreeList for free-list interface
716 template <typename FreeList>
719 template <typename Base> struct pack: public Base
721 typedef FreeList free_list;
728 template <typename Accessor>
729 struct key_accessor {
730 template <typename Base> struct pack: public Base
732 typedef Accessor key_accessor;
736 template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
737 struct replace_key_accessor {
738 typedef typename std::conditional<
739 std::is_same< typename Traits::key_accessor, WhatReplace >::value,
740 typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
746 }} // namespace cds::opt
749 // ****************************************************
750 // Options predefined types and values
752 namespace cds { namespace opt {
754 /// Predefined options value
757 /// Sequential non-atomic item counter
759 This type of \p opt::item_counter option is not intended for concurrent containers
760 and may be used only if it is explicitly noted.
762 class sequential_item_counter
765 typedef size_t counter_type ; ///< Counter type
767 counter_type m_nCounter ; ///< Counter
770 sequential_item_counter()
774 /// Returns current value of the counter
775 counter_type value() const
780 /// Same as \ref value() with relaxed memory ordering
781 operator counter_type() const
786 /// Increments the counter. Semantics: postincrement
792 /// Decrements the counter. Semantics: postdecrement
799 counter_type operator ++()
804 counter_type operator ++(int)
810 counter_type operator --()
815 counter_type operator --(int)
820 /// Resets count to 0
827 /// Relaxed memory ordering \p opt::memory_model
829 In this ordering the memory constraints are defined according to C++ Memory Model specification:
830 each constraint is mapped to \p std::memory_order constraints one-to-one
832 struct relaxed_ordering {
834 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
835 static const atomics::memory_order memory_order_consume = atomics::memory_order_consume;
836 static const atomics::memory_order memory_order_acquire = atomics::memory_order_acquire;
837 static const atomics::memory_order memory_order_release = atomics::memory_order_release;
838 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_acq_rel;
839 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
843 /// Sequential consistent \p opt::memory_memory ordering
845 In this memory model any memory constraint is equivalent to \p std::memory_order_seq_cst.
847 struct sequential_consistent {
849 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_seq_cst;
850 static const atomics::memory_order memory_order_consume = atomics::memory_order_seq_cst;
851 static const atomics::memory_order memory_order_acquire = atomics::memory_order_seq_cst;
852 static const atomics::memory_order memory_order_release = atomics::memory_order_seq_cst;
853 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_seq_cst;
854 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
859 /// Totally relaxed \p opt::memory_model ordering (do not use!)
861 In this memory model any memory constraint is equivalent to \p std::memory_order_relaxed.
862 @warning Do not use this model! It intended for testing purposes only
863 to verify debugging instruments like Thread Sanitizer.
865 struct total_relaxed_ordering {
866 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
867 static const atomics::memory_order memory_order_consume = atomics::memory_order_relaxed;
868 static const atomics::memory_order memory_order_acquire = atomics::memory_order_relaxed;
869 static const atomics::memory_order memory_order_release = atomics::memory_order_relaxed;
870 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_relaxed;
871 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_relaxed;
876 /// Default swap policy for \p opt::swap_policy option
878 The default swap policy is wrappr around \p std::swap algorithm.
880 struct default_swap_policy {
881 /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
882 template <typename T>
883 void operator()( T& v1, T& v2 ) const
889 /// \p opt::move_policy based on move-assignment operator
890 struct assignment_move_policy
892 /// <tt> dest = std::move( src ) </tt>
893 template <typename T>
894 void operator()( T& dest, T&& src ) const
896 dest = std::move( src );
900 /// \p rand() -base random number generator for \p opt::random_engine
902 This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
905 typedef unsigned int result_type; ///< Result type
907 /// Constructor initializes object calling \p std::srand()
913 /// Returns next random number calling \p std::rand()
914 result_type operator()()
916 return (result_type) std::rand();
921 }} // namespace cds::opt
924 // ****************************************************
925 // Options metafunctions
927 namespace cds { namespace opt {
931 template <typename OptionList, typename Option>
934 // Use "pack" member template to pack options
935 typedef typename Option::template pack<OptionList> type;
938 template <typename ...T> class typelist;
940 template <typename Typelist> struct typelist_head;
941 template <typename Head, typename ...Tail>
942 struct typelist_head< typelist<Head, Tail...> > {
945 template <typename Head>
946 struct typelist_head< typelist<Head> > {
950 template <typename Typelist> struct typelist_tail;
951 template <typename Head, typename ...Tail>
952 struct typelist_tail< typelist<Head, Tail...> > {
953 typedef typelist<Tail...> type;
955 template <typename Head>
956 struct typelist_tail< typelist<Head> > {
957 typedef typelist<> type;
960 template <typename OptionList, typename Typelist>
961 struct make_options_impl {
962 typedef typename make_options_impl<
965 typename typelist_head< Typelist >::type
967 typename typelist_tail<Typelist>::type
971 template <typename OptionList>
972 struct make_options_impl<OptionList, typelist<> > {
973 typedef OptionList type;
975 } // namespace details
978 /// make_options metafunction
979 /** @headerfile cds/opt/options.h
981 The metafunction converts option list \p Options to traits structure.
982 The result of metafunction is \p type.
984 Template parameter \p OptionList is default option set (default traits).
985 \p Options is option list.
987 template <typename OptionList, typename... Options>
988 struct make_options {
989 #ifdef CDS_DOXYGEN_INVOKED
990 typedef implementation_defined type ; ///< Result of the metafunction
992 typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
997 // *****************************************************************
998 // find_type_traits metafunction
999 // *****************************************************************
1003 template <typename... Options>
1004 struct find_type_traits_option;
1007 struct find_type_traits_option<> {
1008 typedef cds::opt::none type;
1011 template <typename Any>
1012 struct find_type_traits_option< Any > {
1013 typedef cds::opt::none type;
1016 template <typename Any>
1017 struct find_type_traits_option< cds::opt::type_traits< Any > > {
1021 template <typename Any, typename... Options>
1022 struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
1026 template <typename Any, typename... Options>
1027 struct find_type_traits_option< Any, Options... > {
1028 typedef typename find_type_traits_option< Options... >::type type;
1030 } // namespace details
1033 /// Metafunction to find opt::type_traits option in \p Options list
1034 /** @headerfile cds/opt/options.h
1036 If \p Options contains \p opt::type_traits option then it is the metafunction result.
1037 Otherwise the result is \p DefaultOptons.
1039 template <typename DefaultOptions, typename... Options>
1040 struct find_type_traits {
1041 typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ; ///< Metafunction result
1045 // *****************************************************************
1046 // find_option metafunction
1047 // *****************************************************************
1051 template <typename What, typename... Options>
1055 struct compare_fail;
1057 template <typename A, typename B>
1058 struct compare_option
1060 typedef compare_fail type;
1063 template <template <typename> class Opt, typename A, typename B>
1064 struct compare_option< Opt<A>, Opt<B> >
1066 typedef compare_ok type;
1069 // Specializations for integral type of option
1070 #define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
1071 struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
1073 // For user-defined enum types
1074 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
1076 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
1077 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
1078 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
1079 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
1080 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
1081 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
1082 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
1083 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
1084 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
1085 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
1086 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
1087 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
1090 template <typename CompResult, typename Ok, typename Fail>
1091 struct select_option
1096 template <typename Ok, typename Fail>
1097 struct select_option< compare_ok, Ok, Fail >
1102 template <typename What>
1103 struct find_option< What > {
1107 template <typename What, typename Opt>
1108 struct find_option< What, Opt > {
1109 typedef typename select_option<
1110 typename compare_option< What, Opt >::type
1116 template <typename What, typename Opt, typename... Options>
1117 struct find_option< What, Opt, Options... > {
1118 typedef typename select_option<
1119 typename compare_option< What, Opt >::type
1121 ,typename find_option< What, Options... >::type
1124 } // namespace details
1127 /// Metafunction to find \p What option in \p Options list
1128 /** @headerfile cds/opt/options.h
1130 If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
1131 Otherwise the result is \p What.
1135 #include <cds/opt/options.h>
1136 namespace co = cds::opt;
1142 // Find option co::tag.
1144 // res1 is co::tag< tag_a >
1145 typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
1147 // res2 is default co::tag< default_tag >
1148 typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
1150 // Multiple option co::tag. The first option is selected
1151 // res3 is default co::tag< tag_a >
1152 typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
1156 template <typename What, typename... Options>
1157 struct find_option {
1158 typedef typename details::find_option<What, Options...>::type type ; ///< Metafunction result
1162 // *****************************************************************
1163 // select metafunction
1164 // *****************************************************************
1169 template <typename What, typename... Pairs>
1172 template <typename What, typename Value>
1173 struct select< What, What, Value>
1178 template <typename What, typename Tag, typename Value>
1179 struct select<What, Tag, Value>
1184 template <typename What, typename Value, typename... Pairs>
1185 struct select< What, What, Value, Pairs...>
1190 template <typename What, typename Tag, typename Value, typename... Pairs>
1191 struct select< What, Tag, Value, Pairs...>
1193 typedef typename select<What, Pairs...>::type type;
1195 } // namespace details
1198 /// Select option metafunction
1199 /** @headerfile cds/opt/options.h
1203 select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
1204 if What == T1 then return R1
1205 if What == T2 then return R2
1207 if What == Tn then return Rn
1211 template <typename What, typename... Pairs>
1213 typedef typename details::select< What, Pairs...>::type type ; ///< Metafunction result
1216 }} // namespace cds::opt
1219 #endif // #ifndef CDSLIB_OPT_OPTIONS_H