Skip to content

Commit 102acc6

Browse files
committed
fix: Wire canonical options and callbacks through lift/lower
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent 0a43071 commit 102acc6

File tree

4 files changed

+240
-20
lines changed

4 files changed

+240
-20
lines changed

include/cmcpp/context.hpp

Lines changed: 116 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626

2727
namespace cmcpp
2828
{
29+
enum class EventCode : uint8_t;
30+
2931
using HostTrap = std::function<void(const char *msg) noexcept(false)>;
3032
using GuestRealloc = std::function<int(int ptr, int old_size, int align, int new_size)>;
3133
using GuestMemory = std::span<uint8_t>;
3234
using GuestPostReturn = std::function<void()>;
33-
using GuestCallback = std::function<void()>;
35+
using GuestCallback = std::function<void(EventCode, uint32_t, uint32_t)>;
3436
using HostUnicodeConversion = std::function<std::pair<void *, size_t>(void *dest, uint32_t dest_byte_len, const void *src, uint32_t src_byte_len, Encoding from_encoding, Encoding to_encoding)>;
3537

3638
// Canonical ABI Options ---
@@ -83,8 +85,18 @@ namespace cmcpp
8385
LiftLowerContext(const HostTrap &host_trap, const HostUnicodeConversion &conversion, const LiftLowerOptions &options, ComponentInstance *instance = nullptr)
8486
: trap(host_trap), convert(conversion), opts(options), inst(instance) {}
8587

88+
void set_canonical_options(CanonicalOptions options);
89+
CanonicalOptions *canonical_options();
90+
const CanonicalOptions *canonical_options() const;
91+
bool is_sync() const;
92+
void invoke_post_return() const;
93+
void notify_async_event(EventCode code, uint32_t index, uint32_t payload) const;
94+
8695
void track_owning_lend(HandleElement &lending_handle);
8796
void exit_call();
97+
98+
private:
99+
std::optional<CanonicalOptions> canonical_opts_;
88100
};
89101

90102
inline void trap_if(const LiftLowerContext &cx, bool condition, const char *message = nullptr) noexcept(false)
@@ -103,6 +115,54 @@ namespace cmcpp
103115
throw std::runtime_error(msg);
104116
}
105117

118+
inline void LiftLowerContext::set_canonical_options(CanonicalOptions options)
119+
{
120+
canonical_opts_ = std::move(options);
121+
opts = *canonical_opts_;
122+
}
123+
124+
inline CanonicalOptions *LiftLowerContext::canonical_options()
125+
{
126+
return canonical_opts_ ? &*canonical_opts_ : nullptr;
127+
}
128+
129+
inline const CanonicalOptions *LiftLowerContext::canonical_options() const
130+
{
131+
return canonical_opts_ ? &*canonical_opts_ : nullptr;
132+
}
133+
134+
inline bool LiftLowerContext::is_sync() const
135+
{
136+
if (auto *canon = canonical_options())
137+
{
138+
return canon->sync;
139+
}
140+
return true;
141+
}
142+
143+
inline void LiftLowerContext::invoke_post_return() const
144+
{
145+
if (auto *canon = canonical_options())
146+
{
147+
if (canon->post_return)
148+
{
149+
(*canon->post_return)();
150+
}
151+
}
152+
}
153+
154+
inline void LiftLowerContext::notify_async_event(EventCode code, uint32_t index, uint32_t payload) const
155+
{
156+
if (auto *canon = canonical_options())
157+
{
158+
trap_if(*this, canon->sync, "async continuation requires async canonical options");
159+
if (canon->callback)
160+
{
161+
(*canon->callback)(code, index, payload);
162+
}
163+
}
164+
}
165+
106166
inline LiftLowerContext make_trap_context(const HostTrap &trap)
107167
{
108168
HostUnicodeConversion convert{};
@@ -518,7 +578,7 @@ namespace cmcpp
518578
uint32_t read(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, uint32_t ptr, uint32_t n, bool sync, const HostTrap &trap);
519579
uint32_t cancel(bool sync, const HostTrap &trap);
520580
void drop(const HostTrap &trap);
521-
void complete_async(uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap);
581+
void complete_async(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap);
522582

523583
private:
524584
std::shared_ptr<SharedStreamState> shared_;
@@ -582,14 +642,19 @@ namespace cmcpp
582642

583643
auto pending = std::move(*shared_->pending_read);
584644
shared_->pending_read.reset();
585-
set_pending_event({EventCode::STREAM_READ, pending.handle_index, pack_copy_result(CopyResult::Cancelled, pending.progress)});
645+
auto payload = pack_copy_result(CopyResult::Cancelled, pending.progress);
646+
set_pending_event({EventCode::STREAM_READ, pending.handle_index, payload});
586647
state_ = CopyState::Done;
587648

588649
if (sync)
589650
{
590651
auto event = get_pending_event(trap);
591652
return event.payload;
592653
}
654+
if (pending.cx)
655+
{
656+
pending.cx->notify_async_event(EventCode::STREAM_READ, pending.handle_index, payload);
657+
}
593658
return BLOCKED;
594659
}
595660

@@ -606,10 +671,15 @@ namespace cmcpp
606671
Waitable::drop(trap);
607672
}
608673

609-
inline void ReadableStreamEnd::complete_async(uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap)
674+
inline void ReadableStreamEnd::complete_async(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap)
610675
{
611-
set_pending_event({EventCode::STREAM_READ, handle_index, pack_copy_result(result, progress)});
676+
auto payload = pack_copy_result(result, progress);
677+
set_pending_event({EventCode::STREAM_READ, handle_index, payload});
612678
state_ = (result == CopyResult::Completed) ? CopyState::Idle : CopyState::Done;
679+
if (cx)
680+
{
681+
cx->notify_async_event(EventCode::STREAM_READ, handle_index, payload);
682+
}
613683
}
614684

615685
inline void satisfy_pending_read(SharedStreamState &state, const HostTrap &trap)
@@ -624,7 +694,7 @@ namespace cmcpp
624694
pending.progress += consumed;
625695
if (pending.progress >= pending.requested)
626696
{
627-
pending.endpoint->complete_async(pending.handle_index, CopyResult::Completed, pending.progress, trap);
697+
pending.endpoint->complete_async(pending.cx, pending.handle_index, CopyResult::Completed, pending.progress, trap);
628698
state.pending_read.reset();
629699
}
630700
}
@@ -662,7 +732,7 @@ namespace cmcpp
662732
{
663733
auto pending = std::move(*shared_->pending_read);
664734
shared_->pending_read.reset();
665-
pending.endpoint->complete_async(pending.handle_index, CopyResult::Dropped, pending.progress, trap);
735+
pending.endpoint->complete_async(pending.cx, pending.handle_index, CopyResult::Dropped, pending.progress, trap);
666736
}
667737
shared_->writable_dropped = true;
668738
}
@@ -707,7 +777,7 @@ namespace cmcpp
707777
uint32_t read(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, uint32_t ptr, bool sync, const HostTrap &trap);
708778
uint32_t cancel(bool sync, const HostTrap &trap);
709779
void drop(const HostTrap &trap);
710-
void complete_async(uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap);
780+
void complete_async(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap);
711781

712782
private:
713783
std::shared_ptr<SharedFutureState> shared_;
@@ -772,14 +842,19 @@ namespace cmcpp
772842

773843
auto pending = std::move(*shared_->pending_read);
774844
shared_->pending_read.reset();
775-
set_pending_event({EventCode::FUTURE_READ, pending.handle_index, pack_copy_result(CopyResult::Cancelled, 0)});
845+
auto payload = pack_copy_result(CopyResult::Cancelled, 0);
846+
set_pending_event({EventCode::FUTURE_READ, pending.handle_index, payload});
776847
state_ = CopyState::Done;
777848

778849
if (sync)
779850
{
780851
auto event = get_pending_event(trap);
781852
return event.payload;
782853
}
854+
if (pending.cx)
855+
{
856+
pending.cx->notify_async_event(EventCode::FUTURE_READ, pending.handle_index, payload);
857+
}
783858
return BLOCKED;
784859
}
785860

@@ -796,10 +871,15 @@ namespace cmcpp
796871
Waitable::drop(trap);
797872
}
798873

799-
inline void ReadableFutureEnd::complete_async(uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap)
874+
inline void ReadableFutureEnd::complete_async(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, CopyResult result, uint32_t progress, const HostTrap &trap)
800875
{
801-
set_pending_event({EventCode::FUTURE_READ, handle_index, pack_copy_result(result, progress)});
876+
auto payload = pack_copy_result(result, progress);
877+
set_pending_event({EventCode::FUTURE_READ, handle_index, payload});
802878
state_ = (result == CopyResult::Completed) ? CopyState::Idle : CopyState::Done;
879+
if (cx)
880+
{
881+
cx->notify_async_event(EventCode::FUTURE_READ, handle_index, payload);
882+
}
803883
}
804884

805885
inline uint32_t WritableFutureEnd::write(const std::shared_ptr<LiftLowerContext> &cx, uint32_t handle_index, uint32_t ptr, const HostTrap &trap)
@@ -819,7 +899,7 @@ namespace cmcpp
819899
shared_->pending_read.reset();
820900
ensure_memory_range(*pending.cx, pending.ptr, 1, shared_->descriptor.alignment, shared_->descriptor.element_size);
821901
std::memcpy(pending.cx->opts.memory.data() + pending.ptr, shared_->value.data(), shared_->descriptor.element_size);
822-
pending.endpoint->complete_async(pending.handle_index, CopyResult::Completed, 1, trap);
902+
pending.endpoint->complete_async(pending.cx, pending.handle_index, CopyResult::Completed, 1, trap);
823903
}
824904

825905
set_pending_event({EventCode::FUTURE_WRITE, handle_index, pack_copy_result(CopyResult::Completed, 1)});
@@ -843,7 +923,7 @@ namespace cmcpp
843923
{
844924
auto pending = std::move(*shared_->pending_read);
845925
shared_->pending_read.reset();
846-
pending.endpoint->complete_async(pending.handle_index, CopyResult::Dropped, 0, trap);
926+
pending.endpoint->complete_async(pending.cx, pending.handle_index, CopyResult::Dropped, 0, trap);
847927
}
848928
shared_->writable_dropped = true;
849929
}
@@ -1603,10 +1683,31 @@ namespace cmcpp
16031683
HostUnicodeConversion convert;
16041684
GuestRealloc realloc;
16051685

1606-
std::unique_ptr<LiftLowerContext> createLiftLowerContext(const GuestMemory &memory, const Encoding &string_encoding = Encoding::Utf8, const std::optional<GuestPostReturn> &post_return = std::nullopt)
1686+
std::unique_ptr<LiftLowerContext> createLiftLowerContext(const GuestMemory &memory,
1687+
const Encoding &string_encoding = Encoding::Utf8,
1688+
const std::optional<GuestPostReturn> &post_return = std::nullopt,
1689+
bool sync = true,
1690+
const std::optional<GuestCallback> &callback = std::nullopt)
16071691
{
1608-
LiftLowerOptions opts(string_encoding, memory, realloc);
1692+
CanonicalOptions options;
1693+
options.string_encoding = string_encoding;
1694+
options.memory = memory;
1695+
options.realloc = realloc;
1696+
options.post_return = post_return;
1697+
options.sync = sync;
1698+
options.callback = callback;
1699+
return createLiftLowerContext(std::move(options));
1700+
}
1701+
1702+
std::unique_ptr<LiftLowerContext> createLiftLowerContext(CanonicalOptions options)
1703+
{
1704+
if (!options.realloc)
1705+
{
1706+
options.realloc = realloc;
1707+
}
1708+
LiftLowerOptions opts(options.string_encoding, options.memory, options.realloc);
16091709
auto retVal = std::make_unique<LiftLowerContext>(trap, convert, opts);
1710+
retVal->set_canonical_options(std::move(options));
16101711
return retVal;
16111712
}
16121713
};

include/cmcpp/lower.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ namespace cmcpp
7878
template <Field... Ts>
7979
inline WasmValVector lower_flat_values(LiftLowerContext &cx, uint32_t max_flat, uint32_t *out_param, Ts &&...vs)
8080
{
81+
if (auto *canon = cx.canonical_options())
82+
{
83+
trap_if(cx, canon->sync && max_flat == 0, "async lowering requires async canonical options");
84+
}
8185
WasmValVector retVal = {};
8286
// cx.inst.may_leave=false;
8387
constexpr auto flat_types = ValTrait<tuple_t<Ts...>>::flat_types;
@@ -93,9 +97,11 @@ namespace cmcpp
9397
retVal.insert(retVal.end(), flat.begin(), flat.end());
9498
};
9599
(lower_v(vs), ...);
100+
cx.invoke_post_return();
96101
return retVal;
97102
}
98103
// cx.inst.may_leave=true;
104+
cx.invoke_post_return();
99105
return retVal;
100106
}
101107

test/host-util.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,22 @@ class Heap
4343
}
4444
};
4545

46+
inline std::unique_ptr<LiftLowerContext> createLiftLowerContext(Heap *heap, CanonicalOptions options);
47+
4648
inline std::unique_ptr<LiftLowerContext> createLiftLowerContext(Heap *heap, Encoding encoding)
49+
{
50+
CanonicalOptions options;
51+
options.string_encoding = encoding;
52+
return createLiftLowerContext(heap, std::move(options));
53+
}
54+
55+
inline std::unique_ptr<LiftLowerContext> createLiftLowerContext(Heap *heap, CanonicalOptions options)
4756
{
4857
std::unique_ptr<cmcpp::InstanceContext> instanceContext = std::make_unique<cmcpp::InstanceContext>(trap, convert,
4958
[heap](int original_ptr, int original_size, int alignment, int new_size) -> int
5059
{
5160
return heap->realloc(original_ptr, original_size, alignment, new_size);
5261
});
53-
return instanceContext->createLiftLowerContext(heap->memory, encoding);
62+
options.memory = heap->memory;
63+
return instanceContext->createLiftLowerContext(std::move(options));
5464
}

0 commit comments

Comments
 (0)