Skip to content

⚡ (patch) Hoist promise's future_base* owner, delete per-T cancel indirection - #109

Merged
kammce merged 2 commits into
mainfrom
hoist-promise-owner
Sep 3, 2026
Merged

⚡ (patch) Hoist promise's future_base* owner, delete per-T cancel indirection#109
kammce merged 2 commits into
mainfrom
hoist-promise-owner

Conversation

@kammce

@kammce kammce commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

  • promise_base now stores a future_base* (m_owner) instead of routing cancellation through a per-T cancel_promise<T> static function plus an m_cancel function pointer.
  • cancel() and unhandled_exception() only ever touch future_base's fields (m_tag, m_base), never anything T-specific, so both move from promise<T> to promise_base as ordinary non-template member functions — one shared compiled instance instead of one per T, and no more m_cancel store emitted in every coroutine's ramp.
  • promise_return_base<T>'s own, separate m_owner (future<T>*) is then eliminated too: since promise_return_base<T> is only ever used as a base of promise<T>, return_value()/return_void() reach promise_base::m_owner via a static_cast through promise<T> (added as a friend of promise_base for this) and downcast to future<T>*/future<void>*, instead of keeping a second, redundant pointer.

Measured on the usb demo (stm32f103zg, clang 20, MinSizeRel), rebuilt end-to-end through libhallibhal-utillibhal-usblibhal-arm-mcu → demos:

flash
baseline 65,069 B
after hoisting m_owner 64,821 B (−248 B)
after eliminating the redundant pointer 64,757 B (−64 B)
total −312 B

Test plan

  • All 12 async_context unit tests pass (ctest), including test_cancel and test_cross_context_await
  • Full downstream rebuild (libhal, libhal-util, libhal-usb, libhal-arm-mcu, demos) succeeds
  • usb demo binary flash size measured before/after each commit on identical toolchain/profile

…irection

promise_base now stores a future_base* (m_owner) instead of relying on a
per-T cancel_promise<T> static function plus an m_cancel function pointer.
cancel() and unhandled_exception() only ever touch future_base's fields
(m_tag, m_base), never anything T-specific, so both move from promise<T>
to promise_base as ordinary non-template member functions - one shared
compiled instance instead of one per T, and no more m_cancel store emitted
in every coroutine's ramp.

promise_return_base<T>::m_owner (future<T>*) stays separate and templated,
since return_value()/return_void() write into future<T>'s own m_storage,
which future_base doesn't have.

Measured on the usb demo (stm32f103zg, clang 20, MinSizeRel): 65,069 -> 64,821
bytes of flash (-248 B), verified via a full libhal -> libhal-util ->
libhal-usb -> libhal-arm-mcu -> demos rebuild. All 12 async_context tests
pass.
promise_base::m_owner (future_base*) and promise_return_base<T>::m_owner
(future<T>*) were pointing at the same object from two separate fields,
one per promise<T> - promise_return_base<T> is a sibling base of
promise_base (both are direct bases of promise<T>), not derived from it,
so it couldn't reach promise_base's pointer without its own copy.

Since promise_return_base<T> is only ever used as a base of promise<T>,
return_value()/return_void() can reach promise_base::m_owner safely via a
static_cast through promise<T> (added as a friend of promise_base for
this), then downcast to future<T>*/future<void>* to get at m_storage.
Removes the second field (4 B/frame RAM) and the redundant second store at
each of the three future<T> construction/move call sites.

Measured on the usb demo (stm32f103zg, clang 20, MinSizeRel): 64,821 ->
64,757 bytes of flash (-64 B), on top of the -248 B already landed in this
PR. All 12 async_context tests pass.
@kammce
kammce force-pushed the hoist-promise-owner branch from 7cfb170 to 24c02d9 Compare September 3, 2026 23:24
@kammce
kammce merged commit 2bbdb89 into main Sep 3, 2026
8 checks passed
@kammce
kammce deleted the hoist-promise-owner branch September 3, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant