Bug 1769547 - Do not MOZ_CRASH() on missing process r=nika
[gecko.git] / mfbt / WasiAtomic.h
blob364b8bd616d64816bb3422dba30052fdb4054aba
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_WasiAtomic_h
8 #define mozilla_WasiAtomic_h
10 // Clang >= 14 supports <atomic> for wasm targets.
11 #if _LIBCPP_VERSION >= 14000
12 # include <atomic>
13 #else
15 # include <cstdint>
17 // WASI doesn't support <atomic> and we use it as single-threaded for now.
18 // This is a stub implementation of std atomics to build WASI port of SM.
20 namespace std {
21 enum memory_order {
22 relaxed,
23 consume, // load-consume
24 acquire, // load-acquire
25 release, // store-release
26 acq_rel, // store-release load-acquire
27 seq_cst // store-release load-acquire
30 inline constexpr auto memory_order_relaxed = memory_order::relaxed;
31 inline constexpr auto memory_order_consume = memory_order::consume;
32 inline constexpr auto memory_order_acquire = memory_order::acquire;
33 inline constexpr auto memory_order_release = memory_order::release;
34 inline constexpr auto memory_order_acq_rel = memory_order::acq_rel;
35 inline constexpr auto memory_order_seq_cst = memory_order::seq_cst;
37 template <class T>
38 struct atomic {
39 using value_type = T;
40 value_type value_;
42 atomic() noexcept = default;
43 constexpr atomic(T desired) noexcept : value_{desired} {}
45 atomic(const atomic&) = delete;
46 atomic& operator=(const atomic&) = delete;
47 atomic& operator=(const atomic&) volatile = delete;
48 ~atomic() noexcept = default;
50 T load(memory_order m = memory_order_seq_cst) const volatile noexcept {
51 return value_;
54 void store(T desired,
55 memory_order m = memory_order_seq_cst) volatile noexcept {
56 value_ = desired;
59 T operator=(T desired) volatile noexcept { return value_ = desired; }
61 T exchange(T desired,
62 memory_order m = memory_order_seq_cst) volatile noexcept {
63 T tmp = value_;
64 value_ = desired;
65 return tmp;
68 bool compare_exchange_weak(T& expected, T desired, memory_order,
69 memory_order) volatile noexcept {
70 expected = desired;
71 return true;
74 bool compare_exchange_weak(
75 T& expected, T desired,
76 memory_order m = memory_order_seq_cst) volatile noexcept {
77 expected = desired;
78 return true;
81 bool compare_exchange_strong(T& expected, T desired, memory_order,
82 memory_order) volatile noexcept {
83 expected = desired;
84 return true;
87 bool compare_exchange_strong(
88 T& expected, T desired,
89 memory_order m = memory_order_seq_cst) volatile noexcept {
90 expected = desired;
91 return true;
94 T fetch_add(T arg, memory_order m = memory_order_seq_cst) volatile noexcept {
95 T previous = value_;
96 value_ = value_ + arg;
97 return previous;
100 T fetch_sub(T arg, memory_order m = memory_order_seq_cst) volatile noexcept {
101 T previous = value_;
102 value_ = value_ - arg;
103 return previous;
106 T fetch_or(T arg, memory_order m = memory_order_seq_cst) volatile noexcept {
107 T previous = value_;
108 value_ = value_ | arg;
109 return previous;
112 T fetch_xor(T arg, memory_order m = memory_order_seq_cst) volatile noexcept {
113 T previous = value_;
114 value_ = value_ ^ arg;
115 return previous;
118 T fetch_and(T arg, memory_order m = memory_order_seq_cst) volatile noexcept {
119 T previous = value_;
120 value_ = value_ & arg;
121 return previous;
125 template <class T>
126 struct atomic<T*> {
127 using value_type = T*;
128 using difference_type = ptrdiff_t;
130 value_type value_;
132 atomic() noexcept = default;
133 constexpr atomic(T* desired) noexcept : value_{desired} {}
134 atomic(const atomic&) = delete;
135 atomic& operator=(const atomic&) = delete;
136 atomic& operator=(const atomic&) volatile = delete;
138 T* load(memory_order m = memory_order_seq_cst) const volatile noexcept {
139 return value_;
142 void store(T* desired,
143 memory_order m = memory_order_seq_cst) volatile noexcept {
144 value_ = desired;
147 T* operator=(T* other) volatile noexcept { return value_ = other; }
149 T* exchange(T* desired,
150 memory_order m = memory_order_seq_cst) volatile noexcept {
151 T* previous = value_;
152 value_ = desired;
153 return previous;
156 bool compare_exchange_weak(T*& expected, T* desired, memory_order s,
157 memory_order f) volatile noexcept {
158 expected = desired;
159 return true;
162 bool compare_exchange_weak(
163 T*& expected, T* desired,
164 memory_order m = memory_order_seq_cst) volatile noexcept {
165 expected = desired;
166 return true;
169 bool compare_exchange_strong(T*& expected, T* desired, memory_order s,
170 memory_order f) volatile noexcept {
171 expected = desired;
172 return true;
175 T* fetch_add(ptrdiff_t arg,
176 memory_order m = memory_order_seq_cst) volatile noexcept {
177 T* previous = value_;
178 value_ = value_ + arg;
179 return previous;
182 T* fetch_sub(ptrdiff_t arg,
183 memory_order m = memory_order_seq_cst) volatile noexcept {
184 T* previous = value_;
185 value_ = value_ - arg;
186 return previous;
190 using atomic_uint8_t = atomic<uint8_t>;
191 using atomic_uint16_t = atomic<uint16_t>;
192 using atomic_uint32_t = atomic<uint32_t>;
193 using atomic_uint64_t = atomic<uint64_t>;
195 } // namespace std
197 #endif
199 #endif // mozilla_WasiAtomic_h