AAX SDK 2.6.1
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 Avid Technology, Inc.
4 * All rights reserved.
5 *
6 * CONFIDENTIAL: this document contains confidential information of Avid. Do
7 * not disclose to any third party. Use of the information contained in this
8 * document is subject to an Avid SDK license.
9 *
10 */
11
17/*================================================================================================*/
18
19
20#pragma once
21
22#ifndef AAX_ATOMIC_H_
23#define AAX_ATOMIC_H_
24
25#include "AAX.h"
26#include <stdint.h>
27
28#if (!defined AAX_PointerSize)
29#error Undefined pointer size
30#endif
31
32
34uint32_t AAX_CALLBACK AAX_Atomic_IncThenGet_32(uint32_t & ioData);
35
37uint32_t AAX_CALLBACK AAX_Atomic_DecThenGet_32(uint32_t & ioData);
38
41 volatile uint32_t& ioValue,
42 uint32_t inExchangeValue);
43
46 volatile uint64_t& ioValue,
47 uint64_t inExchangeValue);
48
50template<typename TPointer> TPointer* AAX_CALLBACK AAX_Atomic_Exchange_Pointer(TPointer*& ioValue, TPointer* inExchangeValue)
51{
52#if (AAX_PointerSize == AAXPointer_64bit)
53 return (TPointer*)AAX_Atomic_Exchange_64(*(uint64_t*)(void*)&ioValue, (uint64_t)inExchangeValue);
54#elif (AAX_PointerSize == AAXPointer_32bit)
55 return (TPointer*)AAX_Atomic_Exchange_32(*(uint32_t*)(void*)&ioValue, (uint32_t)inExchangeValue);
56#else
57#error Unsupported pointer size
58#endif
59}
60
63 volatile uint32_t & ioValue,
64 uint32_t inCompareValue,
65 uint32_t inExchangeValue);
66
69 volatile uint64_t& ioValue,
70 uint64_t inCompareValue,
71 uint64_t inExchangeValue);
72
74template<typename TPointer> bool AAX_CALLBACK AAX_Atomic_CompareAndExchange_Pointer(TPointer*& ioValue, TPointer* inCompareValue, TPointer* inExchangeValue)
75{
76#if (AAX_PointerSize == AAXPointer_64bit)
77 return AAX_Atomic_CompareAndExchange_64(*(uint64_t*)(void*)&ioValue, (uint64_t)inCompareValue, (uint64_t)inExchangeValue);
78#elif (AAX_PointerSize == AAXPointer_32bit)
79 return AAX_Atomic_CompareAndExchange_32(*(uint32_t*)(void*)&ioValue, (uint32_t)inCompareValue, (uint32_t)inExchangeValue);
80#else
81#error Unsupported pointer size
82#endif
83}
84
86template<typename TPointer> TPointer* AAX_CALLBACK AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue);
87
88
89
90//TODO: Update all atomic function implementatons with proper acquire/release semantics
91
92
93// GCC/LLVM
94#if defined(__GNUC__)
95
96// These intrinsics require GCC 4.2 or later
97#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
98
99inline uint32_t AAX_CALLBACK
100AAX_Atomic_IncThenGet_32(uint32_t& ioData)
101{
102 return __sync_add_and_fetch(&ioData, 1);
103}
104
105inline uint32_t AAX_CALLBACK
106AAX_Atomic_DecThenGet_32(uint32_t& ioData)
107{
108 return __sync_sub_and_fetch(&ioData, 1);
109}
110
111inline uint32_t
113 volatile uint32_t& ioValue,
114 uint32_t inExchangeValue)
115{
116 return __sync_lock_test_and_set(&ioValue, inExchangeValue);
117}
118
119inline uint64_t
121 volatile uint64_t& ioValue,
122 uint64_t inExchangeValue)
123{
124 return __sync_lock_test_and_set(&ioValue, inExchangeValue);
125}
126
127inline bool
129 volatile uint32_t & ioValue,
130 uint32_t inCompareValue,
131 uint32_t inExchangeValue)
132{
133 return __sync_bool_compare_and_swap(&ioValue, inCompareValue, inExchangeValue);
134}
135
136inline bool
138 volatile uint64_t& ioValue,
139 uint64_t inCompareValue,
140 uint64_t inExchangeValue)
141{
142 return __sync_bool_compare_and_swap(&ioValue, inCompareValue, inExchangeValue);
143}
144
145//TODO: Add GCC version check and alternative implementations for GCC versions that do not support __atomic_load
146template<typename TPointer>
147inline TPointer*
148AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
149{
150 TPointer* value;
151 __atomic_load(const_cast<TPointer * volatile *>(inValue), &(value), __ATOMIC_ACQUIRE);
152 return value;
153}
154
155#else // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
156#error This file requires GCC 4.2 or later
157#endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
158// End GCC/LLVM
159
160
161
162
163
164// Visual C
165#elif defined(_MSC_VER)
166
167#ifndef __INTRIN_H_
168#include <intrin.h>
169#endif
170
171#pragma intrinsic( _InterlockedIncrement, \
172 _InterlockedDecrement, \
173 _InterlockedExchange, \
174 _InterlockedCompareExchange, \
175 _InterlockedCompareExchange64)
176
177inline uint32_t AAX_CALLBACK
178AAX_Atomic_IncThenGet_32(register uint32_t& ioData)
179{
180 return static_cast<uint32_t>(_InterlockedIncrement((volatile long*)&ioData));
181}
182
183inline uint32_t AAX_CALLBACK
184AAX_Atomic_DecThenGet_32(register uint32_t& ioData)
185{
186 return static_cast<uint32_t>(_InterlockedDecrement((volatile long*)&ioData));
187}
188
189inline uint32_t
191 volatile uint32_t& ioDestination,
192 uint32_t inExchangeValue)
193{
194 return static_cast<uint32_t>(_InterlockedExchange((volatile long*)&ioDestination, (long)inExchangeValue));
195}
196
197#if (AAX_PointerSize == AAXPointer_64bit)
198
199#pragma intrinsic( _InterlockedExchange64, \
200 _InterlockedOr64)
201
202inline uint64_t
204 volatile uint64_t& ioValue,
205 uint64_t inExchangeValue)
206{
207 return static_cast<uint64_t>(_InterlockedExchange64((volatile __int64*)&ioValue, (__int64)inExchangeValue));
208}
209
210template<typename TPointer>
211inline TPointer*
212AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
213{
214// Itanium supports acquire semantics
215#if (_M_IA64)
216 return reinterpret_cast<TPointer*>(_InterlockedOr64_acq(const_cast<__int64 volatile *>(reinterpret_cast<const __int64 volatile *>(inValue)), 0x0000000000000000));
217#else
218 return reinterpret_cast<TPointer*>(_InterlockedOr64(const_cast<__int64 volatile *>(reinterpret_cast<const __int64 volatile *>(inValue)), 0x0000000000000000));
219#endif
220}
221
222#elif (AAX_PointerSize == AAXPointer_32bit)
223
224#pragma intrinsic( _InterlockedOr )
225
226// _InterlockedExchange64 is not available on 32-bit Pentium in Visual C
227inline uint64_t
229 volatile uint64_t& ioValue,
230 uint64_t inExchangeValue)
231{
232 for(;;)
233 {
234 uint64_t result = ioValue;
235 if(AAX_Atomic_CompareAndExchange_64(ioValue, result, inExchangeValue))
236 {
237 return result;
238 }
239 }
240
241 return 0; // will never get here
242}
243
244template<typename TPointer>
245inline TPointer*
246AAX_Atomic_Load_Pointer(TPointer const * const volatile * inValue)
247{
248 return reinterpret_cast<TPointer*>(_InterlockedOr(const_cast<long volatile *>(reinterpret_cast<const long volatile *>(inValue)), 0x00000000));
249}
250
251#endif
252
253inline bool
255 uint32_t volatile & ioValue,
256 uint32_t inCompareValue,
257 uint32_t inExchangeValue)
258{
259 return static_cast<uint32_t>(_InterlockedCompareExchange((volatile long*)&ioValue, (long)inExchangeValue, (long)inCompareValue)) == inCompareValue;
260}
261
262inline bool
264 volatile uint64_t& ioValue,
265 uint64_t inCompareValue,
266 uint64_t inExchangeValue)
267{
268 return static_cast<uint64_t>(_InterlockedCompareExchange64((volatile __int64*)&ioValue, (__int64)inExchangeValue, (__int64)inCompareValue)) == inCompareValue;
269}
270
271// End Visual C
272
273
274
275
276
277#else // Not Visual C or GCC/LLVM
278#error Provide an atomic operation implementation for this compiler
279#endif // Compiler version check
280
281#endif // #ifndef AAX_ATOMIC_H_
Various utility definitions for AAX.
#define AAX_CALLBACK
Definition: AAX.h:282
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:74
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:50
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.