1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_PLATFORM_ATOMIC_H_
6#define RUNTIME_PLATFORM_ATOMIC_H_
7
8#include <atomic>
9
10namespace dart {
11
12// Like std::atomic, but operations default to relaxed ordering instead of
13// sequential consistency.
14template <typename T>
15class RelaxedAtomic {
16 public:
17 constexpr RelaxedAtomic() : value_() {}
18 constexpr RelaxedAtomic(T arg) : value_(arg) {} // NOLINT
19 RelaxedAtomic(const RelaxedAtomic& arg) : value_(arg) {} // NOLINT
20
21 T load(std::memory_order order = std::memory_order_relaxed) const {
22 return value_.load(order);
23 }
24 void store(T arg, std::memory_order order = std::memory_order_relaxed) {
25 value_.store(arg, order);
26 }
27
28 T fetch_add(T arg, std::memory_order order = std::memory_order_relaxed) {
29 return value_.fetch_add(arg, order);
30 }
31 T fetch_sub(T arg, std::memory_order order = std::memory_order_relaxed) {
32 return value_.fetch_sub(arg, order);
33 }
34 T fetch_or(T arg, std::memory_order order = std::memory_order_relaxed) {
35 return value_.fetch_or(arg, order);
36 }
37 T fetch_and(T arg, std::memory_order order = std::memory_order_relaxed) {
38 return value_.fetch_and(arg, order);
39 }
40
41 bool compare_exchange_weak(
42 T& expected, // NOLINT
43 T desired,
44 std::memory_order order = std::memory_order_relaxed) {
45 return value_.compare_exchange_weak(expected, desired, order, order);
46 }
47 bool compare_exchange_strong(
48 T& expected, // NOLINT
49 T desired,
50 std::memory_order order = std::memory_order_relaxed) {
51 return value_.compare_exchange_strong(expected, desired, order, order);
52 }
53
54 operator T() const { return load(); }
55 T operator=(T arg) {
56 store(arg);
57 return arg;
58 }
59 T operator=(const RelaxedAtomic& arg) {
60 T loaded_once = arg;
61 store(loaded_once);
62 return loaded_once;
63 }
64 T operator+=(T arg) { return fetch_add(arg) + arg; }
65 T operator-=(T arg) { return fetch_sub(arg) - arg; }
66
67 private:
68 std::atomic<T> value_;
69};
70
71// Like std::atomic, but operations default to acquire for load, release for
72// stores, and acquire-release for read-and-updates.
73template <typename T>
74class AcqRelAtomic {
75 public:
76 constexpr AcqRelAtomic() : value_() {}
77 constexpr AcqRelAtomic(T arg) : value_(arg) {} // NOLINT
78 AcqRelAtomic(const AcqRelAtomic& arg) = delete;
79
80 T load(std::memory_order order = std::memory_order_acquire) const {
81 return value_.load(order);
82 }
83 void store(T arg, std::memory_order order = std::memory_order_release) {
84 value_.store(arg, order);
85 }
86
87 T fetch_add(T arg, std::memory_order order = std::memory_order_acq_rel) {
88 return value_.fetch_add(arg, order);
89 }
90 T fetch_sub(T arg, std::memory_order order = std::memory_order_acq_rel) {
91 return value_.fetch_sub(arg, order);
92 }
93 T fetch_or(T arg, std::memory_order order = std::memory_order_acq_rel) {
94 return value_.fetch_or(arg, order);
95 }
96 T fetch_and(T arg, std::memory_order order = std::memory_order_acq_rel) {
97 return value_.fetch_and(arg, order);
98 }
99
100 bool compare_exchange_weak(
101 T& expected, // NOLINT
102 T desired,
103 std::memory_order order = std::memory_order_acq_rel) {
104 return value_.compare_exchange_weak(expected, desired, order, order);
105 }
106 bool compare_exchange_strong(
107 T& expected, // NOLINT
108 T desired,
109 std::memory_order order = std::memory_order_acq_rel) {
110 return value_.compare_exchange_strong(expected, desired, order, order);
111 }
112
113 // Require explicit loads and stores.
114 operator T() const = delete;
115 T operator=(T arg) = delete;
116 T operator=(const AcqRelAtomic& arg) = delete;
117 T operator+=(T arg) = delete;
118 T operator-=(T arg) = delete;
119
120 private:
121 std::atomic<T> value_;
122};
123
124} // namespace dart
125
126#endif // RUNTIME_PLATFORM_ATOMIC_H_
127