Skip to content

Commit 880cada

Browse files
feat: Add concurrent access interface to primitive type
1 parent 239c448 commit 880cada

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

src/primitive/impl.cppm

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,97 @@ export module mcpplibs.primitives.primitive.impl;
66

77
import mcpplibs.primitives.underlying.traits;
88
import mcpplibs.primitives.policy.traits;
9+
import mcpplibs.primitives.policy.impl;
10+
import mcpplibs.primitives.policy.handler;
911

1012
export namespace mcpplibs::primitives {
1113

14+
namespace details {
15+
16+
template <policy::policy_type... Policies> struct count_concurrency_policies;
17+
18+
template <> struct count_concurrency_policies<> {
19+
static constexpr std::size_t value = 0;
20+
};
21+
22+
template <policy::policy_type First, policy::policy_type... Rest>
23+
struct count_concurrency_policies<First, Rest...> {
24+
static constexpr bool is_match =
25+
policy::traits<First>::kind == policy::category::concurrency;
26+
static constexpr std::size_t value =
27+
count_concurrency_policies<Rest...>::value + (is_match ? 1u : 0u);
28+
};
29+
30+
template <policy::policy_type... Policies> struct resolve_concurrency_policy;
31+
32+
template <> struct resolve_concurrency_policy<> {
33+
using type = policy::defaults::concurrency;
34+
};
35+
36+
template <policy::policy_type First, policy::policy_type... Rest>
37+
struct resolve_concurrency_policy<First, Rest...> {
38+
using type = std::conditional_t<
39+
policy::traits<First>::kind == policy::category::concurrency, First,
40+
typename resolve_concurrency_policy<Rest...>::type>;
41+
};
42+
43+
template <policy::policy_type... Policies>
44+
using resolve_concurrency_policy_t =
45+
typename resolve_concurrency_policy<Policies...>::type;
46+
47+
} // namespace details
48+
1249
template <underlying_type T, policy::policy_type... Policies> class primitive {
1350
public:
1451
using value_type = T;
1552
using policies = std::tuple<Policies...>;
53+
using concurrency_policy = details::resolve_concurrency_policy_t<Policies...>;
54+
55+
static_assert(details::count_concurrency_policies<Policies...>::value <= 1,
56+
"Multiple concurrency policies are not allowed");
57+
1658
constexpr explicit primitive(value_type v) noexcept : value_(v) {}
1759
constexpr value_type &value() noexcept { return value_; }
1860
[[nodiscard]] constexpr value_type const &value() const noexcept { return value_; }
1961
constexpr explicit operator value_type() const noexcept { return value_; }
2062

63+
[[nodiscard]] auto load() const noexcept -> value_type {
64+
using access_handler_t =
65+
policy::concurrency::handler<concurrency_policy, void, value_type,
66+
policy::error::kind>;
67+
static_assert(
68+
policy::concurrency::handler_access_available<concurrency_policy,
69+
value_type>,
70+
"Selected concurrency policy does not provide primitive "
71+
"load/store/CAS support");
72+
return access_handler_t::load(value_);
73+
}
74+
75+
auto store(value_type desired) noexcept -> void {
76+
using access_handler_t =
77+
policy::concurrency::handler<concurrency_policy, void, value_type,
78+
policy::error::kind>;
79+
static_assert(
80+
policy::concurrency::handler_access_available<concurrency_policy,
81+
value_type>,
82+
"Selected concurrency policy does not provide primitive "
83+
"load/store/CAS support");
84+
access_handler_t::store(value_, desired);
85+
}
86+
87+
auto compare_exchange(value_type &expected, value_type desired) noexcept
88+
-> bool {
89+
using access_handler_t =
90+
policy::concurrency::handler<concurrency_policy, void, value_type,
91+
policy::error::kind>;
92+
static_assert(
93+
policy::concurrency::handler_access_available<concurrency_policy,
94+
value_type>,
95+
"Selected concurrency policy does not provide primitive "
96+
"load/store/CAS support");
97+
return access_handler_t::compare_exchange(value_, expected, desired);
98+
}
99+
21100
private:
22101
value_type value_;
23102
};

0 commit comments

Comments
 (0)