24constexpr std::uint64_t payload_schema = 1;
26 sequence_kind = 2, placement_kind = 3, request_kind = 4, pending_kind = 5
33template<
class Tag, auto Member>
struct PayloadMember {
34 friend auto payload_member(Tag) {
return Member; }
36#define PF_EXIT_PAYLOAD_MEMBER(Tag, Owner, Name) \
37 struct Tag { friend auto payload_member(Tag); }; \
38 template struct PayloadMember<Tag, &Owner::Name>
56#undef PF_EXIT_PAYLOAD_MEMBER
58template<
class T,
class Tag>
decltype(
auto) member(T& value, Tag tag) {
59 return (value.*payload_member(tag));
62template<
class T>
struct IsOptional : std::false_type {};
63template<
class T>
struct IsOptional<std::optional<T>> : std::true_type {};
64template<
class T>
struct IsVector : std::false_type {};
65template<
class T>
struct IsVector<std::vector<T>> : std::true_type {};
66template<
class T>
struct IsArray : std::false_type {};
67template<
class T, std::
size_t N>
struct IsArray<std::array<T, N>> : std::true_type {};
68template<
class T>
struct IsVariant : std::false_type {};
69template<
class... T>
struct IsVariant<std::variant<T...>> : std::true_type {};
70template<
class T>
struct IsShared : std::false_type {};
71template<
class T>
struct IsShared<std::shared_ptr<T>> : std::true_type {};
72template<
class T>
inline constexpr bool unsupported_payload =
false;
74template<
class Archive,
class T>
void payload_fields(Archive&, T&);
78 static constexpr bool reading =
false;
79 explicit PayloadOutput(std::uint64_t offset = 0, ScratchBuffer destination = {})
noexcept
80 : skip_(offset), destination_(destination) {}
82 template<
class... T>
void operator()(
const T&... value)
noexcept {
83 (payload_fields(*
this, value), ...);
85 void invalid() noexcept { status = ScratchStatus::programming_error; }
86 void bytes(
const char* data, std::size_t count)
noexcept {
87 if (status != ScratchStatus::ok)
return;
88 if (count > std::numeric_limits<std::uint64_t>::max() - size) {
93 if (skip_ >= count) { skip_ -= count;
return; }
94 const auto copied = std::min<std::size_t>(
95 destination_.size, count -
static_cast<std::size_t
>(skip_));
97 std::memcpy(destination_.data, data +
static_cast<std::size_t
>(skip_), copied);
98 destination_.data += copied;
99 destination_.size -= copied;
103 template<
class T>
void scalar(
const T& value)
noexcept {
104 if constexpr (std::is_enum_v<T>) {
105 scalar(
static_cast<std::underlying_type_t<T>
>(value));
107 std::uint64_t word = 0;
108 if constexpr (std::is_same_v<T, double>)
109 std::memcpy(&word, &value,
sizeof(word));
111 word =
static_cast<std::uint64_t
>(
value);
112 std::array<unsigned char, 8> encoded{};
113 for (
unsigned i = 0; i < encoded.size(); ++i)
114 encoded[i] =
static_cast<unsigned char>((word >> (i * 8)) & 0xff);
115 bytes(
reinterpret_cast<const char*
>(encoded.data()), encoded.size());
119 std::uint64_t size = 0;
123 ScratchBuffer destination_;
128 static constexpr bool reading =
true;
129 PayloadInput(
const CommandScratchStore& store,
ScratchHandle handle, std::uint64_t size) noexcept
130 : store_(store), handle_(handle), size_(size) {}
132 template<
class... T>
void operator()(T&... value) {
133 (payload_fields(*
this, value), ...);
135 [[noreturn]]
void invalid()
const {
138 std::uint64_t remaining() const noexcept {
return size_ - offset_; }
139 void bytes(
char* destination, std::size_t count) {
140 if (count > remaining()) invalid();
142 if (begin_ == end_) {
143 const auto available =
static_cast<std::size_t
>(
144 std::min<std::uint64_t>(buffer_.size(), remaining()));
146 {buffer_.data(), available}), store_);
150 const auto copied = std::min(count, end_ - begin_);
151 std::memcpy(destination, buffer_.data() + begin_, copied);
152 destination += copied;
158 template<
class T>
void scalar(T& value) {
159 if constexpr (std::is_enum_v<T>) {
160 std::underlying_type_t<T> underlying{};
162 value =
static_cast<T
>(underlying);
164 std::array<unsigned char, 8> encoded{};
165 bytes(
reinterpret_cast<char*
>(encoded.data()), encoded.size());
166 std::uint64_t word = 0;
167 for (
unsigned i = 0; i < encoded.size(); ++i)
168 word |=
static_cast<std::uint64_t
>(encoded[i]) << (i * 8);
169 if constexpr (std::is_same_v<T, double>) {
170 std::memcpy(&value, &word,
sizeof(word));
171 }
else if constexpr (std::is_signed_v<T>) {
172 std::int64_t signed_word = 0;
173 std::memcpy(&signed_word, &word,
sizeof(word));
174 if (signed_word < std::numeric_limits<T>::min()
175 || signed_word > std::numeric_limits<T>::max()) invalid();
176 value =
static_cast<T
>(signed_word);
178 if (word > std::numeric_limits<T>::max()) invalid();
179 value =
static_cast<T
>(word);
184 const CommandScratchStore& store_;
187 std::uint64_t offset_ = 0;
188 std::array<std::byte, 512> buffer_{};
189 std::size_t begin_ = 0, end_ = 0;
192template<std::
size_t I = 0,
class Archive,
class Variant>
193void read_variant(Archive& archive, Variant& value, std::uint64_t index) {
194 if constexpr (I < std::variant_size_v<Variant>) {
195 if (index == I) archive(
value.template emplace<I>());
196 else read_variant<I + 1>(archive, value, index);
202template<
class Archive,
class T>
void payload_fields(Archive& a, T& v) {
203 using V = std::remove_const_t<T>;
204 if constexpr (std::is_arithmetic_v<V> || std::is_enum_v<V>) {
205 static_assert(!std::is_floating_point_v<V> || std::is_same_v<V, double>);
207 }
else if constexpr (std::is_same_v<V, std::string>) {
208 std::uint64_t size = v.size();
210 if constexpr (Archive::reading) {
211 if (size > a.remaining() || size > v.max_size()) a.invalid();
212 v.resize(
static_cast<std::size_t
>(size));
214 a.bytes(v.data(), v.size());
215 }
else if constexpr (IsOptional<V>::value) {
216 bool present = v.has_value();
218 if constexpr (Archive::reading) {
219 if (present) a(v.emplace());
221 }
else if (present) a(*v);
222 }
else if constexpr (IsShared<V>::value) {
223 bool present =
static_cast<bool>(v);
225 if constexpr (Archive::reading) {
227 auto value = std::make_shared<std::remove_const_t<typename V::element_type>>();
229 v = std::move(value);
231 }
else if (present) a(*v);
232 }
else if constexpr (IsVector<V>::value) {
233 std::uint64_t size = v.size();
235 if constexpr (Archive::reading) {
238 if (size > v.max_size() || size > a.remaining() / 8) a.invalid();
239 v.resize(
static_cast<std::size_t
>(size));
241 for (
auto& value : v) a(value);
242 }
else if constexpr (IsArray<V>::value) {
243 for (
auto& value : v) a(value);
244 }
else if constexpr (IsVariant<V>::value) {
245 std::uint64_t index = v.index();
247 if constexpr (Archive::reading) read_variant(a, v, index);
249 if (v.valueless_by_exception()) { a.invalid();
return; }
250 std::visit([&](
const auto& value) { a(value); }, v);
252 }
else if constexpr (std::is_same_v<V, native_order::SessionKey>) {
253 if constexpr (Archive::reading) {
257 }
else a(v.string());
258 }
else if constexpr (std::is_same_v<V, native_order::RunIdentity>) {
259 a(v.session_key, v.run_number);
260 }
else if constexpr (std::is_same_v<V, native_order::RequestHandle>) {
261 a(v.run, v.incarnation);
262 }
else if constexpr (std::is_same_v<V, native_order::Request>) {
263 a(v.intent, v.label, v.comment, v.trigger, v.capacity, v.owner, v.group, v.anchor);
264 }
else if constexpr (std::is_same_v<V, native_order::Transact>
265 || std::is_same_v<V, native_order::ReverseTo>) {
267 }
else if constexpr (std::is_same_v<V, native_order::Reduce>) {
269 }
else if constexpr (std::is_same_v<V, native_order::ExplicitUnits>
270 || std::is_same_v<V, native_order::PointBudget>) {
272 }
else if constexpr (std::is_same_v<V, native_order::ScopeFraction>) {
273 a(v.fraction, v.claim, v.basis);
274 }
else if constexpr (std::is_same_v<V, native_order::HostSized>) {
276 }
else if constexpr (std::is_same_v<V, native_order::Sized>) {
277 a(v.side, v.basis, v.time, v.price, v.grid_policy, v.reserve_percent_fee);
278 }
else if constexpr (std::is_same_v<V, native_order::CashValue>) {
280 }
else if constexpr (std::is_same_v<V, native_order::EquityFraction>) {
282 }
else if constexpr (std::is_same_v<V, native_order::Limit>) {
283 a(v.price, v.fill_through);
284 }
else if constexpr (std::is_same_v<V, native_order::Stop>) {
286 }
else if constexpr (std::is_same_v<V, native_order::StopLimit>) {
288 }
else if constexpr (std::is_same_v<V, native_order::Trail>) {
289 a(v.offset, v.arm_price, v.ticks, v.best_seed);
290 }
else if constexpr (std::is_same_v<V, native_order::TrailTicks>) {
292 }
else if constexpr (std::is_same_v<V, native_order::FromOwnerFill>) {
293 a(v.offset, v.ticks, v.rounding);
294 }
else if constexpr (std::is_same_v<V, native_order::WaitForApplied>) {
295 a(v.parent, v.visibility, v.first_match, v.scope);
296 }
else if constexpr (std::is_same_v<V, native_order::BindOpening>) {
297 a(v.opening, v.cycle);
298 }
else if constexpr (std::is_same_v<V, native_order::BindOpenings>) {
299 a(v.openings, v.cycle);
300 }
else if constexpr (std::is_same_v<V, native_order::BindCohort>) {
302 }
else if constexpr (std::is_same_v<V, native_order::Member>) {
303 a(v.group, v.cohort, v.effect);
304 }
else if constexpr (std::is_same_v<V, PlacementSnapshot>) {
305 a(v.family, v.source_id, v.from_entry, v.comment, v.oca_name, v.oca_type, v.qty_type,
306 v.requested_qty, v.projection_remaining_qty, v.qty_percent, v.is_long,
307 v.immediately, v.opening, v.filled_exit, v.deferred_cohort, v.reservation_deferred_to_pending_entry,
308 v.void_issue, v.void_global_issue, v.pending_bound_exit, v.per_entry_origin,
309 v.per_entry_units, v.crosses_zero, v.follow_up_fill, v.waypoint_margin_call,
310 v.fixed_exit_reservation, v.frozen_market_instruction, v.frozen_market_own_units,
311 v.frozen_market_transaction_units, v.frozen_market_targeted_close,
312 v.frozen_market_target_was_long, v.direction_gate, v.affordability_policy_active,
313 v.affordability_close_only, v.rounded_signal_cost_close_only,
314 v.affordability_keep_mc_close_surplus, v.reverse_to, v.replaced_opening,
315 v.replacement_predecessor_market, v.terms_priced_reverse, v.frozen_reversal_transaction,
316 v.placement_cycle, v.sequential_group, v.sequential_rank, v.has_full_entry_bracket,
317 v.paired_reversal_parent, v.preserved_by_close_all, v.preserved_close_all_bar,
318 v.bracket_origin, v.source_sequence, v.command_ordinal, v.placement_open_epoch,
319 v.command_sequence, v.close_callsite_token, v.close_batch_calls, v.close_first_id,
320 v.close_first_target, v.close_first_ledger_consumed, v.close_first_carry_valid,
321 v.close_first_carry_qty, v.close_retire_ledger_whole, v.close_pending_later_qty,
322 v.placement_script_open_ms, v.placement_sub_open_ms, v.projection_created_bar,
323 v.projection_created_bar_pinned, v.projection_position_side, v.projection_after_close,
324 v.close_first_entry, v.signal_price_refused, v.projection_over_pyramiding,
325 v.projection_opposite_market_predecessor, v.projection_predecessor,
326 v.chain_origin_sequence, v.recreated_after_named_cancelled_entry_incarnation,
327 v.named_cancel_surviving_exit_incarnation, v.retained_parent_topology,
328 v.defer_until_post_parent_calculation, v.projection_predecessor_market,
329 v.projection_predecessor_exit, v.projection_created_during_coof,
330 v.projection_coof_at_terminal, v.projection_coof_mid_bar, v.forced_execution_price,
331 v.forced_waypoint_print, v.coof_open_stop_next_waypoint, v.projection_tv_carry_qty,
332 v.projection_default_stop_equity, v.projection_default_stop_signal_close,
333 v.projection_explicit_equity, v.projection_explicit_signal_close,
334 v.projection_affordability_equity, v.projection_affordability_signal_price,
335 v.projection_affordability_held_qty, v.sizing, v.exit_levels, v.trail_activation_level,
336 v.retained_trail_best, v.market_admission, v.birth, v.birth_reach, v.leg_activation,
337 v.exit_activation, v.legs, v.restored_after_margin, v.reservation_expansion,
338 v.reservation_growth_source, v.reservation_growth_owner_incarnation,
339 v.stop_limit_activated, v.coof_cascade_seg_i, v.coof_cascade_inflight_fires,
340 v.paired_flat_market_candidate, v.paired_flat_market_own_qty,
341 v.paired_flat_market_signal_close, v.paired_flat_market_signal_equity,
342 v.paired_flat_market_signal_margin_pct, v.paired_flat_market_signal_pointvalue,
343 v.paired_flat_market_signal_fx, v.paired_flat_market_peer_seq,
344 v.paired_flat_market_transaction_qty, v.signal_close_mc_bar,
345 v.signal_close_mc_entry_incarnation, v.signal_close_mc_fill_seq,
346 v.signal_close_mc_remaining_qty, v.pooc_global_full_exit_dynamic_qty,
347 v.pooc_global_full_exit_tracks_bound_adds, v.pooc_global_full_exit_bound_add,
349 }
else if constexpr (std::is_same_v<V, PineExitLevels>) {
350 a(v.limit, v.stop, v.trail_points, v.trail_offset, v.trail_price,
351 v.profit_ticks, v.loss_ticks);
352 }
else if constexpr (std::is_same_v<V, PineSizingSnapshot>) {
353 a(v.equity, v.price, v.fx, v.mark, v.frozen_units, v.at_fill, v.strategy_equity);
354 }
else if constexpr (std::is_same_v<V, PineCancellationReceipt>) {
355 a(v.cause, v.state, v.close_claim_release, v.source_incarnation, v.source_sequence,
356 v.target_incarnation, v.target_owner, v.target_revision,
357 v.close_claim_consumed, v.close_claim_retired);
358 }
else if constexpr (std::is_same_v<V, BirthCursor>) {
359 auto domain = v.domain();
360 auto position = v.position();
361 auto index = v.index();
362 auto count = v.count();
363 a(domain, position, index, count);
364 if constexpr (Archive::reading) {
374 }
else if constexpr (std::is_same_v<V, OrderBirth>) {
375 auto cause = v.cause();
377 auto timestamp = v.timestamp();
378 auto cursor = v.cursor();
379 auto price = v.cursor_price();
380 auto first = v.first_fill();
381 auto last = v.last_fill();
382 auto evaluation = v.evaluation_ordinal();
383 a(cause, bar, timestamp, cursor,
price, first, last, evaluation);
384 if constexpr (Archive::reading) {
393 bar, timestamp, cursor,
price, first, last, evaluation);
break;
394 default: a.invalid();
397 }
else if constexpr (std::is_same_v<V, ExitLegActivation>) {
398 a(member(v, ActivationBounds{}));
399 }
else if constexpr (std::is_same_v<V, ExitLegActivationBounds>) {
400 a(v.position_cycle, v.stop_first_bar, v.limit_first_bar);
401 }
else if constexpr (std::is_same_v<V, compat::pine::ExitActivationPolicy>) {
402 a(member(v, ActivationEvidence{}));
403 }
else if constexpr (std::is_same_v<V, compat::pine::ExitPlacementEvidence>) {
404 a(v.position_cycle, v.entry_bar, v.direction, v.cursor_price,
405 v.stop_level, v.limit_level, v.limit_continuation);
406 }
else if constexpr (std::is_same_v<V, compat::pine::LimitContinuation>) {
407 a(v.cause, v.observed_fill_sequence);
408 }
else if constexpr (std::is_same_v<V, ReservationExpansion>) {
409 a(member(v, ExpansionCapture{}));
410 }
else if constexpr (std::is_same_v<V, ReservationExpansionCapture>) {
411 a(v.position_cycle, v.side, v.first_later_admission);
412 }
else if constexpr (std::is_same_v<V, ReservationGrowthSource>) {
413 a(member(v, GrowthOwner{}));
414 }
else if constexpr (std::is_same_v<V, admission::Draft>) {
415 a(member(v, AdmissionObservation{}), member(v, AdmissionReview{}),
416 member(v, AdmissionSizing{}));
417 }
else if constexpr (std::is_same_v<V, admission::CommandObservation>) {
418 a(v.command, v.kind, v.birth, v.id, v.requested_quantity, v.quantity_type,
419 v.buy, v.prices, v.oca_name, v.oca_type, v.configuration, v.bar,
420 v.placement_side, v.placement_cycle, v.prior_close_quantity, v.held_quantity,
421 v.held_entries, v.realized_equity, v.placement_equity, v.signal_close,
422 v.quantized_fixed_quantity, v.original_sizing, v.explicit_equity, v.explicit_price);
423 }
else if constexpr (std::is_same_v<V, admission::Configuration>) {
424 a(v.process_on_close, v.calc_on_fills, v.magnifier, v.fill_recalculation, v.scheduler,
425 v.slippage, v.pyramiding, v.default_quantity_type, v.default_quantity_value,
426 v.long_margin, v.short_margin, v.commission_value, v.commission_type,
427 v.pointvalue, v.fx, v.quantity_step, v.mintick, v.risk_direction, v.loss_days_limit,
428 v.drawdown_limit, v.intraday_loss_limit, v.position_limit, v.fill_cap_active, v.risk_halted);
429 }
else if constexpr (std::is_same_v<V, admission::PriceRequest>) {
431 }
else if constexpr (std::is_same_v<V, admission::SizingObservation>) {
432 a(v.quantity, v.equity, v.price, v.mark, v.fx);
433 }
else if constexpr (std::is_same_v<V, admission::ReviewReceipt>) {
434 a(v.sequence, v.checkpoint, v.bar, v.target_command);
435 }
else if constexpr (std::is_same_v<V, admission::SizingRevision>) {
436 a(v.sequence, v.cause_fill, v.bar, v.target_command);
437 }
else if constexpr (std::is_same_v<V, exit_legs::Lifecycle>) {
438 a(member(v, LifecycleTarget{}), member(v, LifecycleRevision{}),
439 member(v, LifecycleDefinition{}), member(v, LifecycleGenerations{}),
440 member(v, LifecycleRetirements{}), member(v, LifecycleSuspension{}),
441 member(v, LifecycleReplay{}));
442 }
else if constexpr (std::is_same_v<V, exit_legs::Definition>) {
443 a(member(v, DefinitionIncarnation{}), member(v, DefinitionRevision{}),
444 member(v, DefinitionPrices{}));
445 }
else if constexpr (std::is_same_v<V, exit_legs::Prices>) {
446 a(v.limit_price, v.stop_price, v.trail_points, v.trail_price,
447 v.trail_offset, v.profit_ticks, v.loss_ticks);
448 }
else if constexpr (std::is_same_v<V, exit_legs::Target>) {
449 a(v.incarnation, v.owner);
450 }
else if constexpr (std::is_same_v<V, exit_legs::Frame>) {
451 a(v.event, v.bar, v.domain, v.phase);
452 }
else if constexpr (std::is_same_v<V, exit_legs::Retirement>) {
453 a(v.generation, v.cause);
454 }
else if constexpr (std::is_same_v<V, exit_legs::Barrier>) {
455 a(v.requested, v.target, v.revision);
456 }
else if constexpr (std::is_same_v<V, exit_legs::ObservationWindow>) {
457 a(v.excluded, v.best, v.prefix);
458 }
else if constexpr (std::is_same_v<V, exit_legs::Replacement>) {
459 a(v.queue_predecessor, v.revival_definition, v.release);
460 }
else if constexpr (std::is_same_v<V, exit_legs::Suspension>) {
461 a(v.cause, v.legs, v.hold, v.revival_definition, v.replacement, v.window);
462 }
else if constexpr (std::is_same_v<V, exit_legs::Action>) {
463 a(v.target, v.expected_revision, v.cause, v.operation);
464 }
else if constexpr (std::is_same_v<V, exit_legs::BindOwner>) {
466 }
else if constexpr (std::is_same_v<V, exit_legs::Suspend>) {
467 a(v.legs, v.hold, v.window, v.retire);
468 }
else if constexpr (std::is_same_v<V, exit_legs::StageReplacement>) {
470 }
else if constexpr (std::is_same_v<V, exit_legs::Restore>
471 || std::is_same_v<V, exit_legs::Cancel>) {
473 }
else if constexpr (std::is_same_v<V, exit_legs::CompleteBarrier>) {
474 a(v.completed, v.requested);
475 }
else if constexpr (std::is_same_v<V, exit_legs::Observe>) {
476 a(v.high, v.low, v.direction, v.fold);
477 }
else if constexpr (std::is_empty_v<V>) {
480 static_assert(unsupported_payload<V>,
"exit payload fields must be enumerated");
486 explicit PayloadSource(
const T&... values) : values_(values...) {
487 PayloadOutput output;
492 std::uint64_t size() const noexcept
override {
return size_; }
493 ScratchStatus read(std::uint64_t offset, ScratchBuffer destination)
const noexcept override {
494 if (offset > size_ || destination.size > size_ - offset
495 || (destination.size && !destination.data))
496 return ScratchStatus::programming_error;
497 PayloadOutput output(offset, destination);
499 return output.status;
502 void emit(PayloadOutput& output)
const noexcept {
503 output(payload_schema);
504 std::apply([&](
const auto&... value) { output(
value...); }, values_);
506 std::tuple<
const T&...> values_;
507 std::uint64_t size_ = 0;
511 std::uint64_t kind, T&... values) {
515 if (info.key_bytes !=
sizeof(words))
518 {reinterpret_cast<std::byte*>(words.data()), sizeof(words)}), store);
519 if (words[0] == 0 || words[1] != kind || words[3] != 0
520 || (kind == sequence_kind ? words[2] != 0 : words[2] == 0))
522 PayloadInput
input(store, version, info.value_bytes);
523 std::uint64_t schema = 0;
525 if (schema != payload_schema)
input.invalid();
531 std::uint64_t scope, std::uint64_t kind,
const T&... values) {
539 read_payload(store, counter, sequence_kind, sequence);
540 if (sequence == std::numeric_limits<std::uint64_t>::max())
543 const PayloadSource<std::uint64_t> counter_value(sequence);
544 const PayloadSource<T...> payload(values...);
549 auto status = store.put(counter_key, counter_value, ignored);
550 if (status == ScratchStatus::ok) status = store.put(key, payload, version);
561 return put_version(store_, scope, placement_kind, value);
567 read_payload(store_, version, placement_kind, value);
574 return put_version(store_, scope, request_kind, value);
580 read_payload(store_, version, request_kind, value);
586 const std::string& key) {
596 std::string saved_key;
597 read_payload(store_, version, pending_kind, saved_request, saved_placement, saved_key);
598 request = std::move(saved_request);
600 key = std::move(saved_key);
607 if (!read || cycle <= 0)
614 if (count > owner.
openings.max_size())
616 owner.
openings.resize(
static_cast<std::size_t
>(count));
617 for (std::uint64_t index = 0; index < count; ++index) {
618 auto& handle = owner.
openings[
static_cast<std::size_t
>(index)];
620 if (handle.run != run || !handle.incarnation)
static BirthCursor segment(BirthCursorDomain domain, int index, int count)
static BirthCursor point(BirthCursorDomain domain, int index, int count)
static OrderBirth direct_command(int bar, int64_t timestamp)
static OrderBirth chart_evaluation(int bar, int64_t timestamp)
static OrderBirth fill_evaluation(int bar, int64_t timestamp, BirthCursor cursor, double price, uint64_t first_fill, uint64_t last_fill, uint64_t evaluation_ordinal)
std::uint64_t placement(std::uint64_t scope, const PlacementSnapshot &) override
native_order::Owner freeze_openings(const native_order::RunIdentity &, std::int64_t cycle, std::uint64_t count, void *, OpeningReader) override
std::uint64_t request(std::uint64_t scope, const native_order::Request &) override
void release_scope(std::uint64_t scope) noexcept override
std::uint64_t pending(std::uint64_t scope, const native_order::Request &, const PlacementSnapshot &, const std::string &key) override
ExitScratchTeardownFailure teardown_failure_
ScratchStatus(*)(void *, std::uint64_t, native_order::RequestHandle &) OpeningReader
void check_teardown_failure() const
#define PF_EXIT_PAYLOAD_MEMBER(Tag, Owner, Name)
uint64_t sequence(const Event &event)
std::uint64_t ScratchHandle
std::variant< Independent, WaitForApplied, BindOpening, BindOpenings, BindCohort > Owner
std::array< std::uint64_t, 4 > ExitScratchKeyWords
void exit_scratch_check(ScratchStatus status)
void exit_scratch_erase_scope_noexcept(CommandScratchStore &store, std::uint64_t scope, std::uint64_t first_kind, std::uint64_t last_kind, ExitScratchTeardownFailure &failure) noexcept
ExitScratchKeyWords exit_scratch_words(ExitScratchContext &context, ScratchHandle handle)
ScratchHandle exit_scratch_seek(ExitScratchContext &context, const ScratchByteSource &key)
void exit_scratch_failure(ScratchStatus)
void exit_scratch_edit(ExitScratchContext &context, Edit operation)
Bind to a fixed cohort of already-live openings.
std::vector< RequestHandle > openings
Aggregate field order keeps market construction: Request{Transact{1.0}, "buy", "comment"}...