0023024: Update headers of OCCT files
[occt.git] / src / Standard / Standard_Atomic.hxx
1 // Created on: 2007-09-04
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2007-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 //! @file 
22 //! Implementation of some atomic operations (elementary operations 
23 //! with data that cannot be interrupted by parallel threads in the
24 //! multithread process) on various platforms
25 //!
26 //! By the moment, only operations necessary for reference counter 
27 //! in Standard_Transient objects are implemented.
28 //! 
29 //! This is preffered to use fixed size types "int32_t" / "int64_t" for
30 //! correct function declarations however we leave "int" assuming it is 32bits for now.
31
32 #ifndef _Standard_Atomic_HeaderFile
33 #define _Standard_Atomic_HeaderFile
34
35 #include <Standard_Macro.hxx>
36
37 #if (defined(_WIN32) || defined(__WIN32__))
38 extern "C" {
39   long _InterlockedIncrement(long volatile* lpAddend);
40   long _InterlockedDecrement(long volatile* lpAddend);
41 }
42 #endif
43
44 #if defined(_MSC_VER)
45   // force intrinsic instead of WinAPI calls
46   #pragma intrinsic (_InterlockedIncrement)
47   #pragma intrinsic (_InterlockedDecrement)
48 #endif
49
50 //! Increments atomically integer variable pointed by theValue
51 //! and returns resulting incremented value.
52 static int Standard_Atomic_Increment (volatile int* theValue)
53 {
54 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
55   // mordern g++ compiler (gcc4.4+)
56   // built-in functions available for appropriate CPUs (at least -march=i486 should be specified on x86 platform)
57   return __sync_add_and_fetch (theValue, 1);
58 #elif (defined(_WIN32) || defined(__WIN32__))
59   // WinAPI function or MSVC intrinsic
60   return _InterlockedIncrement(reinterpret_cast<long volatile*>(theValue));
61 #elif defined(LIN)
62   // use x86 / x86_64 inline assembly (compatibility with alien compilers / old GCC)
63   int anIncResult;
64   __asm__ __volatile__ (
65   #if defined(_OCC64)
66     "lock xaddl %%ebx, (%%rax) \n\t"
67     "incl %%ebx                \n\t"
68     : "=b" (anIncResult)
69     : "a" (theValue), "b" (1)
70     : "cc", "memory");
71   #else
72     "lock xaddl %%eax, (%%ecx) \n\t"
73     "incl %%eax                \n\t"
74     : "=a" (anIncResult)
75     : "c" (theValue), "a" (1)
76     : "memory");
77   #endif
78   return anIncResult;
79 #else
80   //#error "Atomic operation doesn't implemented for current platform!"
81   return ++(*theValue);
82 #endif
83 }
84
85 //! Decrements atomically integer variable pointed by theValue
86 //! and returns resulting decremented value.
87 static int Standard_Atomic_Decrement (volatile int* theValue)
88 {
89 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
90   // mordern g++ compiler (gcc4.4+)
91   // built-in functions available for appropriate CPUs (at least -march=i486 should be specified on x86 platform)
92   return __sync_sub_and_fetch (theValue, 1);
93 #elif (defined(_WIN32) || defined(__WIN32__))
94   // WinAPI function or MSVC intrinsic
95   return _InterlockedDecrement(reinterpret_cast<long volatile*>(theValue));
96 #elif defined(LIN)
97   // use x86 / x86_64 inline assembly (compatibility with alien compilers / old GCC)
98   int aDecResult;
99   __asm__ __volatile__ (
100   #if defined(_OCC64)
101     "lock xaddl %%ebx, (%%rax) \n\t"
102     "decl %%ebx                \n\t"
103     : "=b" (aDecResult)
104     : "a" (theValue), "b" (-1)
105     : "cc", "memory");
106   #else
107     "lock xaddl %%eax, (%%ecx) \n\t"
108     "decl %%eax                \n\t"
109     : "=a" (aDecResult)
110     : "c" (theValue), "a" (-1)
111     : "memory");
112   #endif
113   return aDecResult;
114 #else
115   //#error "Atomic operation doesn't implemented for current platform!"
116   return --(*theValue);
117 #endif
118 }
119
120 #endif //_Standard_Atomic_HeaderFile