blob: a4f9a4fe05b10b8f89c5322d0c4d87d8fd5574f4 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_ATOMICOPS_H_
12#define RTC_BASE_ATOMICOPS_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020014#if defined(WEBRTC_WIN)
15// Include winsock2.h before including <windows.h> to maintain consistency with
Niels Möllerb06b0a62018-05-25 10:05:34 +020016// win32.h. To include win32.h directly, it must be broken out into its own
17// build target.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020018#include <winsock2.h>
19#include <windows.h>
20#endif // defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020022namespace rtc {
23class 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) {
34 return *i;
35 }
36 static void ReleaseStore(volatile int* i, int value) {
37 *i = value;
38 }
39 static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
40 return ::InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(i),
41 new_value,
42 old_value);
43 }
44 // Pointer variants.
45 template <typename T>
46 static T* AcquireLoadPtr(T* volatile* ptr) {
47 return *ptr;
48 }
49 template <typename T>
50 static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
51 return static_cast<T*>(::InterlockedCompareExchangePointer(
52 reinterpret_cast<PVOID volatile*>(ptr), new_value, old_value));
53 }
54#else
55 static int Increment(volatile int* i) {
56 return __sync_add_and_fetch(i, 1);
57 }
58 static int Decrement(volatile int* i) {
59 return __sync_sub_and_fetch(i, 1);
60 }
61 static int AcquireLoad(volatile const int* i) {
62 return __atomic_load_n(i, __ATOMIC_ACQUIRE);
63 }
64 static void ReleaseStore(volatile int* i, int value) {
65 __atomic_store_n(i, value, __ATOMIC_RELEASE);
66 }
67 static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
68 return __sync_val_compare_and_swap(i, old_value, new_value);
69 }
70 // Pointer variants.
71 template <typename T>
72 static T* AcquireLoadPtr(T* volatile* ptr) {
73 return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
74 }
75 template <typename T>
76 static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
77 return __sync_val_compare_and_swap(ptr, old_value, new_value);
78 }
79#endif
80};
81
82
83
84}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000085
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020086#endif // RTC_BASE_ATOMICOPS_H_