sipxportlib  Version 3.3
OsAtomicsAndroid.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2010-2013 SIPez LLC. All rights reserved.
3 //
4 // $$
6 
7 // Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>
8 
9 #ifndef _OsAtomicsAndroid_H_ // [
10 #define _OsAtomicsAndroid_H_
11 
12 #include <cutils/atomic.h>
13 #include <assert.h>
14 
15 #define USE_GCC_ATOMICS_ON_ANDROID
16 
17 #ifdef __x86_64__ // [
18 # error 64-bit Android systems are not supported yet.
19 #endif // __x86_64__ ]
20 
21 typedef enum memory_order {
24 } memory_order;
25 
26 template<class T>
28 {
29 public:
30  bool is_lock_free() const
31  {return true;}
32 
34  {
35  if (order == memory_order_relaxed)
36  {
37  // AFAIK, on all architectures supported by Android write to
38  // an aligned memory location is atomic.
39  mVal = (int32_t)val;
40  }
41  else
42  {
43  // Atomic write with memory barrier.
44  // Assert that we are on aligned memory location, hense this is atomic anyway
45  //assert((((int)&mVal) & 0x3) == 0);
46  // Android 2.3 and above has android_atomic_write #defined as android_atomic_release_store
47  // Its not clear this is even needed. So comment it out for now
48 #ifdef USE_GCC_ATOMICS_ON_ANDROID
49  __sync_lock_test_and_set(&mVal, (int32_t)val);
50 #else
51  android_atomic_write((int32_t)val, &mVal);
52 #endif
53  //mVal = (int32_t)val;
54  }
55  }
56 
58  {
59  // BUG: We should add memory barrier here if memory order is not "relaxed".
60  return (T)mVal;
61  }
62 
63  operator T() const
64  {return load();}
65 
67  {
68  return (T)android_atomic_swap((int32_t)val, &mVal);
69  }
70 
71 // bool compare_exchange(T &, T , memory_order, memory_order);
72 
73  bool compare_exchange(T &expected, T desired, memory_order = memory_order_seq_cst)
74  {
75  if (android_atomic_cmpxchg((int32_t)expected, (int32_t)desired, &mVal) > 0)
76  {
77  expected = (T)mVal;
78  return false;
79  }
80  return true;
81  }
82 
83  void fence(memory_order) const
84  { /* BUG: memory barrier is not implemented */ };
85 
87  {return (T)android_atomic_add((int32_t)val, &mVal);}
88 
90  {return (T)android_atomic_add(-(int32_t)val, &mVal);}
91 
93  {return (T)android_atomic_and((int32_t)val, &mVal);}
94 
96  {return (T)android_atomic_or((int32_t)val, &mVal);}
97 
98 // T fetch_xor(T val, memory_order = memory_order_seq_cst);
99 
100  explicit OsAtomic32<T>(T val = 0) : mVal((int32_t)val) {};
101 
102  T operator=(T val)
103  {store(val); return val;}
104 
105  T operator++(int)
106  {
107 #ifdef USE_GCC_ATOMICS_ON_ANDROID
108  return (T)__sync_fetch_and_add(&mVal, 1)+1;
109 #else
110  return (T)android_atomic_inc(&mVal)+1;
111 #endif
112  }
113 
114  T operator--(int)
115  {
116 #ifdef USE_GCC_ATOMICS_ON_ANDROID
117  return((T)__sync_fetch_and_sub(&mVal, 1)-1);
118 #else
119  return((T)android_atomic_dec(&mVal)-1);
120 #endif
121  }
122 
124  {
125 #ifdef USE_GCC_ATOMICS_ON_ANDROID
126  return((T)__sync_add_and_fetch(&mVal, 1));
127 #else
128  return((T)android_atomic_inc(&mVal));
129 #endif
130  }
131 
133  {
134 #ifdef USE_GCC_ATOMICS_ON_ANDROID
135  return((T)__sync_sub_and_fetch(&mVal, 1));
136 #else
137  return((T)android_atomic_dec(&mVal));
138 #endif
139  }
140 
141  T operator+=(T val)
142  {return fetch_add(val)+val;}
143 
144  T operator-=(T val)
145  {return fetch_sub(val)-val;}
146 
147  T operator&=(T val)
148  {return fetch_and(val)&val;}
149 
150  T operator|=(T val)
151  {return fetch_or(val)|val;}
152 
153 // T operator^=(T val);
154 
155 protected:
156  volatile int32_t mVal;
157 
158  // Prohibit use of copy constructor and operator=
161 };
162 
167 
168 class OsAtomicVoidPtr : protected OsAtomic32<void*>
169 {
170 public:
171  bool is_lock_free() const
173 
174  void store(void* val, memory_order order = memory_order_seq_cst)
175  {OsAtomic32<void*>::store(val, order);}
176 
178  {return OsAtomic32<void*>::load(order);}
179 
180  operator void*() const
181  {return load();}
182 
183  void* exchange(void* val, memory_order order = memory_order_seq_cst)
184  {return OsAtomic32<void*>::exchange(val, order);}
185 
186 // bool compare_exchange(void* &, void* , memory_order, memory_order);
187 
188  bool compare_exchange(void* &expected, void* desired, memory_order order = memory_order_seq_cst)
189  {return OsAtomic32<void*>::compare_exchange(expected, desired, order);}
190 
191  void fence(memory_order order) const
192  {OsAtomic32<void*>::fence(order);}
193 
194  void* fetch_add(ptrdiff_t val, memory_order order = memory_order_seq_cst)
195  {return (void*)android_atomic_add((int32_t)val, &mVal);}
196 
197  void* fetch_sub(ptrdiff_t val, memory_order order = memory_order_seq_cst)
198  {return (void*)android_atomic_add(-(int32_t)val, &mVal);}
199 
200 // OsAtomicVoidPtr() : mMutex(0) {};
201 
202  explicit OsAtomicVoidPtr(void* val = NULL) : OsAtomic32<void*>(val) {};
203 
204  void* operator=(void* val)
205  {return OsAtomic32<void*>::operator=(val);}
206 
207  void* operator+=(ptrdiff_t val)
208  {return (char*)fetch_add(val)+val;}
209 
210  void* operator-=(ptrdiff_t val)
211  {return (char*)fetch_sub(val)-val;}
212 
213 private:
214 
215  // Prohibit use of copy constructor and operator=
218 };
219 
220 template<class T>
221 class OsAtomicPtr : protected OsAtomicVoidPtr
222 {
223 public:
224  bool is_lock_free() const
226 
228  {OsAtomicVoidPtr::store((void*)val, mo);}
229 
231  {return (T*)OsAtomicVoidPtr::load(mo);}
232 
233  operator T*() const
234  {return (T*)OsAtomicVoidPtr::operator void*();}
235 
237  {return (T*)OsAtomicVoidPtr::exchange((void*)val, mo);}
238 
239 // bool compare_exchange(T* &, T* , memory_order mo, memory_order mo);
240 
241  bool compare_exchange(T* &expected, T* desired, memory_order mo = memory_order_seq_cst)
242  {return (T*)OsAtomicVoidPtr::compare_exchange((void*&)expected, (void*)desired, mo);}
243 
244  void fence(memory_order mo) const
246 
248  {return (T*)OsAtomicVoidPtr::fetch_add(val, mo);}
249 
251  {return (T*)OsAtomicVoidPtr::fetch_sub(val, mo);}
252 
253 // OsAtomicPtr() {};
254 
255  explicit OsAtomicPtr(T* val = NULL) : OsAtomicVoidPtr((void*)val) {};
256 
257  T* operator=(T* val)
258  {return (T*)OsAtomicVoidPtr::operator=((void*)val);}
259 
260  T* operator+=(ptrdiff_t val)
261  {return (T*)OsAtomicVoidPtr::operator+=(val);}
262 
263  T* operator-=(ptrdiff_t val)
264  {return (T*)OsAtomicVoidPtr::operator-=(val);}
265 
266 private:
267  // Prohibit use of copy constructor and operator=
268  OsAtomicPtr(const OsAtomicPtr&);
270 };
271 
272 #define OsAtomicLight OsAtomic32
273 #define OsAtomicLightPtr OsAtomicPtr
274 
275 typedef OsAtomicLight<int> OsAtomicLightInt;
276 typedef OsAtomicLight<unsigned int> OsAtomicLightUInt;
277 typedef OsAtomicLight<long> OsAtomicLightLong;
278 typedef OsAtomicLight<unsigned long> OsAtomicLightULong;
279 typedef OsAtomicLight<bool> OsAtomicLightBool;
280 
281 #endif // _OsAtomicsAndroid_H_ ]
void store(void *val,::memory_order=::memory_order_seq_cst)
Definition: OsAtomics.h:175
void * load(memory_order order=memory_order_seq_cst) const
Definition: OsAtomicsAndroid.h:177
T exchange(T val, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:66
Definition: OsAtomicsAndroid.h:22
void * load(::memory_order=::memory_order_seq_cst) const
Definition: OsAtomics.h:178
OsAtomicPtr(T *val=NULL)
Definition: OsAtomicsAndroid.h:255
T operator=(T val)
Definition: OsAtomicsAndroid.h:102
T operator-=(T val)
Definition: OsAtomicsAndroid.h:144
void * exchange(void *val, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:183
void store(void *val, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:174
void * fetch_sub(ptrdiff_t val, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:197
T * fetch_sub(ptrdiff_t val, memory_order mo=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:250
T * operator-=(ptrdiff_t val)
Definition: OsAtomicsAndroid.h:263
T operator--()
Definition: OsAtomicsAndroid.h:132
void * operator=(void *val)
Definition: OsAtomicsAndroid.h:204
memory_order
Definition: OsAtomics.h:41
OsAtomicLight< unsigned long > OsAtomicLightULong
Definition: OsAtomicsAndroid.h:278
OsAtomic32< unsigned long > OsAtomicULong
Definition: OsAtomicsAndroid.h:166
Definition: OsAtomics.h:169
#define NULL
Definition: UtlDefs.h:29
bool is_lock_free() const
Definition: OsAtomicsAndroid.h:171
Definition: OsAtomicsAndroid.h:23
void * fetch_sub(ptrdiff_t val,::memory_order=::memory_order_seq_cst)
Definition: OsAtomics.h:194
bool compare_exchange(void *&expected, void *desired, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:188
OsAtomicLight< long > OsAtomicLightLong
Definition: OsAtomicsAndroid.h:277
void * fetch_add(ptrdiff_t val,::memory_order=::memory_order_seq_cst)
Definition: OsAtomics.h:191
T fetch_or(T val, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:95
T operator++(int)
Definition: OsAtomicsAndroid.h:105
memory_order
Definition: OsAtomicsAndroid.h:21
OsAtomicVoidPtr(void *val=NULL)
Definition: OsAtomicsAndroid.h:202
T * fetch_add(ptrdiff_t val, memory_order mo=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:247
void * fetch_add(ptrdiff_t val, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:194
T operator--(int)
Definition: OsAtomicsAndroid.h:114
Definition: OsAtomicsAndroid.h:27
OsAtomicLight< int > OsAtomicLightInt
Definition: OsAtomicsAndroid.h:275
void * operator-=(ptrdiff_t val)
Definition: OsAtomicsAndroid.h:210
void fence(memory_order mo) const
Definition: OsAtomicsAndroid.h:244
Definition: OsAtomics.h:220
T operator++()
Definition: OsAtomicsAndroid.h:123
void fence(memory_order order) const
Definition: OsAtomicsAndroid.h:191
OsAtomic32< int > OsAtomicInt
Definition: OsAtomicsAndroid.h:163
OsAtomicLight< unsigned int > OsAtomicLightUInt
Definition: OsAtomicsAndroid.h:276
volatile int32_t mVal
Definition: OsAtomicsAndroid.h:156
T * operator=(T *val)
Definition: OsAtomicsAndroid.h:257
bool compare_exchange(T *&expected, T *desired, memory_order mo=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:241
T * load(memory_order mo=memory_order_seq_cst) const
Definition: OsAtomicsAndroid.h:230
bool is_lock_free() const
Definition: OsAtomicsAndroid.h:224
void store(T *val, memory_order mo=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:227
void fence(memory_order) const
Definition: OsAtomicsAndroid.h:83
void * operator+=(ptrdiff_t val)
Definition: OsAtomicsAndroid.h:207
void store(T val, memory_order order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:33
T * operator+=(ptrdiff_t val)
Definition: OsAtomicsAndroid.h:260
Definition: OsAtomicsAndroid.h:22
T operator+=(T val)
Definition: OsAtomicsAndroid.h:141
T operator|=(T val)
Definition: OsAtomicsAndroid.h:150
signed int int32_t
Definition: stdint.h:77
Definition: OsAtomicsAndroid.h:23
OsAtomic32< long > OsAtomicLong
Definition: OsAtomicsAndroid.h:165
Definition: OsAtomicsAndroid.h:23
bool compare_exchange(T &expected, T desired, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:73
T * exchange(T *val, memory_order mo=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:236
T load(memory_order=memory_order_seq_cst) const
Definition: OsAtomicsAndroid.h:57
T fetch_sub(T val, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:89
Definition: OsAtomicsAndroid.h:22
OsAtomic32< unsigned int > OsAtomicUInt
Definition: OsAtomicsAndroid.h:164
T fetch_add(T val, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:86
T operator&=(T val)
Definition: OsAtomicsAndroid.h:147
OsAtomicLight< bool > OsAtomicLightBool
Definition: OsAtomicsAndroid.h:279
bool is_lock_free() const
Definition: OsAtomicsAndroid.h:30
T fetch_and(T val, memory_order=memory_order_seq_cst)
Definition: OsAtomicsAndroid.h:92
void fence(::memory_order) const
Definition: OsAtomics.h:188