CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
OdInterlockedIncDec.h
Go to the documentation of this file.
1
2// Copyright (C) 2002-2022, Open Design Alliance (the "Alliance").
3// All rights reserved.
4//
5// This software and its documentation and related materials are owned by
6// the Alliance. The software may only be incorporated into application
7// programs owned by members of the Alliance, subject to a signed
8// Membership Agreement and Supplemental Software License Agreement with the
9// Alliance. The structure and organization of this software are the valuable
10// trade secrets of the Alliance and its suppliers. The software is also
11// protected by copyright law and international treaty provisions. Application
12// programs incorporating this software must include the following statement
13// with their copyright notices:
14//
15// This application incorporates Open Design Alliance software pursuant to a license
16// agreement with Open Design Alliance.
17// Open Design Alliance Copyright (C) 2002-2022 by Open Design Alliance.
18// All rights reserved.
19//
20// By use of this software, its documentation or related materials, you
21// acknowledge and accept the above terms.
23
24#ifndef _OD_INTERLOCKED_INCREMENT_H_
25#define _OD_INTERLOCKED_INCREMENT_H_
26
27#include <cstring>
28#ifdef OD_POSIX_THREADS
29#include <pthread.h>
30#endif
31#if defined(_MSC_VER)
32#include <winnt.h>
33#endif
34
35#ifndef TD_SINGLE_THREAD
36
37#ifndef __has_feature // https://stackoverflow.com/questions/7419167/determine-llvm-versus-gcc-at-compile-time?rq=1
38 #define __has_feature(x) 0 // Compatibility with non-clang compilers.
39#endif
40
41#if defined(_MSC_VER) && (_M_IX86) && (_M_IX86 >= 400) && !defined(_WIN32_WCE)
42// Intel486 platform with Microsoft compiler
43#pragma warning(push)
44#pragma warning(disable:4035)
45#pragma warning(disable:4793)
46inline int OdInterlockedIncrement(volatile int* dest)
47{
48 __asm
49 {
50 mov edx, dest
51 mov eax, 1
52 lock xadd[edx], eax
53 inc eax
54 }
55}
56inline int OdInterlockedDecrement(volatile int* dest)
57{
58 __asm
59 {
60 mov edx, dest
61 mov eax, -1
62 lock xadd[edx], eax
63 dec eax
64 }
65}
66
67#pragma warning(pop)
68#elif (defined(_WIN32) || defined(_WIN64)) && !defined(ODA_WINDOWS_GCC)
69// Windows platform with generic compiler - use interlocked functions from Win32 API
70#define OdInterlockedIncrement(dest) InterlockedIncrement((LONG*)(dest))
71#define OdInterlockedDecrement(dest) InterlockedDecrement((LONG*)(dest))
72#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(ANDROID)
73// Intel platform with GCC compiler
74inline int OdInterlockedExchangeAdd(volatile int* dest, int incr)
75{
76 int ret;
77 __asm__ __volatile__(
78 "lock; xaddl %0, (%1)"
79 : "=r" (ret)
80 : "r" (dest), "0" (incr)
81 : "memory");
82 return ret;
83}
84inline int OdInterlockedIncrement(volatile int* dest)
85{
86 return OdInterlockedExchangeAdd(dest, 1) + 1;
87}
88inline int OdInterlockedDecrement(volatile int* dest)
89{
90 return OdInterlockedExchangeAdd(dest, -1) - 1;
91}
92#elif defined(__GNUC__) && defined(__POWERPC__)
93// Macintosh PowerPC platform with GCC compiler
94inline int OdInterlockedExchangeAdd(volatile int* dest, int incr)
95{
96 // Assembler code is taken from Wine 0.9.4 sources
97 // See http://cvs.winehq.org/cvsweb/wine/libs/port/interlocked.c?rev=1.7&content-type=text/x-cvsweb-markup
98 int ret = 0;
99 int zero = 0;
100 __asm__ __volatile__(
101 "0: lwarx %0, %3, %1\n"
102 " add %0, %2, %0\n"
103 " stwcx. %0, %3, %1\n"
104 " bne- 0b\n"
105 " isync\n"
106 : "=&r" (ret)
107 : "r"(dest), "r"(incr), "r"(zero)
108 : "cr0", "memory", "r0");
109 return ret - incr;
110}
111
112inline int OdInterlockedIncrement(volatile int* dest)
113{
114 return OdInterlockedExchangeAdd(dest, 1) + 1;
115}
116inline int OdInterlockedDecrement(volatile int* dest)
117{
118 return OdInterlockedExchangeAdd(dest, -1) - 1;
119}
120#elif defined(__APPLE__)
121// iOS or Mac platform
122#include <libkern/OSAtomic.h>
123inline int OdInterlockedIncrement(volatile int* dest)
124{
125 return OSAtomicIncrement32Barrier(dest);
126}
127inline int OdInterlockedDecrement(volatile int* dest)
128{
129 return OSAtomicDecrement32Barrier(dest);
130}
131/*#elif defined(ANDROID) && !defined(ANDROID_GOOGLE)
132//TODO Android r10c NDK doesn't provide such functionality
133// Android platform with GCC or MinGW compiler
134#include <sys/atomics.h>
135inline int OdInterlockedIncrement(volatile int* dest)
136{
137 return __atomic_inc(dest) + 1;
138}
139inline int OdInterlockedDecrement(volatile int* dest)
140{
141 return __atomic_dec(dest) - 1;
142}
143#define OdInterlockedIncrement(dest) InterlockedIncrement((LONG*)(dest))
144#define OdInterlockedDecrement(dest) InterlockedDecrement((LONG*)(dest))*/
145#elif ( (defined(__GNUC__) && defined(__aarch64__)) || defined(__llvm__) || (defined(__clang__) && __has_feature(c_atomic)) ) && (__cplusplus >= 201103L)
146// this solution is portable GNU C++11, e.g. Linux ARM.
147// it uses atomic built-ins:
148// GCC: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
149// LLVM Clang: https://clang.llvm.org/docs/LanguageExtensions.html#langext-c11-atomic
150#include <atomic>
151inline int OdInterlockedIncrement(volatile int* dest)
152{
153 return __atomic_fetch_add(dest, 1, std::memory_order_relaxed) + 1;
154}
155inline int OdInterlockedDecrement(volatile int* dest)
156{
157 return __atomic_fetch_sub(dest, 1, std::memory_order_relaxed) - 1;
158}
159#else
160// here should go other platforms
161// synchronization is disabled if no atomic functions are defined
162#define TD_SINGLE_THREAD
163#endif //architecture
164#endif //TD_SINGLE_THREAD
165
166#endif //_OD_INTERLOCKED_INCREMENT_H_
dec
Definition: DimVarDefs.h:953