AAX SDK 2.8.0
Avid Audio Extensions Development Kit
Loading...
Searching...
No Matches
AAX_Atomic.h
Go to the documentation of this file.
1/*================================================================================================*/
2/*
3 * Copyright 2013-2015, 2018, 2023-2024 Avid Technology, Inc.
4 * All rights reserved.
5 *
6 * This file is part of the Avid AAX SDK.
7 *
8 * The AAX SDK is subject to commercial or open-source licensing.
9 *
10 * By using the AAX SDK, you agree to the terms of both the Avid AAX SDK License
11 * Agreement and Avid Privacy Policy.
12 *
13 * AAX SDK License: https://developer.avid.com/aax
14 * Privacy Policy: https://www.avid.com/legal/privacy-policy-statement
15 *
16 * Or: You may also use this code under the terms of the GPL v3 (see
17 * www.gnu.org/licenses).
18 *
19 * THE AAX SDK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 * EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 * DISCLAIMED.
22 *
23 */
24
30/*================================================================================================*/
31
32
33#pragma once
34
35#ifndef AAX_ATOMIC_H_
36#define AAX_ATOMIC_H_
37
38#include "AAX.h"
39#include <stdint.h>
40
41#if (!defined AAX_PointerSize)
42#error Undefined pointer size
43#endif
44
45
47uint32_t AAX_CALLBACK AAX_Atomic_IncThenGet_32(uint32_t & ioData);
48
50uint32_t AAX_CALLBACK AAX_Atomic_DecThenGet_32(uint32_t & ioData);
51
54 volatile uint32_t& ioValue,
55 uint32_t inExchangeValue);
56
59 volatile uint64_t& ioValue,
60 uint64_t inExchangeValue);
61
63template<typename TPointer> TPointer* AAX_CALLBACK AAX_Atomic_Exchange_Pointer(TPointer*& ioValue, TPointer* inExchangeValue)
64{
65#if (AAX_PointerSize == AAXPointer_64bit)
66 return (TPointer*)AAX_Atomic_Exchange_64(*(uint64_t*)(void*)&ioValue, (uint64_t)inExchangeValue);
67#elif (AAX_PointerSize == AAXPointer_32bit)
68 return (TPointer*)AAX_Atomic_Exchange_32(*(uint32_t*)(void*)&ioValue, (uint32_t)inExchangeValue);
69#else
70#error Unsupported pointer size
71#endif
72}
73
76 volatile uint32_t & ioValue,
77 uint32_t inCompareValue,
78 uint32_t inExchangeValue);
79
82 volatile uint64_t& ioValue,
83 uint64_t inCompareValue,
84 uint64_t inExchangeValue);
85
87template<typename TPointer> bool AAX_CALLBACK AAX_Atomic_CompareAndExchange_Pointer(TPointer*& ioValue, TPointer* inCompareValue, TPointer* inExchangeValue)
88{
89#if (AAX_PointerSize == AAXPointer_64bit)
90 return AAX_Atomic_CompareAndExchange_64(*(uint64_t*)(void*)&ioValue, (uint64_t)inCompareValue, (uint64_t)inExchangeValue);
91#elif (AAX_PointerSize == AAXPointer_32bit)
92 return AAX_Atomic_CompareAndExchange_32(*(uint32_t*)(void*)&ioValue, (uint32_t)inCompareValue, (uint32_t)inExchangeValue);
93#else
94#error Unsupported pointer size
95#endif
96}
97
99template<typename TPointer> TPointer* AAX_CALLBACK AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue);
100
101
102
103//TODO: Update all atomic function implementatons with proper acquire/release semantics
104
105
106// GCC/LLVM
107#if defined(__GNUC__)
108
109// These intrinsics require GCC 4.2 or later
110#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
111
112inline uint32_t AAX_CALLBACK
113AAX_Atomic_IncThenGet_32(uint32_t& ioData)
114{
115 return __sync_add_and_fetch(&ioData, 1);
116}
117
118inline uint32_t AAX_CALLBACK
119AAX_Atomic_DecThenGet_32(uint32_t& ioData)
120{
121 return __sync_sub_and_fetch(&ioData, 1);
122}
123
124inline uint32_t
126 volatile uint32_t& ioValue,
127 uint32_t inExchangeValue)
128{
129 return __sync_lock_test_and_set(&ioValue, inExchangeValue);
130}
131
132inline uint64_t
134 volatile uint64_t& ioValue,
135 uint64_t inExchangeValue)
136{
137 return __sync_lock_test_and_set(&ioValue, inExchangeValue);
138}
139
140inline bool
142 volatile uint32_t & ioValue,
143 uint32_t inCompareValue,
144 uint32_t inExchangeValue)
145{
146 return __sync_bool_compare_and_swap(&ioValue, inCompareValue, inExchangeValue);
147}
148
149inline bool
151 volatile uint64_t& ioValue,
152 uint64_t inCompareValue,
153 uint64_t inExchangeValue)
154{
155 return __sync_bool_compare_and_swap(&ioValue, inCompareValue, inExchangeValue);
156}
157
158//TODO: Add GCC version check and alternative implementations for GCC versions that do not support __atomic_load
159template<typename TPointer>
160inline TPointer*
161AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
162{
163 TPointer* value;
164 __atomic_load(const_cast<TPointer * volatile *>(inValue), &(value), __ATOMIC_ACQUIRE);
165 return value;
166}
167
168#else // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
169#error This file requires GCC 4.2 or later
170#endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
171// End GCC/LLVM
172
173
174
175
176
177// Visual C
178#elif defined(_MSC_VER)
179
180#ifndef __INTRIN_H_
181#include <intrin.h>
182#endif
183
184#pragma intrinsic( _InterlockedIncrement, \
185 _InterlockedDecrement, \
186 _InterlockedExchange, \
187 _InterlockedCompareExchange, \
188 _InterlockedCompareExchange64)
189
190inline uint32_t AAX_CALLBACK
191AAX_Atomic_IncThenGet_32(register uint32_t& ioData)
192{
193 return static_cast<uint32_t>(_InterlockedIncrement((volatile long*)&ioData));
194}
195
196inline uint32_t AAX_CALLBACK
197AAX_Atomic_DecThenGet_32(register uint32_t& ioData)
198{
199 return static_cast<uint32_t>(_InterlockedDecrement((volatile long*)&ioData));
200}
201
202inline uint32_t
204 volatile uint32_t& ioDestination,
205 uint32_t inExchangeValue)
206{
207 return static_cast<uint32_t>(_InterlockedExchange((volatile long*)&ioDestination, (long)inExchangeValue));
208}
209
210#if (AAX_PointerSize == AAXPointer_64bit)
211
212#pragma intrinsic( _InterlockedExchange64, \
213 _InterlockedOr64)
214
215inline uint64_t
217 volatile uint64_t& ioValue,
218 uint64_t inExchangeValue)
219{
220 return static_cast<uint64_t>(_InterlockedExchange64((volatile __int64*)&ioValue, (__int64)inExchangeValue));
221}
222
223template<typename TPointer>
224inline TPointer*
225AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
226{
227// Itanium supports acquire semantics
228#if (_M_IA64)
229 return reinterpret_cast<TPointer*>(_InterlockedOr64_acq(const_cast<__int64 volatile *>(reinterpret_cast<const __int64 volatile *>(inValue)), 0x0000000000000000));
230#else
231 return reinterpret_cast<TPointer*>(_InterlockedOr64(const_cast<__int64 volatile *>(reinterpret_cast<const __int64 volatile *>(inValue)), 0x0000000000000000));
232#endif
233}
234
235#elif (AAX_PointerSize == AAXPointer_32bit)
236
237#pragma intrinsic( _InterlockedOr )
238
239// _InterlockedExchange64 is not available on 32-bit Pentium in Visual C
240inline uint64_t
242 volatile uint64_t& ioValue,
243 uint64_t inExchangeValue)
244{
245 for(;;)
246 {
247 uint64_t result = ioValue;
248 if(AAX_Atomic_CompareAndExchange_64(ioValue, result, inExchangeValue))
249 {
250 return result;
251 }
252 }
253
254 return 0; // will never get here
255}
256
257template<typename TPointer>
258inline TPointer*
259AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
260{
261 return reinterpret_cast<TPointer*>(_InterlockedOr(const_cast<long volatile *>(reinterpret_cast<const long volatile *>(inValue)), 0x00000000));
262}
263
264#endif
265
266inline bool
268 uint32_t volatile & ioValue,
269 uint32_t inCompareValue,
270 uint32_t inExchangeValue)
271{
272 return static_cast<uint32_t>(_InterlockedCompareExchange((volatile long*)&ioValue, (long)inExchangeValue, (long)inCompareValue)) == inCompareValue;
273}
274
275inline bool
277 volatile uint64_t& ioValue,
278 uint64_t inCompareValue,
279 uint64_t inExchangeValue)
280{
281 return static_cast<uint64_t>(_InterlockedCompareExchange64((volatile __int64*)&ioValue, (__int64)inExchangeValue, (__int64)inCompareValue)) == inCompareValue;
282}
283
284// End Visual C
285
286
287
288
289
290#else // Not Visual C or GCC/LLVM
291#error Provide an atomic operation implementation for this compiler
292#endif // Compiler version check
293
294#endif // #ifndef AAX_ATOMIC_H_
Various utility definitions for AAX.
#define AAX_CALLBACK
Definition: AAX.h:295
uint64_t AAX_CALLBACK AAX_Atomic_Exchange_64(volatile uint64_t &ioValue, uint64_t inExchangeValue)
Return the original value of ioValue and then set it to inExchangeValue.
uint32_t AAX_CALLBACK AAX_Atomic_Exchange_32(volatile uint32_t &ioValue, uint32_t inExchangeValue)
Return the original value of ioValue and then set it to inExchangeValue.
uint32_t AAX_CALLBACK AAX_Atomic_IncThenGet_32(uint32_t &ioData)
Increments a 32-bit value and returns the result.
bool AAX_CALLBACK AAX_Atomic_CompareAndExchange_32(volatile uint32_t &ioValue, uint32_t inCompareValue, uint32_t inExchangeValue)
Perform a compare and exchange operation on a 32-bit value.
bool AAX_CALLBACK AAX_Atomic_CompareAndExchange_Pointer(TPointer *&ioValue, TPointer *inCompareValue, TPointer *inExchangeValue)
Perform a compare and exchange operation on a pointer value.
Definition: AAX_Atomic.h:87
TPointer *AAX_CALLBACK AAX_Atomic_Load_Pointer(TPointer const *const volatile *inValue)
Atomically loads a pointer value.
uint32_t AAX_CALLBACK AAX_Atomic_DecThenGet_32(uint32_t &ioData)
Decrements a 32-bit value and returns the result.
TPointer *AAX_CALLBACK AAX_Atomic_Exchange_Pointer(TPointer *&ioValue, TPointer *inExchangeValue)
Perform an exchange operation on a pointer value.
Definition: AAX_Atomic.h:63
bool AAX_CALLBACK AAX_Atomic_CompareAndExchange_64(volatile uint64_t &ioValue, uint64_t inCompareValue, uint64_t inExchangeValue)
Perform a compare and exchange operation on a 64-bit value.