diff options
Diffstat (limited to '3rdParty/Boost/src/libs/atomic/doc/platform.qbk')
-rw-r--r-- | 3rdParty/Boost/src/libs/atomic/doc/platform.qbk | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/libs/atomic/doc/platform.qbk b/3rdParty/Boost/src/libs/atomic/doc/platform.qbk new file mode 100644 index 0000000..6b9a9ec --- /dev/null +++ b/3rdParty/Boost/src/libs/atomic/doc/platform.qbk @@ -0,0 +1,312 @@ +[/ + / Copyright (c) 2009 Helge Bahmann + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:template_organization Organization of class template layers] + +The implementation uses multiple layers of template classes that +inherit from the next lower level each and refine or adapt the respective +underlying class: + +* [^boost::atomic<T>] is the topmost-level, providing + the external interface. Implementation-wise, it does not add anything + (except for hiding copy constructor and assignment operator). + +* [^boost::detail::atomic::internal_atomic&<T,S=sizeof(T),I=is_integral_type<T> >]: + This layer is mainly responsible for providing the overloaded operators + mapping to API member functions (e.g. [^+=] to [^fetch_add]). + The defaulted template parameter [^I] allows + to expose the correct API functions (via partial template + specialization): For non-integral types, it only + publishes the various [^exchange] functions + as well as load and store, for integral types it + additionally exports arithmetic and logic operations. + [br] + Depending on whether the given type is integral, it + inherits from either [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] + or [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]. + There is however some special-casing: for non-integral types + of size 1, 2, 4 or 8, it will coerce the datatype into an integer representation + and delegate to [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>] + -- the rationale is that platform implementors only need to provide + integer-type operations. + +* [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>] + must provide the full set of operations for an integral type T + (i.e. [^load], [^store], [^exchange], + [^compare_exchange_weak], [^compare_exchange_strong], + [^fetch_add], [^fetch_sub], [^fetch_and], + [^fetch_or], [^fetch_xor], [^is_lock_free]). + The default implementation uses locking to emulate atomic operations, so + this is the level at which implementors should provide template specializations + to add support for platform-specific atomic operations. + [br] + The two separate template parameters allow separate specialization + on size and type (which, with fixed size, cannot + specify more than signedness/unsignedness). The rationale is that + most platform-specific atomic operations usually depend only on the + operand size, so that common implementations for signed/unsigned + types are possible. Signedness allows to properly to choose sign-extending + instructions for the [^load] operation, avoiding later + conversion. The expectation is that in most implementations this will + be a normal assignment in C, possibly accompanied by memory + fences, so that the compiler can automatically choose the correct + instruction. + +* At the lowest level, [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] + provides the most basic atomic operations ([^load], [^store], + [^exchange], [^compare_exchange_weak], + [^compare_exchange_strong]) for arbitrarily generic data types. + The default implementation uses locking as a fallback mechanism. + Implementors generally do not have to specialize at this level + (since these will not be used for the common integral type sizes + of 1, 2, 4 and 8 bytes), but if s/he can if s/he so wishes to + provide truly atomic operations for "odd" data type sizes. + Some amount of care must be taken as the "raw" data type + passed in from the user through [^boost::atomic<T>] + is visible here -- it thus needs to be type-punned or otherwise + manipulated byte-by-byte to avoid using overloaded assignment, + comparison operators and copy constructors. + +[endsect] + + +[section:platform_atomic_implementation Implementing platform-specific atomic operations] + +In principle implementors are responsible for providing the +full range of named member functions of an atomic object +(i.e. [^load], [^store], [^exchange], +[^compare_exchange_weak], [^compare_exchange_strong], +[^fetch_add], [^fetch_sub], [^fetch_and], +[^fetch_or], [^fetch_xor], [^is_lock_free]). +These must be implemented as partial template specializations for +[^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 4> + { + public: + explicit platform_atomic_integral(T v) : i(v) {} + platform_atomic_integral(void) {} + + T load(memory_order order=memory_order_seq_cst) const volatile + { + // platform-specific code + } + void store(T v, memory_order order=memory_order_seq_cst) volatile + { + // platform-specific code + } + + private: + volatile T i; + }; + +As noted above, it will usually suffice to specialize on the second +template argument, indicating the size of the data type in bytes. + +[section:automatic_buildup Templates for automatic build-up] + +Often only a portion of the required operations can be +usefully mapped to machine instructions. Several helper template +classes are provided that can automatically synthesize missing methods to +complete an implementation. + +At the minimum, an implementor must provide the +[^load], [^store], +[^compare_exchange_weak] and +[^is_lock_free] methods: + +[c++] + + template<typename T> + class my_atomic_32 { + public: + my_atomic_32() {} + my_atomic_32(T initial_value) : value(initial_value) {} + + T load(memory_order order=memory_order_seq_cst) volatile const + { + // platform-specific code + } + void store(T new_value, memory_order order=memory_order_seq_cst) volatile + { + // platform-specific code + } + bool compare_exchange_weak(T &expected, T desired, + memory_order success_order, + memory_order_failure_order) volatile + { + // platform-specific code + } + bool is_lock_free() const volatile {return true;} + protected: + // typedef is required for classes inheriting from this + typedef T integral_type; + private: + T value; + }; + +The template [^boost::detail::atomic::build_atomic_from_minimal] +can then take care of the rest: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 4> + : public boost::detail::atomic::build_atomic_from_minimal<my_atomic_32<T> > + { + public: + typedef build_atomic_from_minimal<my_atomic_32<T> > super; + + explicit platform_atomic_integral(T v) : super(v) {} + platform_atomic_integral(void) {} + }; + +There are several helper classes to assist in building "complete" +atomic implementations from different starting points: + +* [^build_atomic_from_minimal] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + +* [^build_atomic_from_exchange] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + +* [^build_atomic_from_add] requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + * [^fetch_add] + +* [^build_atomic_from_typical] (<I>supported on gcc only</I>) requires + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + * [^fetch_add_var] (protected method) + * [^fetch_inc] (protected method) + * [^fetch_dec] (protected method) + + This will generate a [^fetch_add] method + that calls [^fetch_inc]/[^fetch_dec] + when the given parameter is a compile-time constant + equal to +1 or -1 respectively, and [^fetch_add_var] + in all other cases. This provides a mechanism for + optimizing the extremely common case of an atomic + variable being used as a counter. + + The prototypes for these methods to be implemented is: + [c++] + + template<typename T> + class my_atomic { + public: + T fetch_inc(memory_order order) volatile; + T fetch_dec(memory_order order) volatile; + T fetch_add_var(T counter, memory_order order) volatile; + }; + +These helper templates are defined in [^boost/atomic/detail/builder.hpp]. + +[endsect] + +[section:automatic_buildup_small Build sub-word-sized atomic data types] + +There is one other helper template that can build sub-word-sized +atomic data types even though the underlying architecture allows +only word-sized atomic operations: + +[c++] + + template<typename T> + class platform_atomic_integral<T, 1> : + public build_atomic_from_larger_type<my_atomic_32<uint32_t>, T> + { + public: + typedef build_atomic_from_larger_type<my_atomic_32<uint32_t>, T> super; + + explicit platform_atomic_integral(T v) : super(v) {} + platform_atomic_integral(void) {} + }; + +The above would create an atomic data type of 1 byte size, and +use masking and shifts to map it to 32-bit atomic operations. +The base type must implement [^load], [^store] +and [^compare_exchange_weak] for this to work. + +[endsect] + +[section:other_sizes Atomic data types for unusual object sizes] + +In unusual circumstances, an implementor may also opt to specialize +[^public boost::detail::atomic::platform_atomic<T,S=sizeof(T)>] +to provide support for atomic objects not fitting an integral size. +If you do that, keep the following things in mind: + +* There is no reason to ever do this for object sizes + of 1, 2, 4 and 8 +* Only the following methods need to be implemented: + * [^load] + * [^store] + * [^compare_exchange_weak] (4-operand version) + * [^compare_exchange_strong] (4-operand version) + * [^exchange] + +The type of the data to be stored in the atomic +variable (template parameter [^T]) +is exposed to this class, and the type may have +overloaded assignment and comparison operators -- +using these overloaded operators however will result +in an error. The implementor is responsible for +accessing the objects in a way that does not +invoke either of these operators (using e.g. +[^memcpy] or type-casts). + +[endsect] + +[endsect] + +[section:platform_atomic_fences Fences] + +Platform implementors need to provide a function performing +the action required for [funcref boost::atomic_thread_fence atomic_thread_fence] +(the fallback implementation will just perform an atomic operation +on an integer object). This is achieved by specializing the +[^boost::detail::atomic::platform_atomic_thread_fence] template +function in the following way: + +[c++] + + template<> + void platform_atomic_thread_fence(memory_order order) + { + // platform-specific code here + } + +[endsect] + +[section:platform_atomic_puttogether Putting it altogether] + +The template specializations should be put into a header file +in the [^boost/atomic/detail] directory, preferably +specifying supported compiler and architecture in its name. + +The file [^boost/atomic/detail/platform.hpp] must +subsequently be modified to conditionally include the new +header. + +[endsect] |