-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathex07_custom_policy.cpp
More file actions
187 lines (160 loc) · 6.46 KB
/
ex07_custom_policy.cpp
File metadata and controls
187 lines (160 loc) · 6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* Example: ex07_custom_policy
*
* Purpose:
* Show end-to-end customization of all policy dimensions (type, value,
* error, concurrency) and custom operation binding integration.
*
* Expected results:
* - Custom policy traits are recognized and selected by dispatcher.
* - Custom value finalize step adjusts addition result by +1.
* - Input 20 and 21 produces final value 42.
* - Program prints a success message and exits with code 0.
*/
#include <atomic>
#include <expected>
#include <iostream>
#include <type_traits>
import mcpplibs.primitives;
import mcpplibs.primitives.operations.invoker;
using namespace mcpplibs::primitives;
namespace demo {
// Point 7 / Step 1: Define one custom tag for each policy dimension.
struct custom_value {};
struct custom_type {};
struct custom_error {};
struct custom_concurrency {};
} // namespace demo
// Point 7 / Step 2: Register tags into policy::traits.
template <> struct mcpplibs::primitives::policy::traits<demo::custom_value> {
using policy_type = demo::custom_value;
static constexpr bool enabled = true;
static constexpr auto kind = category::value;
};
template <> struct mcpplibs::primitives::policy::traits<demo::custom_type> {
using policy_type = demo::custom_type;
static constexpr bool enabled = true;
static constexpr auto kind = category::type;
};
template <> struct mcpplibs::primitives::policy::traits<demo::custom_error> {
using policy_type = demo::custom_error;
static constexpr bool enabled = true;
static constexpr auto kind = category::error;
};
template <>
struct mcpplibs::primitives::policy::traits<demo::custom_concurrency> {
using policy_type = demo::custom_concurrency;
static constexpr bool enabled = true;
static constexpr auto kind = category::concurrency;
};
// Point 7 / Step 3A: Implement custom type handler.
// Always allow and negotiate through std::common_type_t.
template <operations::operation OpTag, typename LhsRep, typename RhsRep>
struct mcpplibs::primitives::policy::type::handler<demo::custom_type, OpTag,
LhsRep, RhsRep> {
static constexpr bool enabled = true;
static constexpr bool allowed = true;
static constexpr unsigned diagnostic_id = 0;
using common_rep = std::common_type_t<LhsRep, RhsRep>;
};
// Point 7 / Step 3B: Implement custom concurrency handler.
template <operations::operation OpTag, typename CommonRep,
typename ErrorPayload>
struct mcpplibs::primitives::policy::concurrency::handler<
demo::custom_concurrency, OpTag, CommonRep, ErrorPayload> {
static constexpr bool enabled = true;
using injection_type = mcpplibs::primitives::policy::concurrency::injection;
using result_type = std::expected<CommonRep, ErrorPayload>;
static constexpr auto inject() noexcept -> injection_type {
injection_type out{};
out.fence_before = true;
out.fence_after = false;
out.order_before = std::memory_order_acquire;
out.order_after = std::memory_order_relaxed;
return out;
}
};
template <typename CommonRep, typename ErrorPayload>
struct mcpplibs::primitives::policy::concurrency::handler<
demo::custom_concurrency, void, CommonRep, ErrorPayload> {
static constexpr bool enabled = true;
using injection_type = mcpplibs::primitives::policy::concurrency::injection;
using result_type = std::expected<CommonRep, ErrorPayload>;
static constexpr auto load(CommonRep const &value) noexcept -> CommonRep {
return value;
}
static constexpr auto store(CommonRep &value, CommonRep desired) noexcept
-> void {
value = desired;
}
static constexpr auto compare_exchange(CommonRep &value, CommonRep &expected,
CommonRep desired) noexcept -> bool {
if (value != expected) {
expected = value;
return false;
}
value = desired;
return true;
}
};
// Point 7 / Step 3C: Implement custom value handler.
// Complex point: finalize() post-processes decision and adjusts output.
template <operations::operation OpTag, typename CommonRep,
typename ErrorPayload>
struct mcpplibs::primitives::policy::value::handler<demo::custom_value, OpTag,
CommonRep, ErrorPayload> {
static constexpr bool enabled = true;
static constexpr bool may_adjust_value = true;
using decision_type =
mcpplibs::primitives::policy::value::decision<CommonRep>;
using result_type = std::expected<CommonRep, ErrorPayload>;
static constexpr auto
finalize(decision_type decision,
mcpplibs::primitives::policy::concurrency::injection const &)
-> decision_type {
if (decision.has_value) {
decision.value = static_cast<CommonRep>(decision.value + 1);
}
return decision;
}
};
// Point 7 / Step 3D: Provide binding for custom value policy + Addition.
// Without this specialization, runtime::run_value static_assert will fail.
template <typename CommonRep>
struct mcpplibs::primitives::operations::runtime::op_binding<
mcpplibs::primitives::operations::Addition, demo::custom_value, CommonRep> {
static constexpr bool enabled = true;
static constexpr auto apply(CommonRep lhs, CommonRep rhs)
-> mcpplibs::primitives::policy::value::decision<CommonRep> {
mcpplibs::primitives::policy::value::decision<CommonRep> out{};
out.has_value = true;
out.value = static_cast<CommonRep>(lhs + rhs);
return out;
}
};
// Point 7 / Step 3E: Implement custom error handler.
template <operations::operation OpTag, typename CommonRep,
typename ErrorPayload>
struct mcpplibs::primitives::policy::error::handler<demo::custom_error, OpTag,
CommonRep, ErrorPayload> {
static constexpr bool enabled = true;
using request_type = mcpplibs::primitives::policy::error::request<CommonRep>;
using result_type = std::expected<CommonRep, ErrorPayload>;
static constexpr auto resolve(request_type const &) -> result_type {
return std::unexpected(policy::error::kind::unspecified);
}
};
int main() {
// Point 7 / Step 4: Compose all custom tags and execute a call path.
using custom_t = primitive<int, demo::custom_value, demo::custom_type,
demo::custom_error, demo::custom_concurrency>;
auto const lhs = custom_t{20};
auto const rhs = custom_t{21};
auto const result = operations::add(lhs, rhs);
if (!result.has_value() || result->value() != 42) {
std::cerr << "custom policy pipeline failed\n";
return 1;
}
std::cout << "custom policy demo passed\n";
return 0;
}