3 //=============================================================================
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //=============================================================================
11 #ifndef ACE_ATOMIC_OP_H
12 #define ACE_ATOMIC_OP_H
13 #include /**/ "ace/pre.h"
15 #include /**/ "ace/config-all.h"
17 #if !defined (ACE_LACKS_PRAGMA_ONCE)
19 #endif /* ACE_LACKS_PRAGMA_ONCE */
21 #include "ace/Thread_Mutex.h"
23 // Include the templates here.
24 #include "ace/Atomic_Op_T.h"
26 // Determine whether builtin atomic op support is
27 // available on this platform.
28 #if defined (ACE_HAS_THREADS)
30 # if defined (ACE_HAS_INTRINSIC_INTERLOCKED)
31 # define ACE_HAS_BUILTIN_ATOMIC_OP
32 # endif /* ACE_HAS_INTRINSIC_INTERLOCKED */
33 # if defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
34 # define ACE_HAS_BUILTIN_ATOMIC_OP
35 # else /* ACE_HAS_INTERLOCKED_EXCHANGEADD */
36 // Inline assembly emulation of InterlockedExchangeAdd
37 // is currently only implemented for MSVC (x86 only) and Borland.
38 # if (defined (_MSC_VER) && defined (_M_IX86)) || defined (__BORLANDC__)
39 # define ACE_HAS_BUILTIN_ATOMIC_OP
40 # endif /* _MSC_VER || __BORLANDC__ */
41 # endif /* ACE_HAS_INTERLOCKED_EXCHANGEADD */
42 # elif defined (ACE_HAS_INTEL_ASSEMBLY)
43 # define ACE_HAS_BUILTIN_ATOMIC_OP
44 # elif defined (ACE_HAS_VXATOMICLIB)
45 # define ACE_HAS_BUILTIN_ATOMIC_OP
47 #endif /* ACE_HAS_THREADS */
49 // If we have the GCC Atomic builtin support, use it
50 #if defined (ACE_HAS_GCC_ATOMIC_BUILTINS) && (ACE_HAS_GCC_ATOMIC_BUILTINS == 1)
51 # undef ACE_HAS_BUILTIN_ATOMIC_OP
54 // Include the templates here.
55 #include "ace/Atomic_Op_GCC_T.h"
57 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
59 #if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
62 * @brief Specialization of ACE_Atomic_Op for platforms that
63 * support atomic integer operations.
65 * Specialization of ACE_Atomic_Op for platforms that support atomic
69 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, long>
72 /// Initialize @c value_ to 0.
75 /// Initialize @c value_ to c.
76 ACE_Atomic_Op (long c
);
79 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &c
);
81 /// Atomically pre-increment @c value_.
84 /// Atomically post-increment @c value_.
85 long operator++ (int);
87 /// Atomically increment @c value_ by rhs.
88 long operator+= (long rhs
);
90 /// Atomically pre-decrement @c value_.
93 /// Atomically post-decrement @c value_.
94 long operator-- (int);
96 /// Atomically decrement @c value_ by rhs.
97 long operator-= (long rhs
);
99 /// Atomically compare @c value_ with rhs.
100 bool operator== (long rhs
) const;
102 /// Atomically compare @c value_ with rhs.
103 bool operator!= (long rhs
) const;
105 /// Atomically check if @c value_ greater than or equal to rhs.
106 bool operator>= (long rhs
) const;
108 /// Atomically check if @c value_ greater than rhs.
109 bool operator> (long rhs
) const;
111 /// Atomically check if @c value_ less than or equal to rhs.
112 bool operator<= (long rhs
) const;
114 /// Atomically check if @c value_ less than rhs.
115 bool operator< (long rhs
) const;
117 /// Atomically assign rhs to @c value_.
118 ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &operator= (long rhs
);
120 /// Atomically assign <rhs> to @c value_.
121 ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &rhs
);
123 /// Exchange value with @a newval.
124 long exchange (long newval
);
126 /// Explicitly return @c value_.
129 /// Dump the state of an object.
132 /// Explicitly return @c value_ (by reference).
133 volatile long &value_i ();
135 // ACE_ALLOC_HOOK_DECLARE;
136 // Declare the dynamic allocation hooks.
138 /// Used during ACE object manager initialization to optimize the fast
139 /// atomic op implementation according to the number of CPUs.
140 static void init_functions ();
143 /// This function cannot be supported by this template specialization.
144 /// If you need access to an underlying lock, use the ACE_Atomic_Op_Ex
145 /// template instead.
146 ACE_Thread_Mutex
&mutex ();
149 /// Current object decorated by the atomic op.
150 volatile long value_
;
152 /// Pointers to selected atomic op implementations.
153 static long (*increment_fn_
) (volatile long *);
154 static long (*decrement_fn_
) (volatile long *);
155 static long (*exchange_fn_
) (volatile long *, long);
156 static long (*exchange_add_fn_
) (volatile long *, long);
160 * @brief Specialization of ACE_Atomic_Op for platforms that
161 * support atomic integer operations.
163 * Specialization of ACE_Atomic_Op for platforms that support atomic
164 * integer operations.
167 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long>
170 /// Initialize @c value_ to 0.
173 /// Initialize @c value_ to c.
174 ACE_Atomic_Op (unsigned long c
);
176 /// Manage copying...
177 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &c
);
179 /// Atomically pre-increment @c value_.
180 unsigned long operator++ ();
182 /// Atomically post-increment @c value_.
183 unsigned long operator++ (int);
185 /// Atomically increment @c value_ by rhs.
186 unsigned long operator+= (unsigned long rhs
);
188 /// Atomically pre-decrement @c value_.
189 unsigned long operator-- ();
191 /// Atomically post-decrement @c value_.
192 unsigned long operator-- (int);
194 /// Atomically decrement @c value_ by rhs.
195 unsigned long operator-= (unsigned long rhs
);
197 /// Atomically compare @c value_ with rhs.
198 bool operator== (unsigned long rhs
) const;
200 /// Atomically compare @c value_ with rhs.
201 bool operator!= (unsigned long rhs
) const;
203 /// Atomically check if @c value_ greater than or equal to rhs.
204 bool operator>= (unsigned long rhs
) const;
206 /// Atomically check if @c value_ greater than rhs.
207 bool operator> (unsigned long rhs
) const;
209 /// Atomically check if @c value_ less than or equal to rhs.
210 bool operator<= (unsigned long rhs
) const;
212 /// Atomically check if @c value_ less than rhs.
213 bool operator< (unsigned long rhs
) const;
215 /// Atomically assign rhs to @c value_.
216 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &operator= (unsigned long rhs
);
218 /// Atomically assign <rhs> to @c value_.
219 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &rhs
);
221 /// Exchange value with @a newval.
222 unsigned long exchange (unsigned long newval
);
224 /// Explicitly return @c value_.
225 unsigned long value () const;
227 /// Dump the state of an object.
230 /// Explicitly return @c value_ (by reference).
231 volatile unsigned long &value_i ();
233 // ACE_ALLOC_HOOK_DECLARE;
234 // Declare the dynamic allocation hooks.
236 /// Used during ACE object manager initialization to optimize the fast
237 /// atomic op implementation according to the number of CPUs.
238 static void init_functions ();
241 /// This function cannot be supported by this template specialization.
242 /// If you need access to an underlying lock, use the ACE_Atomic_Op_Ex
243 /// template instead.
244 ACE_Thread_Mutex
&mutex ();
247 /// Current object decorated by the atomic op.
248 volatile unsigned long value_
;
250 // Pointers to selected atomic op implementations.
251 static long (*increment_fn_
) (volatile long *);
252 static long (*decrement_fn_
) (volatile long *);
253 static long (*exchange_fn_
) (volatile long *, long);
254 static long (*exchange_add_fn_
) (volatile long *, long);
257 #endif /* !ACE_HAS_BUILTIN_ATOMIC_OP */
259 #if defined (ACE_HAS_GCC_ATOMIC_BUILTINS) && (ACE_HAS_GCC_ATOMIC_BUILTINS == 1)
262 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, int>
263 : public ACE_Atomic_Op_GCC
<int>
267 ACE_Atomic_Op (int c
);
268 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, int> &c
);
269 ACE_Atomic_Op
<ACE_Thread_Mutex
, int> &operator= (int rhs
);
270 ACE_Atomic_Op
<ACE_Thread_Mutex
, int> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, int> &rhs
);
274 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned int>
275 : public ACE_Atomic_Op_GCC
<unsigned int>
279 ACE_Atomic_Op (unsigned int c
);
280 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned> &c
);
281 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned int> &operator= (unsigned int rhs
);
282 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned int> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned int> &rhs
);
285 // If we have built in atomic op, use that, the assignment operator
286 // is faster for a long/unsinged long
288 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, long>
289 : public ACE_Atomic_Op_GCC
<long>
293 ACE_Atomic_Op (long c
);
294 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &c
);
295 ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &operator= (long rhs
);
296 ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long> &rhs
);
300 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long>
301 : public ACE_Atomic_Op_GCC
<unsigned long>
305 ACE_Atomic_Op (unsigned long c
);
306 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &c
);
307 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &operator= (unsigned long rhs
);
308 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> &c
);
311 // The long long intrinsics are not available on PPC
312 #if !defined (__powerpc__)
314 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, long long>
315 : public ACE_Atomic_Op_GCC
<long long>
319 ACE_Atomic_Op (long long c
);
320 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long long> &c
);
321 ACE_Atomic_Op
<ACE_Thread_Mutex
, long long> &operator= (long long rhs
);
322 ACE_Atomic_Op
<ACE_Thread_Mutex
, long long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, long long> &c
);
326 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long long>
327 : public ACE_Atomic_Op_GCC
<unsigned long long>
331 ACE_Atomic_Op (unsigned long long c
);
332 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long long> &c
);
333 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long long> &operator= (unsigned long long rhs
);
334 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long long> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long long> &c
);
336 #endif /* !__powerpc__ */
338 #if !defined (ACE_LACKS_GCC_ATOMIC_BUILTINS_2)
340 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, short>
341 : public ACE_Atomic_Op_GCC
<short>
345 ACE_Atomic_Op (short c
);
346 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, short> &c
);
347 ACE_Atomic_Op
<ACE_Thread_Mutex
, short> &operator= (short rhs
);
348 ACE_Atomic_Op
<ACE_Thread_Mutex
, short> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, short> &c
);
352 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned short>
353 : public ACE_Atomic_Op_GCC
<unsigned short>
357 ACE_Atomic_Op (unsigned short c
);
358 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned short> &c
);
359 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned short> &operator= (unsigned short rhs
);
360 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned short> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned short> &c
);
364 #if !defined (ACE_LACKS_GCC_ATOMIC_BUILTINS_1)
366 class ACE_Export ACE_Atomic_Op
<ACE_Thread_Mutex
, bool>
367 : public ACE_Atomic_Op_GCC
<bool>
371 ACE_Atomic_Op (bool c
);
372 ACE_Atomic_Op (const ACE_Atomic_Op
<ACE_Thread_Mutex
, bool> &c
);
373 ACE_Atomic_Op
<ACE_Thread_Mutex
, bool> &operator= (bool rhs
);
374 ACE_Atomic_Op
<ACE_Thread_Mutex
, bool> &operator= (const ACE_Atomic_Op
<ACE_Thread_Mutex
, bool> &c
);
378 #endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
380 ACE_END_VERSIONED_NAMESPACE_DECL
382 #if defined (__ACE_INLINE__)
383 #include "ace/Atomic_Op.inl"
384 #endif /* __ACE_INLINE__ */
386 #include /**/ "ace/post.h"
387 #endif /*ACE_ATOMIC_OP_H*/