libcopp  1.1.0
atomic_int_type_msvc_impl.h
Go to the documentation of this file.
1 
16 #ifndef UTIL_LOCK_ATOMIC_INT_TYPE_MSVC_IMPL_H
17 #define UTIL_LOCK_ATOMIC_INT_TYPE_MSVC_IMPL_H
18 
19 #pragma once
20 
21 #include <Windows.h>
22 
23 namespace util {
24  namespace lock {
25 
26  enum memory_order {
33  };
34 
35  namespace detail {
36 
37  template<int INT_SIZE>
39 
40  template<>
41  struct atomic_msvc_oprs<1> {
42  typedef char opr_t;
43 
44  static opr_t exchange(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
45  return InterlockedExchange8(target, value);
46  }
47 
48  static opr_t cas(volatile opr_t * target, opr_t value, opr_t expected, ::util::lock::memory_order order) {
49  volatile short* star = reinterpret_cast<volatile short*>(target);
50  short real_expect = expected;
51  real_expect |= 0xFF00 & *star;
52 
53  switch (order) {
55  return static_cast<opr_t>(InterlockedCompareExchangeNoFence16(star, value, real_expect));
57  return static_cast<opr_t>(InterlockedCompareExchangeAcquire16(star, value, real_expect));
59  return static_cast<opr_t>(InterlockedCompareExchangeRelease16(star, value, real_expect));
60  default:
61  return static_cast<opr_t>(InterlockedCompareExchange16(star, value, real_expect));
62  }
63  }
64 
65  static opr_t inc(volatile opr_t * target, ::util::lock::memory_order order) {
66  return add(target, 1, order);
67  }
68 
69  static opr_t dec(volatile opr_t * target, ::util::lock::memory_order order) {
70  return sub(target, 1, order);
71  }
72 
73  static opr_t add(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
74  // no api just like InterlockedAdd16, use cas to simulate it
75  if (NULL == target || 0 == value) {
76  return 0;
77  }
78 
79  opr_t ret = *target;
80  while (true) {
81  if (ret == cas(target, ret + value, ret, order)) {
82  ret += value;
83  break;
84  }
85  ret = *target;
86  }
87 
88  return ret;
89  }
90 
91  static opr_t sub(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
92  // no api just like InterlockedAdd16, use cas to simulate it
93  if (NULL == target || 0 == value) {
94  return 0;
95  }
96 
97  opr_t ret = *target;
98  while (true) {
99  if (ret == cas(target, ret - value, ret, order)) {
100  ret -= value;
101  break;
102  }
103  ret = *target;
104  }
105 
106  return ret;
107  }
108 
109  static opr_t and(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
110  return InterlockedAnd8(target, value);
111  }
112 
113  static opr_t or(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
114  return InterlockedOr8(target, value);
115  }
116 
117  static opr_t xor(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
118  return InterlockedXor8(target, value);
119  }
120  };
121 
122  template<>
123  struct atomic_msvc_oprs<2> {
124  typedef SHORT opr_t;
125 
126  static opr_t exchange(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
127  return InterlockedExchange16(target, value);
128  }
129 
130  static opr_t cas(volatile opr_t * target, opr_t value, opr_t expected, ::util::lock::memory_order order) {
131  switch(order) {
133  return InterlockedCompareExchangeNoFence16(target, value, expected);
135  return InterlockedCompareExchangeAcquire16(target, value, expected);
137  return InterlockedCompareExchangeRelease16(target, value, expected);
138  default:
139  return InterlockedCompareExchange16(target, value, expected);
140  }
141  }
142 
143  static opr_t inc(volatile opr_t * target, ::util::lock::memory_order order) {
144  switch(order) {
146  return InterlockedIncrementNoFence16(target);
148  return InterlockedIncrementAcquire16(target);
150  return InterlockedIncrementRelease16(target);
151  default:
152  return InterlockedIncrement16(target);
153  }
154  }
155 
156  static opr_t dec(volatile opr_t * target, ::util::lock::memory_order order) {
157  switch(order) {
159  return InterlockedDecrementNoFence16(target);
161  return InterlockedDecrementAcquire16(target);
163  return InterlockedDecrementRelease16(target);
164  default:
165  return InterlockedDecrement16(target);
166  }
167  }
168 
169  static opr_t add(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
170  // no api just like InterlockedAdd16, use cas to simulate it
171  if (NULL == target || 0 == value) {
172  return 0;
173  }
174 
175  opr_t ret = *target;
176  while (true) {
177  if (ret == cas(target, ret + value, ret, order)) {
178  ret += value;
179  break;
180  }
181  ret = *target;
182  }
183 
184  return ret;
185  }
186 
187  static opr_t sub(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
188  // no api just like InterlockedAdd16, use cas to simulate it
189  if (NULL == target || 0 == value) {
190  return 0;
191  }
192 
193  opr_t ret = *target;
194  while (true) {
195  if (ret == cas(target, ret - value, ret, order)) {
196  ret -= value;
197  break;
198  }
199  ret = *target;
200  }
201 
202  return ret;
203  }
204 
205  static opr_t and(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
206  return InterlockedAnd16(target, value);
207  }
208 
209  static opr_t or(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
210  return InterlockedOr16(target, value);
211  }
212 
213  static opr_t xor(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
214  return InterlockedXor16(target, value);
215  }
216  };
217 
218  template<>
219  struct atomic_msvc_oprs<8> {
220  typedef LONGLONG opr_t;
221 
222  static opr_t exchange(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
223  switch(order) {
225  return InterlockedExchangeNoFence64(target, value);
227  return InterlockedExchangeAcquire64(target, value);
228  default:
229  return InterlockedExchange64(target, value);
230  }
231  }
232 
233  static opr_t cas(volatile opr_t * target, opr_t value, opr_t expected, ::util::lock::memory_order order) {
234  switch(order) {
236  return InterlockedCompareExchangeNoFence64(target, value, expected);
238  return InterlockedCompareExchangeAcquire64(target, value, expected);
240  return InterlockedCompareExchangeRelease64(target, value, expected);
241  default:
242  return InterlockedCompareExchange64(target, value, expected);
243  }
244  }
245 
246  static opr_t inc(volatile opr_t * target, ::util::lock::memory_order order) {
247  switch(order) {
249  return InterlockedIncrementNoFence64(target);
251  return InterlockedIncrementAcquire64(target);
253  return InterlockedIncrementRelease64(target);
254  default:
255  return InterlockedIncrement64(target);
256  }
257  }
258 
259  static opr_t dec(volatile opr_t * target, ::util::lock::memory_order order) {
260  switch(order) {
262  return InterlockedDecrementNoFence64(target);
264  return InterlockedDecrementAcquire64(target);
266  return InterlockedDecrementRelease64(target);
267  default:
268  return InterlockedDecrement64(target);
269  }
270  }
271 
272  static opr_t add(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
273  switch(order) {
275  return InterlockedAddNoFence64(target, value);
277  return InterlockedAddAcquire64(target, value);
279  return InterlockedAddRelease64(target, value);
280  default:
281  return InterlockedAdd64(target, value);
282  }
283  }
284 
285  static opr_t sub(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
286  switch(order) {
288  return InterlockedAddNoFence64(target, ~(value - 1));
290  return InterlockedAddAcquire64(target, ~(value - 1));
292  return InterlockedAddRelease64(target, ~(value - 1));
293  default:
294  return InterlockedAdd64(target, ~(value - 1));
295  }
296  }
297 
298  static opr_t and(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
299  switch(order) {
301  return InterlockedAnd64NoFence(target, value);
303  return InterlockedAnd64Acquire(target, value);
305  return InterlockedAnd64Release(target, value);
306  default:
307  return InterlockedAnd64(target, value);
308  }
309  }
310 
311  static opr_t or(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
312  switch(order) {
314  return InterlockedOr64NoFence(target, value);
316  return InterlockedOr64Acquire(target, value);
318  return InterlockedOr64Release(target, value);
319  default:
320  return InterlockedOr64(target, value);
321  }
322  }
323 
324  static opr_t xor(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
325  switch(order) {
327  return InterlockedXor64NoFence(target, value);
329  return InterlockedXor64Acquire(target, value);
331  return InterlockedXor64Release(target, value);
332  default:
333  return InterlockedXor64(target, value);
334  }
335  }
336  };
337 
338  template<int INT_SIZE>
339  struct atomic_msvc_oprs {
340  typedef LONG opr_t;
341 
342  static opr_t exchange(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
343  switch(order) {
345  return InterlockedExchangeNoFence(target, value);
347  return InterlockedExchangeAcquire(target, value);
348  default:
349  return InterlockedExchange(target, value);
350  }
351  }
352 
353  static opr_t cas(volatile opr_t * target, opr_t value, opr_t expected, ::util::lock::memory_order order) {
354  switch(order) {
356  return InterlockedCompareExchangeNoFence(target, value, expected);
358  return InterlockedCompareExchangeAcquire(target, value, expected);
360  return InterlockedCompareExchangeRelease(target, value, expected);
361  default:
362  return InterlockedCompareExchange(target, value, expected);
363  }
364  }
365 
366  static opr_t inc(volatile opr_t * target, ::util::lock::memory_order order) {
367  switch(order) {
369  return InterlockedIncrementNoFence(target);
371  return InterlockedIncrementAcquire(target);
373  return InterlockedIncrementRelease(target);
374  default:
375  return InterlockedIncrement(target);
376  }
377  }
378 
379  static opr_t dec(volatile opr_t * target, ::util::lock::memory_order order) {
380  switch(order) {
382  return InterlockedDecrementNoFence(target);
384  return InterlockedDecrementAcquire(target);
386  return InterlockedDecrementRelease(target);
387  default:
388  return InterlockedDecrement(target);
389  }
390  }
391 
392  static opr_t add(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
393  switch(order) {
395  return InterlockedAddNoFence(target, value);
397  return InterlockedAddAcquire(target, value);
399  return InterlockedAddRelease(target, value);
400  default:
401  return InterlockedAdd(target, value);
402  }
403  }
404 
405  static opr_t sub(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
406  switch(order) {
408  return InterlockedAddNoFence(target, ~(value - 1));
410  return InterlockedAddAcquire(target, ~(value - 1));
412  return InterlockedAddRelease(target, ~(value - 1));
413  default:
414  return InterlockedAdd(target, ~(value - 1));
415  }
416  }
417 
418  static opr_t and(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
419  switch(order) {
421  return InterlockedAndNoFence(target, value);
423  return InterlockedAndAcquire(target, value);
425  return InterlockedAndRelease(target, value);
426  default:
427  return InterlockedAnd(target, value);
428  }
429  }
430 
431  static opr_t or(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
432  switch(order) {
434  return InterlockedOrNoFence(target, value);
436  return InterlockedOrAcquire(target, value);
438  return InterlockedOrRelease(target, value);
439  default:
440  return InterlockedOr(target, value);
441  }
442  }
443 
444  static opr_t xor(volatile opr_t * target, opr_t value, ::util::lock::memory_order order) {
445  switch(order) {
447  return InterlockedXorNoFence(target, value);
449  return InterlockedXorAcquire(target, value);
451  return InterlockedXorRelease(target, value);
452  default:
453  return InterlockedXor(target, value);
454  }
455  }
456  };
457  }
458  }
459 }
460 
461 #endif /* _UTIL_LOCK_ATOMIC_INT_TYPE_MSVC_IMPL_H_ */
static opr_t sub(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t and(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t exchange(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t xor(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t add(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t sub(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t sub(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t or(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t sub(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t exchange(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t inc(volatile opr_t *target,::util::lock::memory_order order)
static opr_t exchange(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t dec(volatile opr_t *target,::util::lock::memory_order order)
static opr_t add(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t inc(volatile opr_t *target,::util::lock::memory_order order)
static opr_t and(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t inc(volatile opr_t *target,::util::lock::memory_order order)
static opr_t add(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t cas(volatile opr_t *target, opr_t value, opr_t expected,::util::lock::memory_order order)
static opr_t dec(volatile opr_t *target,::util::lock::memory_order order)
static opr_t cas(volatile opr_t *target, opr_t value, opr_t expected,::util::lock::memory_order order)
static opr_t add(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t cas(volatile opr_t *target, opr_t value, opr_t expected,::util::lock::memory_order order)
static opr_t and(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t dec(volatile opr_t *target,::util::lock::memory_order order)
static opr_t cas(volatile opr_t *target, opr_t value, opr_t expected,::util::lock::memory_order order)
static opr_t or(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t or(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t xor(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t inc(volatile opr_t *target,::util::lock::memory_order order)
static opr_t or(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t xor(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t and(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t exchange(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t xor(volatile opr_t *target, opr_t value,::util::lock::memory_order order)
static opr_t dec(volatile opr_t *target,::util::lock::memory_order order)