atomic_ops.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Copyright 2011 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef RTC_BASE_ATOMIC_OPS_H_
  11. #define RTC_BASE_ATOMIC_OPS_H_
  12. #if defined(WEBRTC_WIN)
  13. // clang-format off
  14. // clang formating would change include order.
  15. // Include winsock2.h before including <windows.h> to maintain consistency with
  16. // win32.h. To include win32.h directly, it must be broken out into its own
  17. // build target.
  18. #include <winsock2.h>
  19. #include <windows.h>
  20. // clang-format on
  21. #endif // defined(WEBRTC_WIN)
  22. namespace rtc {
  23. class AtomicOps {
  24. public:
  25. #if defined(WEBRTC_WIN)
  26. // Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
  27. static int Increment(volatile int* i) {
  28. return ::InterlockedIncrement(reinterpret_cast<volatile LONG*>(i));
  29. }
  30. static int Decrement(volatile int* i) {
  31. return ::InterlockedDecrement(reinterpret_cast<volatile LONG*>(i));
  32. }
  33. static int AcquireLoad(volatile const int* i) { return *i; }
  34. static void ReleaseStore(volatile int* i, int value) { *i = value; }
  35. static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
  36. return ::InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(i),
  37. new_value, old_value);
  38. }
  39. // Pointer variants.
  40. template <typename T>
  41. static T* AcquireLoadPtr(T* volatile* ptr) {
  42. return *ptr;
  43. }
  44. template <typename T>
  45. static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
  46. return static_cast<T*>(::InterlockedCompareExchangePointer(
  47. reinterpret_cast<PVOID volatile*>(ptr), new_value, old_value));
  48. }
  49. #else
  50. static int Increment(volatile int* i) { return __sync_add_and_fetch(i, 1); }
  51. static int Decrement(volatile int* i) { return __sync_sub_and_fetch(i, 1); }
  52. static int AcquireLoad(volatile const int* i) {
  53. return __atomic_load_n(i, __ATOMIC_ACQUIRE);
  54. }
  55. static void ReleaseStore(volatile int* i, int value) {
  56. __atomic_store_n(i, value, __ATOMIC_RELEASE);
  57. }
  58. static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
  59. return __sync_val_compare_and_swap(i, old_value, new_value);
  60. }
  61. // Pointer variants.
  62. template <typename T>
  63. static T* AcquireLoadPtr(T* volatile* ptr) {
  64. return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
  65. }
  66. template <typename T>
  67. static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
  68. return __sync_val_compare_and_swap(ptr, old_value, new_value);
  69. }
  70. #endif
  71. };
  72. } // namespace rtc
  73. #endif // RTC_BASE_ATOMIC_OPS_H_