3 #ifndef __CDS_OPT_OPTIONS_H
4 #define __CDS_OPT_OPTIONS_H
7 Framework to define template options
10 2011.01.23 khizmax Created
13 #include <cds/details/aligned_type.h>
14 #include <cds/user_setup/allocator.h>
15 #include <cds/user_setup/cache_line.h>
16 #include <cds/cxx11_atomic.h>
17 #include <stdlib.h> // rand, srand
21 /// Framework to define template options
23 There are two kind of options:
24 - \p type-option - option that determines a data type. The template argument \p Type of the option is a type.
25 - \p value-option - option that determines a value. The template argument \p Value of the option is a value.
29 /// Predefined options value (generally, for the options that determine the data types)
32 /// Type indicates that an option is not specified and the default one should be used
36 template <class Base> struct pack: public Base
41 /// Metafunction for selecting default option value
44 - \p Option - option value
45 - \p Default - default option value
46 - \p Value - option value if \p Option is not opt::none
48 If \p Option is opt::none, the metafunction result is \p Default, otherwise
49 the result is \p Value.
53 // default_spin is cds::lock::Spin
54 typedef typename cds::opt::select_default< cds::opt::none, cds::lock::Spin >::type default_spin;
56 // spin_32bit is cds::lock::Spin32
57 typedef typename cds::opt::select_default< cds::lock::Spin32, cds::lock::Spin >::type spin_32bit;
60 template <typename Option, typename Default, typename Value = Option>
63 typedef Value type ; ///< metafunction result
66 template <typename Default>
67 struct select_default< none, Default >
73 /// Metafunction to select option value
75 This metafunction is intended for extracting the value of the \p Option option.
78 #include <cds/opt/options.h>
79 #include <type_traits> // only for testing purpose (static_assert)
84 typedef cds::opt::tag< tag_a > tag_option;
86 // What is the value of the tag_option?
87 // How we can extract tag_a from tag_option?
88 // Here is a solution:
89 typedef cds::opt::value< tag_option >::tag tag_option_value;
91 // tag_option_value is the same as tag_a
92 static_assert( std::is_same< tag_option_value, tag_a >::value, "Error: tag_option_value != tag_a" );
96 template <typename Option>
97 struct value: public Option::template pack<none>
101 /// [type-option] Option setter specifies a tag
103 Suppose, you have a struct
108 and you want that your class \p X would be derived from several \p Feature:
110 class X: public Feature, public Feature
114 How can you distinguish one \p Feature from another?
115 You may use a tag option:
117 template <typename Tag>
123 class X: public Feature< tag_a >, public Feature< tag_b >
126 Now you can distinguish one \p Feature from another:
129 Feature<tag_a>& fa = static_cast< Feature<tag_a> >( x );
130 Feature<tag_b>& fb = static_cast< Feature<tag_b> >( x );
133 \p tag option setter allows you to do things like this for an option-centric approach:
135 template <typename ...Options>
141 class X: public Feature< tag<tag_a> >, public Feature< tag<tag_b> >
145 This option setter is widely used in cds::intrusive containers to distinguish
146 between different intrusive part of container's node.
148 An incomplete type can serve as a \p Tag.
150 template <typename Tag>
153 template<class Base> struct pack: public Base
160 /// [type-option] Option setter specifies lock class
162 Specification of the \p Type class is:
170 template <typename Type>
173 template<class Base> struct pack: public Base
175 typedef Type lock_type;
180 /// [type-option] Back-off strategy option setter
182 Back-off strategy used in some algorithm.
183 See cds::backoff namespace for back-off explanation and supported interface.
185 template <typename Type>
188 template <class Base> struct pack: public Base
190 typedef Type back_off;
195 /// [type-option] Option setter for garbage collecting schema used
197 Possible values of \p GC template parameter are:
198 - cds::gc::HP - Hazard Pointer garbage collector
199 - cds::gc::HRC - Gidenstam's garbage collector
200 - cds::gc::PTB - Pass-the-Buck garbage collector
201 - cds::gc::none::GC - No garbage collector (not supported for some containers)
203 template <typename GC>
206 template <class Base> struct pack: public Base
213 /// [type-option] Option setter for an allocator
215 \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
216 that, in turn, is \p std::allocator.
218 The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
219 you may specify any valid type as std::allocator's template parameter.
221 See also opt::node_allocator
223 template <typename Type>
226 template <typename Base> struct pack: public Base
228 typedef Type allocator;
233 /// [type-option] Option setter for node allocator
235 \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
236 that, in turn, is \p std::allocator.
238 Many node-base containers require an allocator for maintaining data (container's node) and for internal use.
239 Sometimes, this types of allocator should be different for performance reason.
240 For example, we should like to allocate the node from a pool of preallocated nodes.
241 Such pool can be seen as the node allocator.
243 Usually, if a container supports \p opt::allocator and \p %opt::node_allocator options
244 and \p opt::node_allocator is not specified the \p %opt::allocator option is used for maintaining the nodes.
246 The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
247 you may specify any valid type as std::allocator's template parameter.
249 template <typename Type>
250 struct node_allocator {
252 template <typename Base> struct pack: public Base
254 typedef Type node_allocator;
259 /// [type-option] Option setter for item counting
261 Some data structure (for example, queues) has additional feature for item counting.
262 This option allows to set up appropriate item counting policy for that data structure.
264 Predefined option \p Type:
265 - atomicity::empty_item_counter - no item counting performed. It is default policy for many
267 - atomicity::item_counter - the class that provides atomically item counting
268 - opt::v::sequential_item_counter - simple non-atomic item counter. This item counter is not intended for
269 concurrent containers and may be used only if it is explicitly noted.
271 You may provide other implementation of atomicity::item_counter interface for your needs.
273 Note, the item counting in lock-free containers cannot be exact; for example, if
274 item counter for a container returns zero it is not mean that the container is empty.
275 Thus, item counter may be used for statistical purposes only.
277 template <typename Type>
278 struct item_counter {
280 template <typename Base> struct pack: public Base
282 typedef Type item_counter;
288 /// Sequential non-atomic item counter
290 This type of item counter is not intended for concurrent containers
291 and may be used only if it is explicitly noted.
293 class sequential_item_counter
296 typedef size_t counter_type ; ///< Counter type
298 counter_type m_nCounter ; ///< Counter
301 sequential_item_counter()
305 /// Returns current value of the counter
306 counter_type value() const
311 /// Same as \ref value() with relaxed memory ordering
312 operator counter_type() const
317 /// Increments the counter. Semantics: postincrement
323 /// Decrements the counter. Semantics: postdecrement
330 counter_type operator ++()
335 counter_type operator ++(int)
341 counter_type operator --()
346 counter_type operator --(int)
351 /// Resets count to 0
359 /// Special alignment constants for \ref cds::opt::alignment option
360 enum special_alignment {
361 no_special_alignment = 0, ///< no special alignment
362 cache_line_alignment = 1 ///< use cache line size defined in cds/user_setup/cache_line.h
365 /// [value-option] Alignment option setter
367 Alignment for some internal data of containers. May be useful to solve false sharing problem.
368 \p Value defines desired alignment and it may be power of two integer or predefined values from
369 \ref special_alignment enum.
371 template <unsigned int Value>
374 template <typename Base> struct pack: public Base
376 enum { alignment = Value };
383 template <typename Type, unsigned int Alignment>
384 struct alignment_setter {
385 typedef typename cds::details::aligned_type< Type, Alignment >::type type;
388 template <typename Type>
389 struct alignment_setter<Type, no_special_alignment> {
393 template <typename Type>
394 struct alignment_setter<Type, cache_line_alignment> {
395 typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type type;
398 } // namespace details
401 /// [type-option] Generic option setter for statisitcs
403 This option sets a type to gather statistics.
404 The option is generic - no predefined type(s) is provided.
405 The particular \p Type of statistics depends on internal structure of the object.
407 template <typename Type>
410 template <typename Base> struct pack: public Base
417 /// [type-option] Option setter for C++ memory model
419 The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
420 - v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
421 \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
422 - v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
423 this mode any memory ordering constraint maps to \p memory_order_seq_cst.
425 The \p Type template parameter can be v::relaxed_ordering or v::sequential_consistent.
427 You may mix different memory ordering options for different containers: one declare as sequentially consistent,
428 another declare as relaxed.
429 Usually, v::relaxed_ordering is the default memory ordering for <b>cds</b> containers.
431 template <typename Type>
432 struct memory_model {
434 template <typename Base> struct pack: public Base
436 typedef Type memory_model;
442 /// Relaxed memory ordering model
444 In this memory model the memory constraints are defined according to C++ Memory Model specification.
446 See opt::memory_model for explanations
448 struct relaxed_ordering {
451 // For new C++11 (cds-1.1.0)
452 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
453 static const atomics::memory_order memory_order_consume = atomics::memory_order_consume;
454 static const atomics::memory_order memory_order_acquire = atomics::memory_order_acquire;
455 static const atomics::memory_order memory_order_release = atomics::memory_order_release;
456 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_acq_rel;
457 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
461 /// Sequential consistent memory ordering model
463 In this memory model any memory constraint is equivalent to \p memory_order_seq_cst.
465 See opt::memory_model for explanations
467 struct sequential_consistent {
470 // For new C++11 (cds-1.1.0)
471 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_seq_cst;
472 static const atomics::memory_order memory_order_consume = atomics::memory_order_seq_cst;
473 static const atomics::memory_order memory_order_acquire = atomics::memory_order_seq_cst;
474 static const atomics::memory_order memory_order_release = atomics::memory_order_seq_cst;
475 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_seq_cst;
476 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
481 /// [type-option] Base type traits option setter
483 This option setter is intended generally for internal use for type rebinding.
485 template <typename Type>
488 template <typename Base> struct pack: public Base
490 typedef Type type_traits;
495 /// Resizing policy option
497 This option specifies the resizing policy that decides when to resize a container.
498 Used in some containers, for example, in container::StripedHashSet, intrusive::StripedHashSet.
500 The real resizing policy specified by \p Type does strongly depend on a container
501 that supports this option, see container documentation about possibly \p Type values.
503 template <typename Type>
504 struct resizing_policy {
506 template <typename Base> struct pack: public Base
508 typedef Type resizing_policy;
513 /// Copy policy option
515 The copy policy defines an item copying algorithm which is used, for example, when a container is resized.
516 It is very specific algorithm depending on type of the container.
518 template <typename Type>
521 template <typename Base> struct pack: public Base
523 typedef Type copy_policy;
528 /// Swap policy option
530 The swap policy specifies an algorithm for swapping two objects.
531 Usually, the default policy is \p std::swap (see opt::v::default_swap_policy):
535 template <typename T>
536 void operator ()( T& v1, T& v2 )
543 template <typename Type>
546 template <typename Base> struct pack: public Base
548 typedef Type swap_policy;
555 /// Default swap policy (see opt::swap_policy option)
557 The default swap policy is wrappr around \p std::swap algorithm.
559 struct default_swap_policy {
560 /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
561 template <typename T>
562 void operator()( T& v1, T& v2 ) const
569 /// Move policy option
571 The move policy specifies an algorithm for moving object content.
572 In trivial case, it can be simple assignment.
574 The move interface is:
576 template <typename T>
578 void operator()( T& dest, T& src );
582 Note that in move algorithm the \p src source argument can be changed too.
583 So you can use move semantics.
585 Usually, the default move policy is opt::v::assignment_move_policy
587 template <typename Type>
590 template <typename Base> struct pack: public Base
592 typedef Type move_policy;
598 /// \ref opt::move_policy "Move policy" based on assignment operator
599 struct assignment_move_policy
601 /// <tt> dest = src </tt>
602 template <typename T>
603 void operator()( T& dest, T const& src ) const
610 /// [value-option] Enable sorting
612 This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
613 sorting of a container.
615 template <bool Enable>
618 template <typename Base> struct pack: public Base
620 static bool const sort = Enable;
625 /// [type-option] Concurrent access policy
627 This option specifies synchronization strategy for fine-grained lock-based containers.
628 The option has no predefined \p Policy type.
629 For each container that accepts this option the range of available \p Policy types
632 template <typename Policy>
633 struct mutex_policy {
635 template <typename Base> struct pack: public Base
637 typedef Policy mutex_policy;
643 /// [type-option] Random number generator
645 The option specifies a random number generator.
646 \p Random can be any STL random number generator producing
647 unsigned integer: \p std::linear_congruential_engine,
648 \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
649 and so on, or opt::v::c_rand.
652 template <typename Random>
653 struct random_engine {
655 template <typename Base> struct pack: public Base
657 typedef Random random_engine;
663 /// \p rand() -base random number generator
665 This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
668 typedef unsigned int result_type; ///< Result type
670 /// Constructor initializes object calling \p srand()
676 /// Returns next random number calling \p rand()
677 result_type operator()()
679 return (result_type) rand();
686 template <typename Accessor>
687 struct key_accessor {
688 template <typename Base> struct pack: public Base
690 typedef Accessor key_accessor;
694 template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
695 struct replace_key_accessor {
696 typedef typename std::conditional<
697 std::is_same< typename Traits::key_accessor, WhatReplace >::value,
698 typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
704 }} // namespace cds::opt
706 #include <cds/opt/make_options_var.h>
708 #endif // #ifndef __CDS_OPT_OPTIONS_H