eathread_atomic.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. /////////////////////////////////////////////////////////////////////////////
  5. // eathread_atomic.h
  6. //
  7. // Defines functionality for thread-safe primitive operations.
  8. //
  9. // EAThread atomics do NOT imply the use of read/write barriers. This is
  10. // partly due to historical reasons and partly due to EAThread's internal
  11. // code being optimized for not using barriers.
  12. //
  13. // In future, we are considering migrating the atomics interface which
  14. // defaults atomics to use full read/write barriers while allowing users
  15. // to opt-out of full barrier usage. The new C++11 interface already provides
  16. // similar interfaces.
  17. //
  18. // http://en.cppreference.com/w/cpp/atomic/memory_order
  19. //
  20. // Created by Rob Parolin
  21. /////////////////////////////////////////////////////////////////////////////
  22. #ifndef EATHREAD_INTERNAL_EATHREAD_ATOMIC_H
  23. #define EATHREAD_INTERNAL_EATHREAD_ATOMIC_H
  24. #include <EABase/eabase.h>
  25. #include <eathread/internal/config.h>
  26. #include <eathread/internal/eathread_atomic_standalone.h>
  27. #include <atomic>
  28. #if defined(EA_PRAGMA_ONCE_SUPPORTED)
  29. #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
  30. #endif
  31. #define EA_THREAD_ATOMIC_IMPLEMENTED
  32. namespace EA
  33. {
  34. namespace Thread
  35. {
  36. /// class AtomicInt
  37. ///
  38. /// Implements thread-safe access to an integer and primary operations on that integer.
  39. /// AtomicIntegers are commonly used as lightweight flags and signals between threads
  40. /// or as the synchronization object for spinlocks. Those familiar with the Win32 API
  41. /// will find that AtomicInt32 is essentially a platform independent interface to
  42. /// the Win32 InterlockedXXX family of functions. Those familiar with Linux may
  43. /// find that AtomicInt32 is essentially a platform independent interface to atomic_t
  44. /// functionality.
  45. ///
  46. /// Note that the reference implementation defined here is itself not thread-safe.
  47. /// A thread-safe version requires platform-specific code.
  48. ///
  49. /// Example usage
  50. /// AtomicInt32 i = 0;
  51. ///
  52. /// ++i;
  53. /// i--;
  54. /// i += 7;
  55. /// i -= 3;
  56. /// i = 2;
  57. ///
  58. /// int x = i.GetValue();
  59. /// i.Increment();
  60. /// bool oldValueWas6 = i.SetValueConditional(3, 6);
  61. /// i.Add(4);
  62. ///
  63. template <class T>
  64. class AtomicInt
  65. {
  66. public:
  67. typedef AtomicInt<T> ThisType;
  68. typedef T ValueType;
  69. /// AtomicInt
  70. /// Empty constructor. Intentionally leaves mValue in an unspecified state.
  71. /// This is done so that an AtomicInt acts like a standard built-in integer.
  72. AtomicInt()
  73. {}
  74. AtomicInt(ValueType n)
  75. { SetValue(n); }
  76. AtomicInt(const ThisType& x)
  77. { SetValue(x.GetValue()); }
  78. AtomicInt& operator=(const ThisType& x)
  79. { SetValue(x.GetValue()); return *this; }
  80. ValueType GetValue() const
  81. { return mValue.load(); }
  82. ValueType GetValueRaw() const
  83. { return mValue; }
  84. ValueType SetValue(ValueType n)
  85. { return mValue.exchange(n); }
  86. bool SetValueConditional(ValueType n, ValueType condition)
  87. { return mValue.compare_exchange_strong(condition, n); }
  88. ValueType Increment()
  89. { return mValue.operator++(); }
  90. ValueType Decrement()
  91. { return mValue.operator--(); }
  92. ValueType Add(ValueType n)
  93. { return mValue.fetch_add(n) + n; }
  94. // operators
  95. inline operator const ValueType() const { return GetValue(); }
  96. inline ValueType operator =(ValueType n) { return mValue.operator=(n); }
  97. inline ValueType operator+=(ValueType n) { return mValue.operator+=(n); }
  98. inline ValueType operator-=(ValueType n) { return mValue.operator-=(n); }
  99. inline ValueType operator++() { return mValue.operator++(); }
  100. inline ValueType operator++(int) { return mValue.operator++(0); }
  101. inline ValueType operator--() { return mValue.operator--(); }
  102. inline ValueType operator--(int) { return mValue.operator--(0); }
  103. protected:
  104. std::atomic<ValueType> mValue;
  105. };
  106. } // namespace Thread
  107. } // namespace EA
  108. #endif // EATHREAD_INTERNAL_EATHREAD_ATOMIC_H