2 / Copyright (c) 2009 Helge Bahmann
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 [section:template_organization Organization of class template layers]
10 The implementation uses multiple layers of template classes that
11 inherit from the next lower level each and refine or adapt the respective
14 * [^boost::atomic<T>] is the topmost-level, providing
15 the external interface. Implementation-wise, it does not add anything
16 (except for hiding copy constructor and assignment operator).
18 * [^boost::detail::atomic::internal_atomic&<T,S=sizeof(T),I=is_integral_type<T> >]:
19 This layer is mainly responsible for providing the overloaded operators
20 mapping to API member functions (e.g. [^+=] to [^fetch_add]).
21 The defaulted template parameter [^I] allows
22 to expose the correct API functions (via partial template
23 specialization): For non-integral types, it only
24 publishes the various [^exchange] functions
25 as well as load and store, for integral types it
26 additionally exports arithmetic and logic operations.
28 Depending on whether the given type is integral, it
29 inherits from either [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>]
30 or [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>].
31 There is however some special-casing: for non-integral types
32 of size 1, 2, 4 or 8, it will coerce the datatype into an integer representation
33 and delegate to [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]
34 -- the rationale is that platform implementors only need to provide
35 integer-type operations.
37 * [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]
38 must provide the full set of operations for an integral type T
39 (i.e. [^load], [^store], [^exchange],
40 [^compare_exchange_weak], [^compare_exchange_strong],
41 [^fetch_add], [^fetch_sub], [^fetch_and],
42 [^fetch_or], [^fetch_xor], [^is_lock_free]).
43 The default implementation uses locking to emulate atomic operations, so
44 this is the level at which implementors should provide template specializations
45 to add support for platform-specific atomic operations.
47 The two separate template parameters allow separate specialization
48 on size and type (which, with fixed size, cannot
49 specify more than signedness/unsignedness). The rationale is that
50 most platform-specific atomic operations usually depend only on the
51 operand size, so that common implementations for signed/unsigned
52 types are possible. Signedness allows to properly to choose sign-extending
53 instructions for the [^load] operation, avoiding later
54 conversion. The expectation is that in most implementations this will
55 be a normal assignment in C, possibly accompanied by memory
56 fences, so that the compiler can automatically choose the correct
59 * At the lowest level, [^boost::detail::atomic::platform_atomic<T,S=sizeof(T)>]
60 provides the most basic atomic operations ([^load], [^store],
61 [^exchange], [^compare_exchange_weak],
62 [^compare_exchange_strong]) for arbitrarily generic data types.
63 The default implementation uses locking as a fallback mechanism.
64 Implementors generally do not have to specialize at this level
65 (since these will not be used for the common integral type sizes
66 of 1, 2, 4 and 8 bytes), but if s/he can if s/he so wishes to
67 provide truly atomic operations for "odd" data type sizes.
68 Some amount of care must be taken as the "raw" data type
69 passed in from the user through [^boost::atomic<T>]
70 is visible here -- it thus needs to be type-punned or otherwise
71 manipulated byte-by-byte to avoid using overloaded assignment,
72 comparison operators and copy constructors.
77 [section:platform_atomic_implementation Implementing platform-specific atomic operations]
79 In principle implementors are responsible for providing the
80 full range of named member functions of an atomic object
81 (i.e. [^load], [^store], [^exchange],
82 [^compare_exchange_weak], [^compare_exchange_strong],
83 [^fetch_add], [^fetch_sub], [^fetch_and],
84 [^fetch_or], [^fetch_xor], [^is_lock_free]).
85 These must be implemented as partial template specializations for
86 [^boost::detail::atomic::platform_atomic_integral<T,S=sizeof(T)>]:
91 class platform_atomic_integral<T, 4>
94 explicit platform_atomic_integral(T v) : i(v) {}
95 platform_atomic_integral(void) {}
97 T load(memory_order order=memory_order_seq_cst) const volatile
99 // platform-specific code
101 void store(T v, memory_order order=memory_order_seq_cst) volatile
103 // platform-specific code
110 As noted above, it will usually suffice to specialize on the second
111 template argument, indicating the size of the data type in bytes.
113 [section:automatic_buildup Templates for automatic build-up]
115 Often only a portion of the required operations can be
116 usefully mapped to machine instructions. Several helper template
117 classes are provided that can automatically synthesize missing methods to
118 complete an implementation.
120 At the minimum, an implementor must provide the
122 [^compare_exchange_weak] and
123 [^is_lock_free] methods:
131 my_atomic_32(T initial_value) : value(initial_value) {}
133 T load(memory_order order=memory_order_seq_cst) volatile const
135 // platform-specific code
137 void store(T new_value, memory_order order=memory_order_seq_cst) volatile
139 // platform-specific code
141 bool compare_exchange_weak(T &expected, T desired,
142 memory_order success_order,
143 memory_order_failure_order) volatile
145 // platform-specific code
147 bool is_lock_free() const volatile {return true;}
149 // typedef is required for classes inheriting from this
150 typedef T integral_type;
155 The template [^boost::detail::atomic::build_atomic_from_minimal]
156 can then take care of the rest:
161 class platform_atomic_integral<T, 4>
162 : public boost::detail::atomic::build_atomic_from_minimal<my_atomic_32<T> >
165 typedef build_atomic_from_minimal<my_atomic_32<T> > super;
167 explicit platform_atomic_integral(T v) : super(v) {}
168 platform_atomic_integral(void) {}
171 There are several helper classes to assist in building "complete"
172 atomic implementations from different starting points:
174 * [^build_atomic_from_minimal] requires
177 * [^compare_exchange_weak] (4-operand version)
179 * [^build_atomic_from_exchange] requires
182 * [^compare_exchange_weak] (4-operand version)
183 * [^compare_exchange_strong] (4-operand version)
186 * [^build_atomic_from_add] requires
189 * [^compare_exchange_weak] (4-operand version)
190 * [^compare_exchange_strong] (4-operand version)
194 * [^build_atomic_from_typical] (<I>supported on gcc only</I>) requires
197 * [^compare_exchange_weak] (4-operand version)
198 * [^compare_exchange_strong] (4-operand version)
200 * [^fetch_add_var] (protected method)
201 * [^fetch_inc] (protected method)
202 * [^fetch_dec] (protected method)
204 This will generate a [^fetch_add] method
205 that calls [^fetch_inc]/[^fetch_dec]
206 when the given parameter is a compile-time constant
207 equal to +1 or -1 respectively, and [^fetch_add_var]
208 in all other cases. This provides a mechanism for
209 optimizing the extremely common case of an atomic
210 variable being used as a counter.
212 The prototypes for these methods to be implemented is:
218 T fetch_inc(memory_order order) volatile;
219 T fetch_dec(memory_order order) volatile;
220 T fetch_add_var(T counter, memory_order order) volatile;
223 These helper templates are defined in [^boost/atomic/detail/builder.hpp].
227 [section:automatic_buildup_small Build sub-word-sized atomic data types]
229 There is one other helper template that can build sub-word-sized
230 atomic data types even though the underlying architecture allows
231 only word-sized atomic operations:
236 class platform_atomic_integral<T, 1> :
237 public build_atomic_from_larger_type<my_atomic_32<uint32_t>, T>
240 typedef build_atomic_from_larger_type<my_atomic_32<uint32_t>, T> super;
242 explicit platform_atomic_integral(T v) : super(v) {}
243 platform_atomic_integral(void) {}
246 The above would create an atomic data type of 1 byte size, and
247 use masking and shifts to map it to 32-bit atomic operations.
248 The base type must implement [^load], [^store]
249 and [^compare_exchange_weak] for this to work.
253 [section:other_sizes Atomic data types for unusual object sizes]
255 In unusual circumstances, an implementor may also opt to specialize
256 [^public boost::detail::atomic::platform_atomic<T,S=sizeof(T)>]
257 to provide support for atomic objects not fitting an integral size.
258 If you do that, keep the following things in mind:
260 * There is no reason to ever do this for object sizes
262 * Only the following methods need to be implemented:
265 * [^compare_exchange_weak] (4-operand version)
266 * [^compare_exchange_strong] (4-operand version)
269 The type of the data to be stored in the atomic
270 variable (template parameter [^T])
271 is exposed to this class, and the type may have
272 overloaded assignment and comparison operators --
273 using these overloaded operators however will result
274 in an error. The implementor is responsible for
275 accessing the objects in a way that does not
276 invoke either of these operators (using e.g.
277 [^memcpy] or type-casts).
283 [section:platform_atomic_fences Fences]
285 Platform implementors need to provide a function performing
286 the action required for [funcref boost::atomic_thread_fence atomic_thread_fence]
287 (the fallback implementation will just perform an atomic operation
288 on an integer object). This is achieved by specializing the
289 [^boost::detail::atomic::platform_atomic_thread_fence] template
290 function in the following way:
295 void platform_atomic_thread_fence(memory_order order)
297 // platform-specific code here
302 [section:platform_atomic_puttogether Putting it altogether]
304 The template specializations should be put into a header file
305 in the [^boost/atomic/detail] directory, preferably
306 specifying supported compiler and architecture in its name.
308 The file [^boost/atomic/detail/platform.hpp] must
309 subsequently be modified to conditionally include the new