Math API nvidia_logo_transpbg.gif Up
atom.h
Go to the documentation of this file.
1/***************************************************************************************************
2 * Copyright 2025 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_BASE_ATOM32_USE_ATOMIC) && !defined( MI_BASE_ATOM32_USE_ASSEMBLY)
17#if defined( MI_ARCH_X86) && (defined( MI_COMPILER_GCC) || defined( MI_COMPILER_ICC))
18# define MI_BASE_ATOM32_USE_ASSEMBLY
19#else
20# define MI_BASE_ATOM32_USE_ATOMIC
21#endif
22#endif
23
24// Sanity check.
25#if ! (defined( MI_BASE_ATOM32_USE_ATOMIC) ^ defined( MI_BASE_ATOM32_USE_ASSEMBLY))
26#error Exactly one of MI_BASE_ATOM32_USE_ATOMIC and MI_BASE_ATOM32_USE_ASSEMBLY should be defined.
27#endif
28
29#if defined( MI_BASE_ATOM32_USE_ATOMIC)
30#include <atomic>
31#endif
32
33namespace mi {
34
35namespace base {
36
42class Atom32
43{
44public:
46 Atom32() : m_value( 0) { }
47
49 Atom32( const Uint32 value) : m_value( value) { }
50
51#ifndef MI_BASE_ATOM32_USE_ASSEMBLY
53 Atom32( const Atom32& other);
54
56 Atom32& operator=( const Atom32& rhs);
57#endif
58
60 Uint32 operator=( const Uint32 rhs) { m_value = rhs; return rhs; }
61
64
67
70
73
76
79
81 operator Uint32() const { return m_value; }
82
84 Uint32 swap( const Uint32 rhs);
85
86private:
87#ifdef MI_BASE_ATOM32_USE_ASSEMBLY
88 // The counter.
89 volatile Uint32 m_value;
90#else
91 // The counter.
92 std::atomic_uint32_t m_value;
93#endif
94};
95
96#ifndef MI_FOR_DOXYGEN_ONLY
97
98#ifdef MI_BASE_ATOM32_USE_ASSEMBLY
99
100inline Uint32 Atom32::operator+=( const Uint32 rhs)
101{
102 Uint32 retval;
103 asm volatile(
104 "movl %2,%0\n"
105 "lock; xaddl %0,%1\n"
106 "addl %2,%0\n"
107 : "=&r"( retval), "+m"( m_value)
108 : "r"( rhs)
109 : "cc"
110 );
111 return retval;
112}
113
114inline Uint32 Atom32::operator-=( const Uint32 rhs)
115{
116 Uint32 retval;
117 asm volatile(
118 "neg %2\n"
119 "movl %2,%0\n"
120 "lock; xaddl %0,%1\n"
121 "addl %2,%0\n"
122 : "=&r"( retval), "+m"( m_value)
123 : "r"( rhs)
124 : "cc", "%2"
125 );
126 return retval;
127}
128
130{
131 Uint32 retval;
132 asm volatile(
133 "movl $1,%0\n"
134 "lock; xaddl %0,%1\n"
135 "addl $1,%0\n"
136 : "=&r"( retval), "+m"( m_value)
137 :
138 : "cc"
139 );
140 return retval;
141}
142
143inline Uint32 Atom32::operator++( int)
144{
145 Uint32 retval;
146 asm volatile(
147 "movl $1,%0\n"
148 "lock; xaddl %0,%1\n"
149 : "=&r"( retval), "+m"( m_value)
150 :
151 : "cc"
152 );
153 return retval;
154}
155
157{
158 Uint32 retval;
159 asm volatile(
160 "movl $-1,%0\n"
161 "lock; xaddl %0,%1\n"
162 "addl $-1,%0\n"
163 : "=&r"( retval), "+m"( m_value)
164 :
165 : "cc"
166 );
167 return retval;
168}
169
170inline Uint32 Atom32::operator--( int)
171{
172 Uint32 retval;
173 asm volatile(
174 "movl $-1,%0\n"
175 "lock; xaddl %0,%1\n"
176 : "=&r"( retval), "+m"( m_value)
177 :
178 : "cc"
179 );
180 return retval;
181}
182
183inline Uint32 Atom32::swap( const Uint32 rhs)
184{
185 Uint32 retval;
186 asm volatile(
187 "0:\n"
188 "movl %1,%0\n"
189 "lock; cmpxchg %2,%1\n"
190 "jnz 0b\n"
191 : "=&a"( retval), "+m"( m_value)
192 : "r"( rhs)
193 : "cc"
194 );
195 return retval;
196}
197
198#else
199
200inline Atom32::Atom32( const Atom32& other) : m_value( other.m_value.load()) { }
201
202inline Atom32& Atom32::operator=( const Atom32& rhs)
203{
204 m_value = rhs.m_value.load();
205 return *this;
206}
207
208inline Uint32 Atom32::operator+=( const Uint32 rhs)
209{
210 m_value += rhs;
211 return m_value;
212}
213
214inline Uint32 Atom32::operator-=( const Uint32 rhs)
215{
216 m_value -= rhs;
217 return m_value;
218}
219
221{
222 return ++m_value;
223}
224
225inline Uint32 Atom32::operator++( int)
226{
227 return m_value++;
228}
229
231{
232 return --m_value;
233}
234
235inline Uint32 Atom32::operator--( int)
236{
237 return m_value--;
238}
239
240inline Uint32 Atom32::swap( const Uint32 rhs)
241{
242 return m_value.exchange( rhs);
243}
244
245#endif // MI_BASE_ATOM32_USE_ASSEMBLY
246
247#endif // !MI_FOR_DOXYGEN_ONLY
248 // end group mi_base_threads
250
251} // namespace base
252
253} // namespace mi
254
255#endif // MI_BASE_ATOM_H
A 32-bit unsigned counter with atomic arithmetic, increments, and decrements.
Definition: atom.h:43
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:46
Uint32 operator+=(const Uint32 rhs)
Adds rhs to the counter.
Uint32 operator=(const Uint32 rhs)
Assigns rhs to the counter.
Definition: atom.h:60
Uint32 operator++(int)
Increments the counter by one (post-increment).
Atom32(const Uint32 value)
This constructor initializes the counter to value.
Definition: atom.h:49
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
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH.
Definition: math.h:22
Basic types.