2626
2727namespace 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 };
0 commit comments