Skip to content

Commit 239c448

Browse files
feat: Refine memory order concurrency strategy and implement traits
1 parent c15becf commit 239c448

1 file changed

Lines changed: 188 additions & 5 deletions

File tree

src/policy/impl.cppm

Lines changed: 188 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
module;
2+
#include <atomic>
23
#include <concepts>
34
#include <exception>
45
#include <expected>
56
#include <stdexcept>
67
#include <string>
78
#include <type_traits>
89

9-
1010
export module mcpplibs.primitives.policy.impl;
1111

1212
import mcpplibs.primitives.operations.traits;
@@ -37,7 +37,10 @@ struct terminate {};
3737

3838
namespace concurrency {
3939
struct none {};
40-
struct atomic {};
40+
struct fenced {};
41+
struct fenced_relaxed {};
42+
struct fenced_acq_rel {};
43+
struct fenced_seq_cst {};
4144
} // namespace concurrency
4245

4346
template <> struct traits<value::checked> {
@@ -100,8 +103,26 @@ template <> struct traits<concurrency::none> {
100103
static constexpr auto kind = category::concurrency;
101104
};
102105

103-
template <> struct traits<concurrency::atomic> {
104-
using policy_type = concurrency::atomic;
106+
template <> struct traits<concurrency::fenced> {
107+
using policy_type = concurrency::fenced;
108+
static constexpr bool enabled = true;
109+
static constexpr auto kind = category::concurrency;
110+
};
111+
112+
template <> struct traits<concurrency::fenced_relaxed> {
113+
using policy_type = concurrency::fenced_relaxed;
114+
static constexpr bool enabled = true;
115+
static constexpr auto kind = category::concurrency;
116+
};
117+
118+
template <> struct traits<concurrency::fenced_acq_rel> {
119+
using policy_type = concurrency::fenced_acq_rel;
120+
static constexpr bool enabled = true;
121+
static constexpr auto kind = category::concurrency;
122+
};
123+
124+
template <> struct traits<concurrency::fenced_seq_cst> {
125+
using policy_type = concurrency::fenced_seq_cst;
105126
static constexpr bool enabled = true;
106127
static constexpr auto kind = category::concurrency;
107128
};
@@ -189,7 +210,7 @@ struct concurrency::handler<concurrency::none, OpTag, CommonRep, ErrorPayload> {
189210

190211
template <operations::operation OpTag, typename CommonRep,
191212
typename ErrorPayload>
192-
struct concurrency::handler<concurrency::atomic, OpTag, CommonRep,
213+
struct concurrency::handler<concurrency::fenced, OpTag, CommonRep,
193214
ErrorPayload> {
194215
static constexpr bool enabled = true;
195216
static constexpr bool requires_external_sync = true;
@@ -200,10 +221,172 @@ struct concurrency::handler<concurrency::atomic, OpTag, CommonRep,
200221
injection_type out{};
201222
out.fence_before = true;
202223
out.fence_after = true;
224+
out.order_before = std::memory_order_seq_cst;
225+
out.order_after = std::memory_order_seq_cst;
203226
return out;
204227
}
205228
};
206229

230+
template <operations::operation OpTag, typename CommonRep,
231+
typename ErrorPayload>
232+
struct concurrency::handler<concurrency::fenced_relaxed, OpTag, CommonRep,
233+
ErrorPayload> {
234+
static constexpr bool enabled = true;
235+
static constexpr bool requires_external_sync = true;
236+
using injection_type = concurrency::injection;
237+
using result_type = std::expected<CommonRep, ErrorPayload>;
238+
239+
static constexpr auto inject() noexcept -> injection_type {
240+
injection_type out{};
241+
out.fence_before = true;
242+
out.fence_after = true;
243+
out.order_before = std::memory_order_relaxed;
244+
out.order_after = std::memory_order_relaxed;
245+
return out;
246+
}
247+
};
248+
249+
template <operations::operation OpTag, typename CommonRep,
250+
typename ErrorPayload>
251+
struct concurrency::handler<concurrency::fenced_acq_rel, OpTag, CommonRep,
252+
ErrorPayload> {
253+
static constexpr bool enabled = true;
254+
static constexpr bool requires_external_sync = true;
255+
using injection_type = concurrency::injection;
256+
using result_type = std::expected<CommonRep, ErrorPayload>;
257+
258+
static constexpr auto inject() noexcept -> injection_type {
259+
injection_type out{};
260+
out.fence_before = true;
261+
out.fence_after = true;
262+
out.order_before = std::memory_order_acquire;
263+
out.order_after = std::memory_order_release;
264+
return out;
265+
}
266+
};
267+
268+
template <operations::operation OpTag, typename CommonRep,
269+
typename ErrorPayload>
270+
struct concurrency::handler<concurrency::fenced_seq_cst, OpTag, CommonRep,
271+
ErrorPayload> {
272+
static constexpr bool enabled = true;
273+
static constexpr bool requires_external_sync = true;
274+
using injection_type = concurrency::injection;
275+
using result_type = std::expected<CommonRep, ErrorPayload>;
276+
277+
static constexpr auto inject() noexcept -> injection_type {
278+
injection_type out{};
279+
out.fence_before = true;
280+
out.fence_after = true;
281+
out.order_before = std::memory_order_seq_cst;
282+
out.order_after = std::memory_order_seq_cst;
283+
return out;
284+
}
285+
};
286+
287+
template <typename CommonRep, typename ErrorPayload>
288+
struct concurrency::handler<concurrency::fenced, void, CommonRep,
289+
ErrorPayload> {
290+
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
291+
using injection_type = concurrency::injection;
292+
using result_type = std::expected<CommonRep, ErrorPayload>;
293+
294+
static auto load(CommonRep const &value) noexcept -> CommonRep {
295+
std::atomic_ref<CommonRep const> ref(value);
296+
return ref.load(std::memory_order_seq_cst);
297+
}
298+
299+
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
300+
std::atomic_ref<CommonRep> ref(value);
301+
ref.store(desired, std::memory_order_seq_cst);
302+
}
303+
304+
static auto compare_exchange(CommonRep &value, CommonRep &expected,
305+
CommonRep desired) noexcept -> bool {
306+
std::atomic_ref<CommonRep> ref(value);
307+
return ref.compare_exchange_strong(expected, desired,
308+
std::memory_order_seq_cst,
309+
std::memory_order_seq_cst);
310+
}
311+
};
312+
313+
template <typename CommonRep, typename ErrorPayload>
314+
struct concurrency::handler<concurrency::fenced_relaxed, void, CommonRep,
315+
ErrorPayload> {
316+
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
317+
using injection_type = concurrency::injection;
318+
using result_type = std::expected<CommonRep, ErrorPayload>;
319+
320+
static auto load(CommonRep const &value) noexcept -> CommonRep {
321+
std::atomic_ref<CommonRep const> ref(value);
322+
return ref.load(std::memory_order_relaxed);
323+
}
324+
325+
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
326+
std::atomic_ref<CommonRep> ref(value);
327+
ref.store(desired, std::memory_order_relaxed);
328+
}
329+
330+
static auto compare_exchange(CommonRep &value, CommonRep &expected,
331+
CommonRep desired) noexcept -> bool {
332+
std::atomic_ref<CommonRep> ref(value);
333+
return ref.compare_exchange_strong(expected, desired,
334+
std::memory_order_relaxed,
335+
std::memory_order_relaxed);
336+
}
337+
};
338+
339+
template <typename CommonRep, typename ErrorPayload>
340+
struct concurrency::handler<concurrency::fenced_acq_rel, void, CommonRep,
341+
ErrorPayload> {
342+
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
343+
using injection_type = concurrency::injection;
344+
using result_type = std::expected<CommonRep, ErrorPayload>;
345+
346+
static auto load(CommonRep const &value) noexcept -> CommonRep {
347+
std::atomic_ref<CommonRep const> ref(value);
348+
return ref.load(std::memory_order_acquire);
349+
}
350+
351+
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
352+
std::atomic_ref<CommonRep> ref(value);
353+
ref.store(desired, std::memory_order_release);
354+
}
355+
356+
static auto compare_exchange(CommonRep &value, CommonRep &expected,
357+
CommonRep desired) noexcept -> bool {
358+
std::atomic_ref<CommonRep> ref(value);
359+
return ref.compare_exchange_strong(expected, desired,
360+
std::memory_order_acq_rel,
361+
std::memory_order_acquire);
362+
}
363+
};
364+
365+
template <typename CommonRep, typename ErrorPayload>
366+
struct concurrency::handler<concurrency::fenced_seq_cst, void, CommonRep,
367+
ErrorPayload> {
368+
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
369+
using injection_type = concurrency::injection;
370+
using result_type = std::expected<CommonRep, ErrorPayload>;
371+
372+
static auto load(CommonRep const &value) noexcept -> CommonRep {
373+
return concurrency::handler<concurrency::fenced, void, CommonRep,
374+
ErrorPayload>::load(value);
375+
}
376+
377+
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
378+
concurrency::handler<concurrency::fenced, void, CommonRep,
379+
ErrorPayload>::store(value, desired);
380+
}
381+
382+
static auto compare_exchange(CommonRep &value, CommonRep &expected,
383+
CommonRep desired) noexcept -> bool {
384+
return concurrency::handler<concurrency::fenced, void, CommonRep,
385+
ErrorPayload>::compare_exchange(value, expected,
386+
desired);
387+
}
388+
};
389+
207390
template <operations::operation OpTag, typename CommonRep,
208391
typename ErrorPayload>
209392
struct value::handler<value::checked, OpTag, CommonRep, ErrorPayload> {

0 commit comments

Comments
 (0)