Base API nvidia_logo_transpbg.gif Up
atom.h
Go to the documentation of this file.
1/***************************************************************************************************
2 * Copyright 2024 NVIDIA Corporation. All rights reserved.
3 **************************************************************************************************/
8
9#ifndef MI_BASE_ATOM_H
10#define MI_BASE_ATOM_H
11
12#include <mi/base/config.h>
13#include <mi/base/types.h>
14
15// Select implementation to use
16#if defined( MI_ARCH_X86) && (defined( MI_COMPILER_GCC) || defined( MI_COMPILER_ICC))
17# define MI_ATOM32_X86GCC
18#elif (__cplusplus >= 201103L)
19# define MI_ATOM32_STD
20# include <atomic>
21#elif defined( MI_ARCH_X86) && defined( MI_COMPILER_MSC)
22# define MI_ATOM32_X86MSC
23# include <intrin.h>
24# pragma intrinsic( _InterlockedExchangeAdd)
25# pragma intrinsic( _InterlockedCompareExchange)
26#else
27# define MI_ATOM32_GENERIC
28# include <mi/base/lock.h>
29#endif
30
31namespace mi {
32
33namespace base {
34
40class Atom32
41{
42public:
44 Atom32() : m_value( 0) { }
45
47 Atom32( const Uint32 value) : m_value( value) { }
48
49#if defined( MI_ATOM32_STD) || defined( MI_ATOM32_GENERIC)
51 Atom32( const Atom32& other);
52
54 Atom32& operator=( const Atom32& rhs);
55#endif
56
58 Uint32 operator=( const Uint32 rhs) { m_value = rhs; return rhs; }
59
62
65
68
71
74
77
79 operator Uint32() const { return m_value; }
80
82 Uint32 swap( const Uint32 rhs);
83
84private:
85#if defined( MI_ATOM32_STD)
86 // The counter.
87#if defined( MI_COMPILER_GCC) && (__GNUC__ <= 6)
88 std::atomic<std::uint32_t> m_value;
89#else
90 std::atomic_uint32_t m_value;
91#endif
92#else
93 // The counter.
94 volatile Uint32 m_value;
95#endif
96
97#if defined( MI_ATOM32_GENERIC)
98 // The lock for #m_value needed by the generic implementation.
99 mi::base::Lock m_lock;
100#endif
101};
102
103#if !defined( MI_FOR_DOXYGEN_ONLY)
104
105#if defined( MI_ATOM32_X86GCC)
106
107inline Uint32 Atom32::operator+=( const Uint32 rhs)
108{
109 Uint32 retval;
110 asm volatile(
111 "movl %2,%0\n"
112 "lock; xaddl %0,%1\n"
113 "addl %2,%0\n"
114 : "=&r"( retval), "+m"( m_value)
115 : "r"( rhs)
116 : "cc"
117 );
118 return retval;
119}
120
121inline Uint32 Atom32::operator-=( const Uint32 rhs)
122{
123 Uint32 retval;
124 asm volatile(
125 "neg %2\n"
126 "movl %2,%0\n"
127 "lock; xaddl %0,%1\n"
128 "addl %2,%0\n"
129 : "=&r"( retval), "+m"( m_value)
130 : "r"( rhs)
131 : "cc", "%2"
132 );
133 return retval;
134}
135
137{
138 Uint32 retval;
139 asm volatile(
140 "movl $1,%0\n"
141 "lock; xaddl %0,%1\n"
142 "addl $1,%0\n"
143 : "=&r"( retval), "+m"( m_value)
144 :
145 : "cc"
146 );
147 return retval;
148}
149
150inline Uint32 Atom32::operator++( int)
151{
152 Uint32 retval;
153 asm volatile(
154 "movl $1,%0\n"
155 "lock; xaddl %0,%1\n"
156 : "=&r"( retval), "+m"( m_value)
157 :
158 : "cc"
159 );
160 return retval;
161}
162
164{
165 Uint32 retval;
166 asm volatile(
167 "movl $-1,%0\n"
168 "lock; xaddl %0,%1\n"
169 "addl $-1,%0\n"
170 : "=&r"( retval), "+m"( m_value)
171 :
172 : "cc"
173 );
174 return retval;
175}
176
177inline Uint32 Atom32::operator--( int)
178{
179 Uint32 retval;
180 asm volatile(
181 "movl $-1,%0\n"
182 "lock; xaddl %0,%1\n"
183 : "=&r"( retval), "+m"( m_value)
184 :
185 : "cc"
186 );
187 return retval;
188}
189
190inline Uint32 Atom32::swap( const Uint32 rhs)
191{
192 Uint32 retval;
193 asm volatile(
194 "0:\n"
195 "movl %1,%0\n"
196 "lock; cmpxchg %2,%1\n"
197 "jnz 0b\n"
198 : "=&a"( retval), "+m"( m_value)
199 : "r"( rhs)
200 : "cc"
201 );
202 return retval;
203}
204
205#elif defined( MI_ATOM32_STD)
206
207inline Atom32::Atom32( const Atom32& other) : m_value( other.m_value.load()) { }
208
209inline Atom32& Atom32::operator=( const Atom32& rhs)
210{
211 m_value = rhs.m_value.load();
212 return *this;
213}
214
215inline Uint32 Atom32::operator+=( const Uint32 rhs)
216{
217 m_value += rhs;
218 return m_value;
219}
220
221inline Uint32 Atom32::operator-=( const Uint32 rhs)
222{
223 m_value -= rhs;
224 return m_value;
225}
226
228{
229 return ++m_value;
230}
231
232inline Uint32 Atom32::operator++( int)
233{
234 return m_value++;
235}
236
238{
239 return --m_value;
240}
241
242inline Uint32 Atom32::operator--( int)
243{
244 return m_value--;
245}
246
247inline Uint32 Atom32::swap( const Uint32 rhs)
248{
249 return m_value.exchange( rhs);
250}
251
252#elif defined( MI_ATOM32_X86MSC)
253
254__forceinline Uint32 Atom32::operator+=( const Uint32 rhs)
255{
256 return _InterlockedExchangeAdd( reinterpret_cast<volatile long*>( &m_value), rhs) + rhs;
257}
258
259__forceinline Uint32 Atom32::operator-=( const Uint32 rhs)
260{
261 return _InterlockedExchangeAdd(
262 reinterpret_cast<volatile long*>( &m_value), -static_cast<const Sint32>( rhs)) - rhs;
263}
264
265__forceinline Uint32 Atom32::operator++()
266{
267 return _InterlockedExchangeAdd( reinterpret_cast<volatile long*>( &m_value), 1L) + 1L;
268}
269
270__forceinline Uint32 Atom32::operator++( int)
271{
272 return _InterlockedExchangeAdd( reinterpret_cast<volatile long*>( &m_value), 1L);
273}
274
275__forceinline Uint32 Atom32::operator--()
276{
277 return _InterlockedExchangeAdd( reinterpret_cast<volatile long*>( &m_value), -1L) - 1L;
278}
279
280__forceinline Uint32 Atom32::operator--( int)
281{
282 return _InterlockedExchangeAdd( reinterpret_cast<volatile long*>( &m_value), -1L);
283}
284
285__forceinline Uint32 Atom32::swap( const Uint32 rhs)
286{
287 return _InterlockedExchange( reinterpret_cast<volatile long*>( &m_value), rhs);
288}
289
290#elif defined( MI_ATOM32_GENERIC)
291
292inline Atom32::Atom32( const Atom32& other) : m_value( other.m_value) { }
293
294inline Atom32& Atom32::operator=( const Atom32& rhs)
295{
296 m_value = rhs.m_value;
297 return *this;
298}
299
300inline Uint32 Atom32::operator+=( const Uint32 rhs)
301{
302 mi::base::Lock::Block block( &m_lock);
303 return m_value += rhs;
304}
305
306inline Uint32 Atom32::operator-=( const Uint32 rhs)
307{
308 mi::base::Lock::Block block( &m_lock);
309 return m_value -= rhs;
310}
311
313{
314 mi::base::Lock::Block block( &m_lock);
315 return ++m_value;
316}
317
318inline Uint32 Atom32::operator++( int)
319{
320 mi::base::Lock::Block block( &m_lock);
321 return m_value++;
322}
323
325{
326 mi::base::Lock::Block block( &m_lock);
327 return --m_value;
328}
329
330inline Uint32 Atom32::operator--( int)
331{
332 mi::base::Lock::Block block( &m_lock);
333 return m_value--;
334}
335
336inline Uint32 Atom32::swap( const Uint32 rhs)
337{
338 mi::base::Lock::Block block( &m_lock);
339 Uint32 retval = m_value;
340 m_value = rhs;
341 return retval;
342}
343
344#else
345#error One of MI_ATOM32_X86GCC, MI_ATOM32_STD, MI_ATOM32_X86MSC, or MI_ATOM32_GENERIC must be \
346 defined.
347#endif
348
349#undef MI_ATOM32_X86GCC
350#undef MI_ATOM32_STD
351#undef MI_ATOM32_X86MSC
352#undef MI_ATOM32_GENERIC
353
354#endif // !MI_FOR_DOXYGEN_ONLY
355 // end group mi_base_threads
357
358} // namespace base
359
360} // namespace mi
361
362#endif // MI_BASE_ATOM_H
A 32-bit unsigned counter with atomic arithmetic, increments, and decrements.
Definition: atom.h:41
Utility class to acquire a lock that is released by the destructor.
Definition: lock.h:61
Non-recursive lock class.
Definition: lock.h:49
Configuration of the Base API.
Uint32 operator-=(const Uint32 rhs)
Subtracts rhs from the counter.
Uint32 operator--(int)
Decrements the counter by one (post-decrement).
Atom32()
The default constructor initializes the counter to zero.
Definition: atom.h:44
Uint32 operator+=(const Uint32 rhs)
Adds rhs to the counter.
Uint32 operator=(const Uint32 rhs)
Assigns rhs to the counter.
Definition: atom.h:58
Uint32 operator++(int)
Increments the counter by one (post-increment).
Atom32(const Uint32 value)
This constructor initializes the counter to value.
Definition: atom.h:47
Atom32(const Atom32 &other)
The copy constructor assigns the value of other to the counter.
Uint32 operator++()
Increments the counter by one (pre-increment).
Atom32 & operator=(const Atom32 &rhs)
Assigns the value of rhs to the counter.
Uint32 swap(const Uint32 rhs)
Assigns rhs to the counter and returns the old value of counter.
Uint32 operator--()
Decrements the counter by one (pre-decrement).
unsigned int Uint32
32-bit unsigned integer.
Definition: types.h:49
signed int Sint32
32-bit signed integer.
Definition: types.h:46
Multithreading locks.
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH.
Definition: base.h:34
Basic types.