You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The presets build tests with GCC/Clang coverage instrumentation enabled, so generating a report is mostly a matter of running the suite and capturing the counters. On Ubuntu the full workflow looks like:
169
+
170
+
```bash
171
+
# 1. Install tooling (once per machine)
172
+
sudo apt-get update
173
+
sudo apt-get install -y lcov
174
+
175
+
# 2. Rebuild and rerun tests to refresh .gcda files
Generated artifacts live in the `build/` directory (`coverage.info`, `coverage.filtered.info`, and optionally `coverage-html/`). The same commands work on other platforms once the equivalent of `lcov` (or LLVM's `llvm-cov`) is installed.
168
193
169
194
## Usage
170
195
171
196
This library is a header only library. To use it in your project, you can:
172
197
-[x] Copy the contents of the `include` directory to your project.
173
198
-[ ] Use `vcpkg` to install the library and its dependencies.
174
199
175
-
### Async runtime helpers
200
+
### Configuring `InstanceContext` and canonical options
201
+
202
+
Most host interactions begin by materialising an `InstanceContext`. This container wires together the host trap callback, string conversion routine, and the guest `realloc` export. Use `createInstanceContext` to capture those dependencies once:
203
+
204
+
```cpp
205
+
cmcpp::HostTrap trap = [](constchar *msg) {
206
+
throw std::runtime_error(msg ? msg : "trap");
207
+
};
208
+
cmcpp::HostUnicodeConversion convert = {}; // see test/host-util.cpp for an ICU-backed example
209
+
cmcpp::GuestRealloc realloc = [&](int ptr, int old_size, int align, int new_size) {
auto cx = icx->createLiftLowerContext(std::move(options));
232
+
cx->inst = &component_instance;
233
+
```
234
+
235
+
The canonical options determine whether async continuations are allowed (`sync`), which hook to run after a successful lowering (`post_return`), and how async notifications surface back to the embedder (`callback`). Every guest call that moves data across the ABI should use the same context until `LiftLowerContext::exit_call()` is invoked.
236
+
237
+
### Driving async flows with the runtime harness
176
238
177
-
The canonical Component Model runtime is cooperative: hosts must drive pending work by scheduling tasks explicitly. `cmcpp` now provides a minimal async harness in `cmcpp/runtime.hpp`:
239
+
The Component Model runtime is cooperative: hosts advance work by draining a pending queue. `cmcpp/runtime.hpp` provides the same primitives as the canonical Python reference:
178
240
179
-
-`Store` owns the pending task queue and exposes `invoke` plus `tick()`.
241
+
- `Store` owns the queue of `Thread` objects and exposes `invoke` plus `tick()`.
180
242
- `FuncInst` is the callable signature hosts use to wrap guest functions.
181
-
-`Thread::create` builds a pending task with user-supplied readiness/resume callbacks.
182
-
-`Call::from_thread` returns a cancellation-capable handle to the caller.
183
-
-`Task` coordinates canonical backpressure, `canon_task.{return,cancel}`, and `canon_yield` helpers exposed through `context.hpp`.
184
-
-`canon_backpressure_{set,inc,dec}` update in-flight counters; most canonical entry points now guard `ComponentInstance::may_leave` before touching guest state.
243
+
- `Thread::create` builds resumable work with readiness and resume callbacks.
244
+
- `Call::from_thread` returns a handle that supports cancellation and completion queries.
245
+
- `Task` bridges canonical backpressure (`canon_task.{return,cancel}`) and ensures `ComponentInstance::may_leave` rules are enforced.
185
246
186
-
Typical usage:
247
+
A minimal async call looks like this:
187
248
188
249
```cpp
189
250
cmcpp::Store store;
190
-
cmcpp::FuncInst func = [](cmcpp::Store &store,
191
-
cmcpp::SupertaskPtr,
192
-
cmcpp::OnStart on_start,
193
-
cmcpp::OnResolve on_resolve) {
251
+
252
+
cmcpp::FuncInst guest = [](cmcpp::Store &store,
253
+
cmcpp::SupertaskPtr,
254
+
cmcpp::OnStart on_start,
255
+
cmcpp::OnResolve on_resolve) {
194
256
auto args = std::make_shared<std::vector<std::any>>(on_start());
195
-
auto gate = std::make_shared<std::atomic<bool>>(false);
257
+
auto ready = std::make_shared<std::atomic<bool>>(false);
std::printf("resolved with %d\n", std::any_cast<int32_t>((*values)[0]));
279
+
});
280
+
281
+
while (!call.completed()) {
282
+
store.tick();
283
+
}
213
284
```
214
285
215
-
### Waitables, streams, and futures
286
+
`Call::request_cancellation()` cooperatively aborts work before the next `tick()`, mirroring the canonical `cancel` semantics.
287
+
288
+
### Waitables, streams, futures, and other resources
289
+
290
+
`ComponentInstance` manages resource tables that back the canonical `canon_waitable_*`, `canon_stream_*`, and `canon_future_*` entry points. Hosts typically:
291
+
292
+
1. Instantiate a descriptor (`make_stream_descriptor<T>()`, `make_future_descriptor<T>()`, etc.).
293
+
2. Create handles via `canon_stream_new`/`canon_future_new`, which return packed readable/writable indices.
294
+
3. Join readable ends to a waitable set with `canon_waitable_join`.
295
+
4. Poll readiness using `canon_waitable_set_poll`, decoding the `EventCode` and payload stored in guest memory.
296
+
5. Drop resources with the corresponding `canon_*_drop_*` helpers once the guest is finished.
297
+
298
+
Streams and futures honour the canonical copy result payload layout, so the values copied into guest memory exactly match the spec. Cancellation helpers (`canon_stream_cancel_*`, `canon_future_cancel_*`) post events when the embedder requests termination, and the async callback registered in `CanonicalOptions` receives the same event triplet that the waitable set reports.
299
+
300
+
For a complete walkthrough, see the doctest suites in `test/main.cpp`:
216
301
217
-
The canonical async ABI surfaces are implemented via `canon_waitable_*`, `canon_stream_*`, and `canon_future_*` helpers on `ComponentInstance`. Waitable sets can be joined to readable/writable stream ends or futures, and `canon_waitable_set_poll` reports readiness using the same event payload layout defined by the spec. See the doctests in `test/main.cpp` for end-to-end examples.
- "Task yield, cancel, and return" exercises backpressure and async task APIs.
218
306
219
-
Call `tick()` in your host loop until all pending work completes. Cancellation is cooperative: calling `Call::request_cancellation()` marks the associated thread as cancelled before the next `tick()`.
307
+
Those tests are ICU-enabled and run automatically via `ctest`.
The canonical ABI reference (`design/mvp/canonical-abi/definitions.py`) includes a `Store`, `Thread`, and scheduling loop that enable cooperative async execution via `tick()`. The current C++ headers lack any runtime to drive asynchronous component calls.
@@ -26,6 +27,7 @@ The canonical ABI reference (`design/mvp/canonical-abi/definitions.py`) includes
26
27
27
28
## Issue: Complete resource handle lifecycle
28
29
-**Labels:**`enhancement`, `abi`
30
+
-**Status:** Done
29
31
30
32
### Background
31
33
`ResourceHandle`, `ResourceType`, and `ComponentInstance.resources` are currently empty shells. The canonical implementation tracks ownership, borrow counts, destructors, and exposes `canon resource.{new,drop,rep}`.
@@ -49,6 +51,7 @@ The canonical ABI reference (`design/mvp/canonical-abi/definitions.py`) includes
49
51
50
52
### Background
51
53
Canonical ABI defines waitables, waitable-sets, buffers, streams, and futures plus their cancellation behaviors. Our headers only contain empty structs.
54
+
-**Status:** Done
52
55
53
56
### Scope
54
57
- Model waitable and waitable-set state, including registration with the component store.
@@ -66,6 +69,7 @@ Canonical ABI defines waitables, waitable-sets, buffers, streams, and futures pl
66
69
67
70
## Issue: Implement backpressure and task lifecycle management
68
71
-**Labels:**`enhancement`, `async`
72
+
-**Status:** Done
69
73
70
74
### Background
71
75
`ComponentInstance` holds flags for `may_leave`, `backpressure`, and call-state tracking but they are unused. Canonical ABI specifies `canon task.{return,cancel}`, `canon yield`, and backpressure counters governing concurrent entry.
@@ -86,6 +90,7 @@ Canonical ABI defines waitables, waitable-sets, buffers, streams, and futures pl
86
90
87
91
## Issue: Support context locals and error-context APIs
88
92
-**Labels:**`enhancement`, `abi`
93
+
-**Status:** Done
89
94
90
95
### Background
91
96
`LiftLowerContext` currently omits instance references and borrow scopes, and `ContextLocalStorage`/`ErrorContext` types are unused. The canonical ABI exposes `canon context.{get,set}` and `canon error-context.{new,debug-message,drop}`.
@@ -106,6 +111,7 @@ Canonical ABI defines waitables, waitable-sets, buffers, streams, and futures pl
106
111
107
112
## Issue: Finish function flattening utilities
108
113
-**Labels:**`enhancement`, `abi`
114
+
-**Status:** Done
109
115
110
116
### Background
111
117
`include/cmcpp/func.hpp` contains commented-out flattening helpers. Canonical ABI requires flattening functions to honor `MAX_FLAT_PARAMS/RESULTS` and spill to heap memory via the provided `realloc`.
@@ -146,6 +152,7 @@ Canonical ABI defines waitables, waitable-sets, buffers, streams, and futures pl
146
152
147
153
## Issue: Expand docs and tests for canonical runtime features
148
154
-**Labels:**`documentation`, `testing`
155
+
-**Status:** Done
149
156
150
157
### Background
151
158
New runtime pieces require supporting documentation and tests. Currently, README lacks guidance and test coverage mirrors only existing functionality.
0 commit comments