Embedded Template Library  1.0
atomic_std.h
1 /******************************************************************************
2 The MIT License(MIT)
3 
4 Embedded Template Library.
5 https://github.com/ETLCPP/etl
6 https://www.etlcpp.com
7 
8 Copyright(c) 2018 jwellbelove
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files(the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions :
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 ******************************************************************************/
28 
29 #ifndef ETL_ATOMIC_STD_INCLUDED
30 #define ETL_ATOMIC_STD_INCLUDED
31 
32 #include "../platform.h"
33 #include "../nullptr.h"
34 #include "../char_traits.h"
35 
36 #include <atomic>
37 #include <stdint.h>
38 
39 namespace etl
40 {
41  //***************************************************************************
42  // ETL Atomic type for compilers that support std::atomic.
43  // etl::atomic is a simple wrapper around std::atomic.
44  //***************************************************************************
45 
46  typedef std::memory_order memory_order;
47 
48  static const etl::memory_order memory_order_relaxed = std::memory_order_relaxed;
49  static const etl::memory_order memory_order_consume = std::memory_order_consume;
50  static const etl::memory_order memory_order_acquire = std::memory_order_acquire;
51  static const etl::memory_order memory_order_release = std::memory_order_release;
52  static const etl::memory_order memory_order_acq_rel = std::memory_order_acq_rel;
53  static const etl::memory_order memory_order_seq_cst = std::memory_order_seq_cst;
54 
55  template <typename T>
56  class atomic
57  {
58  public:
59 
60  atomic()
61  : value(0)
62  {
63  }
64 
65  atomic(T v)
66  : value(v)
67  {
68  }
69 
70  // Assignment
71  T operator =(T v)
72  {
73  return value = v;
74  }
75 
76  T operator =(T v) volatile
77  {
78  return value = v;
79  }
80 
81  // Pre-increment
82  T operator ++()
83  {
84  return ++value;
85  }
86 
87  T operator ++() volatile
88  {
89  return ++value;
90  }
91 
92  // Post-increment
93  T operator ++(int)
94  {
95  return value++;
96  }
97 
98  T operator ++(int) volatile
99  {
100  return value++;
101  }
102 
103  // Pre-decrement
104  T operator --()
105  {
106  return --value;
107  }
108 
109  T operator --() volatile
110  {
111  return --value;
112  }
113 
114  // Post-decrement
115  T operator --(int)
116  {
117  return value--;
118  }
119 
120  T operator --(int) volatile
121  {
122  return value--;
123  }
124 
125  // Add
126  T operator +=(T v)
127  {
128  return value += v;
129  }
130 
131  T operator +=(T v) volatile
132  {
133  return value += v;
134  }
135 
136  // Subtract
137  T operator -=(T v)
138  {
139  return value -= v;
140  }
141 
142  T operator -=(T v) volatile
143  {
144  return value -= v;
145  }
146 
147  // And
148  T operator &=(T v)
149  {
150  return value &= v;
151  }
152 
153  T operator &=(T v) volatile
154  {
155  return value &= v;
156  }
157 
158  // Or
159  T operator |=(T v)
160  {
161  return value |= v;
162  }
163 
164  T operator |=(T v) volatile
165  {
166  return value |= v;
167  }
168 
169  // Exclusive or
170  T operator ^=(T v)
171  {
172  return value ^= v;
173  }
174 
175  T operator ^=(T v) volatile
176  {
177  return value ^= v;
178  }
179 
180  // Conversion operator
181  operator T () const
182  {
183  return T(value);
184  }
185 
186  operator T() volatile const
187  {
188  return T(value);
189  }
190 
191  // Is lock free?
192  bool is_lock_free() const
193  {
194  return value.is_lock_free();
195  }
196 
197  bool is_lock_free() const volatile
198  {
199  return value.is_lock_free();
200  }
201 
202  // Store
203  void store(T v, etl::memory_order order = etl::memory_order_seq_cst)
204  {
205  value.store(v, order);
206  }
207 
208  void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
209  {
210  value.store(v, order);
211  }
212 
213  // Load
214  T load(etl::memory_order order = etl::memory_order_seq_cst) const
215  {
216  return value.load(order);
217  }
218 
219  T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile
220  {
221  return value.load(order);
222  }
223 
224  // Fetch add
225  T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst)
226  {
227  return value.fetch_add(v, order);
228  }
229 
230  T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
231  {
232  return value.fetch_add(v, order);
233  }
234 
235  // Fetch subtract
236  T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst)
237  {
238  return value.fetch_sub(v, order);
239  }
240 
241  T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
242  {
243  return value.fetch_sub(v, order);
244  }
245 
246  // Fetch or
247  T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst)
248  {
249  return value.fetch_or(v, order);
250  }
251 
252  T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
253  {
254  return value.fetch_or(v, order);
255  }
256 
257  // Fetch and
258  T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst)
259  {
260  return value.fetch_and(v, order);
261  }
262 
263  T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
264  {
265  return value.fetch_and(v, order);
266  }
267 
268  // Fetch exclusive or
269  T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst)
270  {
271  return value.fetch_xor(v, order);
272  }
273 
274  T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
275  {
276  return value.fetch_xor(v, order);
277  }
278 
279  // Exchange
280  T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst)
281  {
282  return value.exchange(v, order);
283  }
284 
285  T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile
286  {
287  return value.exchange(v, order);
288  }
289 
290  // Compare exchange weak
291  bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
292  {
293  return value.compare_exchange_weak(expected, desired, order);
294  }
295 
296  bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
297  {
298  return value.compare_exchange_weak(expected, desired, order);
299  }
300 
301  bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
302  {
303  return value.compare_exchange_weak(expected, desired, success, failure);
304  }
305 
306  bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
307  {
308  return value.compare_exchange_weak(expected, desired, success, failure);
309  }
310 
311  // Compare exchange strong
312  bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst)
313  {
314  return value.compare_exchange_strong(expected, desired, order);
315  }
316 
317  bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
318  {
319  return value.compare_exchange_strong(expected, desired, order);
320  }
321 
322  bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure)
323  {
324  return value.compare_exchange_strong(expected, desired, success, failure);
325  }
326 
327  bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile
328  {
329  return value.compare_exchange_strong(expected, desired, success, failure);
330  }
331 
332  private:
333 
334  atomic& operator =(const atomic&);
335  //atomic& operator =(const atomic&) volatile;
336 
337  std::atomic<T> value;
338  };
339 
340  template <typename T>
341  class atomic<T*>
342  {
343  public:
344 
345  atomic()
346  : value(ETL_NULLPTR)
347  {
348  }
349 
350  atomic(T* v)
351  : value(v)
352  {
353  }
354 
355  // Assignment
356  T* operator =(T* v)
357  {
358  return value = v;
359  }
360 
361  T* operator =(T* v) volatile
362  {
363  return value = v;
364  }
365 
366  // Pre-increment
367  T* operator ++()
368  {
369  return ++value;
370  }
371 
372  T* operator ++() volatile
373  {
374  return ++value;
375  }
376 
377  // Post-increment
378  T* operator ++(int)
379  {
380  return value++;
381  }
382 
383  T* operator ++(int) volatile
384  {
385  return value++;
386  }
387 
388  // Pre-decrement
389  T* operator --()
390  {
391  return --value;
392  }
393 
394  T* operator --() volatile
395  {
396  return --value;
397  }
398 
399  // Post-decrement
400  T* operator --(int)
401  {
402  return value--;
403  }
404 
405  T* operator --(int) volatile
406  {
407  return value--;
408  }
409 
410  // Add
411  T* operator +=(ptrdiff_t v)
412  {
413  return value += v;
414  }
415 
416  T* operator +=(ptrdiff_t v) volatile
417  {
418  return value += v;
419  }
420 
421  // Subtract
422  T* operator -=(ptrdiff_t v)
423  {
424  return value -= v;
425  }
426 
427  T* operator -=(ptrdiff_t v) volatile
428  {
429  return value -= v;
430  }
431 
432  // Conversion operator
433  operator T* () const
434  {
435  return (T*)value;
436  }
437 
438  operator T*() volatile const
439  {
440  return (T*)value;
441  }
442 
443  // Is lock free?
444  bool is_lock_free() const
445  {
446  return value.is_lock_free();
447  }
448 
449  bool is_lock_free() const volatile
450  {
451  return value.is_lock_free();
452  }
453 
454  // Store
455  void store(T* v, etl::memory_order order = etl::memory_order_seq_cst)
456  {
457  value.store(v, order);
458  }
459 
460  void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile
461  {
462  value.store(v, order);
463  }
464 
465  // Load
466  T* load(etl::memory_order order = etl::memory_order_seq_cst)
467  {
468  return value.load(order);
469  }
470 
471  T* load(etl::memory_order order = etl::memory_order_seq_cst) volatile
472  {
473  return value.load(order);
474  }
475 
476  // Fetch add
477  T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
478  {
479  return value.fetch_add(v, order);
480  }
481 
482  T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile
483  {
484  return value.fetch_add(v, order);
485  }
486 
487  // Fetch subtract
488  T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst)
489  {
490  return value.fetch_sub(v, order);
491  }
492 
493  T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile
494  {
495  return value.fetch_sub(v, order);
496  }
497 
498  // Exchange
499  T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst)
500  {
501  return value.exchange(v, order);
502  }
503 
504  T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile
505  {
506  return value.exchange(v, order);
507  }
508 
509  // Compare exchange weak
510  bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
511  {
512  return value.compare_exchange_weak(expected, desired, order);
513  }
514 
515  bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
516  {
517  return value.compare_exchange_weak(expected, desired, order);
518  }
519 
520  bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure)
521  {
522  return value.compare_exchange_weak(expected, desired, success, failure);
523  }
524 
525  bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile
526  {
527  return value.compare_exchange_weak(expected, desired, success, failure);
528  }
529 
530  // Compare exchange strong
531  bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst)
532  {
533  return value.compare_exchange_strong(expected, desired, order);
534  }
535 
536  bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile
537  {
538  return value.compare_exchange_strong(expected, desired, order);
539  }
540 
541  bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure)
542  {
543  return value.compare_exchange_strong(expected, desired, success, failure);
544  }
545 
546  bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile
547  {
548  return value.compare_exchange_strong(expected, desired, success, failure);
549  }
550 
551  private:
552 
553  atomic & operator =(const atomic&) ETL_DELETE;
554  atomic& operator =(const atomic&) volatile ETL_DELETE;
555 
556  std::atomic<T*> value;
557  };
558 
559  typedef std::atomic<bool> atomic_bool;
560  typedef std::atomic<char> atomic_char;
561  typedef std::atomic<signed char> atomic_schar;
562  typedef std::atomic<unsigned char> atomic_uchar;
563  typedef std::atomic<short> atomic_short;
564  typedef std::atomic<unsigned short> atomic_ushort;
565  typedef std::atomic<int> atomic_int;
566  typedef std::atomic<unsigned int> atomic_uint;
567  typedef std::atomic<long> atomic_long;
568  typedef std::atomic<unsigned long> atomic_ulong;
569  typedef std::atomic<long long> atomic_llong;
570  typedef std::atomic<unsigned long long> atomic_ullong;
571  typedef std::atomic<wchar_t> atomic_wchar_t;
572  typedef std::atomic<char16_t> atomic_char16_t;
573  typedef std::atomic<char32_t> atomic_char32_t;
574 #if ETL_USING_8BIT_TYPES
575  typedef std::atomic<uint8_t> atomic_uint8_t;
576  typedef std::atomic<int8_t> atomic_int8_t;
577 #endif
578  typedef std::atomic<uint16_t> atomic_uint16_t;
579  typedef std::atomic<int16_t> atomic_int16_t;
580  typedef std::atomic<uint32_t> atomic_uint32_t;
581  typedef std::atomic<int32_t> atomic_int32_t;
582 #if ETL_USING_64BIT_TYPES
583  typedef std::atomic<uint64_t> atomic_uint64_t;
584  typedef std::atomic<int64_t> atomic_int64_t;
585 #endif
586  typedef std::atomic<int_least8_t> atomic_int_least8_t;
587  typedef std::atomic<uint_least8_t> atomic_uint_least8_t;
588  typedef std::atomic<int_least16_t> atomic_int_least16_t;
589  typedef std::atomic<uint_least16_t> atomic_uint_least16_t;
590  typedef std::atomic<int_least32_t> atomic_int_least32_t;
591  typedef std::atomic<uint_least32_t> atomic_uint_least32_t;
592 #if ETL_USING_64BIT_TYPES
593  typedef std::atomic<int_least64_t> atomic_int_least64_t;
594  typedef std::atomic<uint_least64_t> atomic_uint_least64_t;
595 #endif
596  typedef std::atomic<int_fast8_t> atomic_int_fast8_t;
597  typedef std::atomic<uint_fast8_t> atomic_uint_fast8_t;
598  typedef std::atomic<int_fast16_t> atomic_int_fast16_t;
599  typedef std::atomic<uint_fast16_t> atomic_uint_fast16_t;
600  typedef std::atomic<int_fast32_t> atomic_int_fast32_t;
601  typedef std::atomic<uint_fast32_t> atomic_uint_fast32_t;
602 #if ETL_USING_64BIT_TYPES
603  typedef std::atomic<int_fast64_t> atomic_int_fast64_t;
604  typedef std::atomic<uint_fast64_t> atomic_uint_fast64_t;
605 #endif
606  typedef std::atomic<intptr_t> atomic_intptr_t;
607  typedef std::atomic<uintptr_t> atomic_uintptr_t;
608  typedef std::atomic<size_t> atomic_size_t;
609  typedef std::atomic<ptrdiff_t> atomic_ptrdiff_t;
610  typedef std::atomic<intmax_t> atomic_intmax_t;
611  typedef std::atomic<uintmax_t> atomic_uintmax_t;
612 }
613 
614 #endif
Definition: absolute.h:37
T exchange(T &object, const T &new_value)
exchange (const)
Definition: utility.h:301