Mobile API Reference  MicroStrategy 2019
AtomicLong.h
Go to the documentation of this file.
1 //==============================================================================================
2 // FILENAME : AtomicLong.h
3 // AUTHOR : Jing Ning
4 // CREATION : 9/26/01
5 // Copyright (C) MicroStrategy Incorporated 2001
6 //==============================================================================================
7 #ifndef MSynch_AtomicLong_h
8 #define MSynch_AtomicLong_h
9 
11 #include "Synch.h"
12 //#ifdef __hpux
13 //#define HPUX32
14 //#undef HPUX64
15 //#endif
16 
17 #ifdef _AIX
18 #include <sys/atomic_op.h>
19 #elif defined(sun) || defined(linux)
20 /*extern "C"
21 {
22  long MSynch_AtomicIncrement(long *lp);
23  long MSynch_AtomicDecrement(long *lp);
24  long MSynch_AtomicSet(long *lp, long newVal);
25  long MSynch_AtomicAdd(long *lp, long inValue);
26 }*/
27 #elif defined(__hpux)
28  // To compile ExecLibRubyBridge on HP-UX PA-RISC machine There is no such
29  // assembly defined functions. -- hzhang 12/22/2005
30  #if #cpu(parisc)
31 
32  #else
33  extern "C"
34  {
35  long MSynch_AtomicIncrement(long *lp);
36  long MSynch_AtomicDecrement(long *lp);
37  long MSynch_AtomicSet(long *lp, long newVal);
38  long MSynch_AtomicAdd(long *lp, long inValue);
39  }
40  #endif //__hpux
41 #elif defined(WIN32)
42  // do nothing
43 #else
45 #endif
46 
47 #ifdef __hpux
49 #endif
50 
51 namespace MSynch
52 {
53 // To compile ExecLibRubyBridge on HP-UX PA-RISC machine We have
54 // to distinguish between IA and PA machines. But Windows preprocessing
55 // do not accept #cpu(parisc) so we have to seperate tehm. -- hzhang 12/22/2005
56 #if defined(WIN32)
57  // do nothing
58 #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/)
59  // do nothing
60 #else
61  //class AtomicLongData;
62 #endif
63 
72  {
73  public:
74 
75 #if defined(WIN32)
76  AtomicLong(const Int32 inValue = 0){ mnAtomicLongData = 0;}
77  AtomicLong(const AtomicLong& irAtomicLong){ mnAtomicLongData = irAtomicLong.mnAtomicLongData;}
78 #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) // HP-UX only works on IA machine -hzhang
79  AtomicLong(const Int32 inValue = 0){ mnAtomicLongData = 0;}
80  AtomicLong(const AtomicLong& irAtomicLong){ mnAtomicLongData = irAtomicLong.mnAtomicLongData;}
81 #else
82  AtomicLong(const Int32 inValue = 0){ mAtomicLongData = 0;}
84  AtomicLong(const AtomicLong& irAtomicLong){ mAtomicLongData = irAtomicLong.mAtomicLongData;}
85 #endif
86  ~AtomicLong() throw(){}
87 
88  // pre-increment (++i)
89  // IMPORTANT: operator++ will return to you a copy (a long) of the incremented value
90  // this is thread safe, otherwise, you would increment the value, get pre-empted and then
91  // extract a value that has been modified by other thread
92  // you may not do ++(++i), it will not compile
93 // change to inline for unix platforms
94 #ifdef WIN32
95  Int32 operator++() throw();
96 #else
97  Int32 operator++() throw()
98  {
99  #ifdef _AIX
100  //AIX system call returns original value, need to fix that.
101  return ::fetch_and_addlp(&mnAtomicLongData, 1)+1;
102 
103  #elif defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) // HP-UX only works on IA machine -hzhang
104  //return MSynch_AtomicIncrement(&mnAtomicLongData);
105  return __sync_fetch_and_add(&mnAtomicLongData, 1)+1;
106  #else
107  return ++(mAtomicLongData);
108  #endif
109  }
110 #endif
111 
112  // Atomic addition of an increment value
113  // Return value is the initial value
114 // change to inline for unix platforms
115 #ifdef WIN32
116  Int32 operator+=(Int32 inValue) throw();
117 #else
118  Int32 operator+=(Int32 inValue) throw()
119  {
120  #ifdef _AIX
121  return ::fetch_and_addlp(&mnAtomicLongData, inValue);
122 
123  #elif defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) // HP-UX only works on IA machine -hzhang
124  return __sync_fetch_and_add(&mnAtomicLongData, inValue)+inValue;
125  #else
126  return (mAtomicLongData)++;
127  #endif
128  }
129 #endif
130 
131  // pre-decrement (--i)
132  // IMPORTANT: operator-- will return to you a copy (a long) of the decremented value
133  // this is thread safe, otherwise, you would decrement the value, get pre-empted and then
134  // extract a value that has been modified by other thread
135  // you may not do --(--i), it will not compile
136 // change to inline for unix platforms
137 #ifdef WIN32
138  Int32 operator--() throw();
139 #else
140  Int32 operator--() throw()
141  {
142  #ifdef _AIX
143  //AIX system call returns original value, need to fix that.
144  return ::fetch_and_addlp(&mnAtomicLongData, -1)-1;
145 
146  #elif defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) // HP-UX only works on IA machine -hzhang
147  //return MSynch_AtomicDecrement(&mnAtomicLongData);
148  return __sync_fetch_and_sub(&mnAtomicLongData, 1)-1;
149 
150  #else
151  return --(mAtomicLongData);
152  #endif
153  }
154 #endif
155 
156  operator Int32() const throw()
157  {
158  // To compile ExecLibRubyBridge on HP-UX PA-RISC machine We have
159  // to distinguish between IA and PA machines. But Windows preprocessing
160  // does not accept #cpu(parisc) so we have to seperate tehm. -- hzhang 12/22/2005
161  #if defined(WIN32) /* need read_lock it ? */
162  return mnAtomicLongData;
163  #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) /* need read_lock it ? */
164  return mnAtomicLongData;
165  #else
166  return mAtomicLongData;
167  #endif
168  }
169 
170  Int32 GetValue() const throw()
171  {
172  // To compile ExecLibRubyBridge on HP-UX PA-RISC machine We have
173  // to distinguish between IA and PA machines. But Windows preprocessing
174  // do not accept #cpu(parisc) so we have to seperate tehm. -- hzhang 12/22/2005
175  #if defined(WIN32) /* need read_lock it ? */
176  return mnAtomicLongData;
177  #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) /* need read_lock it ? */
178  return mnAtomicLongData;
179  #else
180  return mAtomicLongData;
181  #endif
182  }
183 
184 #if defined(WIN32)
185  void operator=(const Int32 inValue){mnAtomicLongData = 0;}
186  void operator=(const AtomicLong& irAtomicLong){ mnAtomicLongData = irAtomicLong.mnAtomicLongData;}
187 #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/)
188  void operator=(const Int32 inValue){mnAtomicLongData = 0;}
189  void operator=(const AtomicLong& irAtomicLong){ mnAtomicLongData = irAtomicLong.mnAtomicLongData;}
190 #else
191  // WARNING Assignment operator to atomic long is never thread-safe.
192  // It is meant only for (single-threaded) initialization.
193  // Caller of atomic long must ensure that this call is only used when that atomic
194  // long can only be accessed by a single thread.
195  void operator=(const Int32 inValue){mAtomicLongData = 0;}
196 
197  // WARNING Assignment operator to atomic long is never thread-safe.
198  // It is meant only for (single-threaded) initialization.
199  // Caller of atomic long must ensure that this call is only used when that atomic
200  // long can only be accessed by a single thread.
201  void operator=(const AtomicLong& irAtomicLong){ mAtomicLongData = irAtomicLong.mAtomicLongData;}
202  // Exchange sets the inValue as the value of the AtomicLong and returns
203  // the PREVIOUS value held by the AtomicLong.
204 #endif
206  {
207  #ifdef WIN32
208  return ::InterlockedExchange(&mnAtomicLongData,inValue);
209 
210  #elif defined(_AIX)
211  long retVal = mnAtomicLongData;
212  while(FALSE == ::compare_and_swaplp(&mnAtomicLongData, &retVal, inValue))
213  {
214  // do nothing because compare_and_swaplp
215  // will update retVal to the new value
216  }
217  return retVal;
218 
219  #elif defined(sun) || defined(linux) || (defined(__hpux)) /* && !#cpu(parisc))
220  HP-UX only wors on IA machine -hzhang */
221  //return MSynch_AtomicSet(&mnAtomicLongData,inValue);
222  return __sync_lock_test_and_set(&mnAtomicLongData,inValue);
223  #elif defined(_MAC)
224  _ASSERT(false);
225  return 0;
226  #else
227  {
229  long lPreviousValue = mAtomicLongData;
230  mAtomicLongData = inValue;
231  return lPreviousValue;
232  }
233  #endif
234  }
235 
236  private:
237 // To compile ExecLibRubyBridge on HP-UX PA-RISC machine We have
238 // to distinguish between IA and PA machines. But Windows preprocessing
239 // does not accept #cpu(parisc) so we have to seperate tehm. -- hzhang 12/22/2005
240 #if defined(WIN32)
241  long mnAtomicLongData;
242 #elif defined(_AIX) || defined(sun) || defined(linux) || (defined(__hpux) /*&& !#cpu(parisc)*/) // HP-UX only works on IA machine -hzhang
243  long mnAtomicLongData;
244 #elif defined(_MAC)
245  Int32 mAtomicLongData;
246 #else
247  Int32 mAtomicLongData;
248  mutable InprocessRecursiveMutex mMutex;
249 #endif
250  };
251 }
252 
253 #endif // MSynch_AtomicLong_h
void operator=(const AtomicLong &irAtomicLong)
Definition: AtomicLong.h:201
~AtomicLong()
Definition: AtomicLong.h:86
Int32 GetValue() const
Definition: AtomicLong.h:170
AtomicLong(const AtomicLong &irAtomicLong)
Definition: AtomicLong.h:84
#define _ASSERT(x)
Definition: Asserte.h:34
void operator=(const Int32 inValue)
Definition: AtomicLong.h:195
Definition: InprocessRecursiveMutex.h:25
Definition: ReferenceCountedImpl.h:18
Int32 Exchange(Int32 inValue)
Definition: AtomicLong.h:205
Definition: InprocessRecursiveMutex.h:31
#define Int32
Definition: BasicTypes.h:20
#define DLL_SYNCH_EXIM
Definition: Synch.h:17
Int32 operator++()
Definition: AtomicLong.h:97
Definition: AtomicLong.h:71
#define FALSE
Definition: PDCwtypes.h:54
Int32 operator--()
Definition: AtomicLong.h:140
Int32 operator+=(Int32 inValue)
Definition: AtomicLong.h:118