Skip to content

add thread-safe dispatcher callback mechanism#694

Open
arnetheduck wants to merge 8 commits into
masterfrom
thread-call-soon
Open

add thread-safe dispatcher callback mechanism#694
arnetheduck wants to merge 8 commits into
masterfrom
thread-call-soon

Conversation

@arnetheduck

@arnetheduck arnetheduck commented Jul 16, 2026

Copy link
Copy Markdown
Member

callSoon currently is well-defined for the current thread but cannot be called from a different thread.

ThreadSignalPtr can be used to overcome this limitation but comes with the significant downside that each signal requires its own file descriptor / handle - while this approach works for specific cases it becomes costly in a general-purpose setting such as https://github.com/status-im/nim-async-channels where each channel ends up needing its own instance.

It would in theory be possible to use a thread-local ThreadSignalPtr for channels in particular, but this would still not achieve the higher goal of sharing a single wake-up / notification mechanism per event loop instance.

A thread-safe callSoon allows threads to post work to the dispatcher of another thread and getting called back from within the scope of that thread "soon" - for example, in the AsyncChannel when a reader appears and the channel is empty, the reader can register its own dispatcher with the channel so that when a queue item appears, the channel can wake up the corresponding dispatcher and complete the future from within the correct thread-local context.

A simple unbounded MPSC queue is used for storing cross-thread callbacks - the cost is roughly equivalent to the existing AsyncCallback when used with a closure environment, ie one allocation per posted work item plus whatever the caller needs.

The design does not depend on the specific queue being used, ie a future version could use a ring buffer + a spill queue or similar designs that reduce allocations.

Coupled with the queue is a cross-platform "wakeup" mechanism similar to the one used in ThreadSignalPtr - when a callback is posted to the queue, we also make sure to wake up the dispatcher so that indeed the callback happens "soon".

Base automatically changed from more-reset to master July 16, 2026 17:16
@arnetheduck
arnetheduck marked this pull request as ready for review July 17, 2026 19:04
`callSoon` currently is well-defined for the current thread but cannot
be called from a different thread.

`ThreadSignalPtr` can be used to overcome this limitation but comes with
the significant downside that each signal requires its own file
descriptor / handle - while this approach works for specific cases it
becomes costly in a general-purpose setting such as
https://github.com/status-im/nim-async-channels where each channel ends
up needing its own instance.

It would in theory be possible to use a thread-local `ThreadSignalPtr`
for channels in particular, but this would still not achieve the higher
goal of sharing a single wake-up / notification mechanism per event loop
instance.

A thread-safe `callSoon` allows threads to post work to the dispatcher
of another thread and getting called back from within the scope of that
thread "soon" - for example, in the AsyncChannel when a reader appears
and the channel is empty, the reader can register its own dispatcher
with the channel so that when a queue item appears, the channel can wake
up the corresponding dispatcher and complete the future from within the
correct thread-local context.

A simple unbounded MPSC queue is used for storing cross-thread callbacks
- the cost is roughly equivalent to the existing `AsyncCallback` when
used with a closure environment, ie one allocation per posted work item
plus whatever the caller needs.

The design does not depend on the specific queue being used, ie a future
version could use a ring buffer + a spill queue or similar designs that
reduce allocations.

Coupled with the queue is a cross-platform "wakeup" mechanism similar to
the one used in `ThreadSignalPtr` - when a callback is posted to the
queue, we also make sure to wake up the dispatcher so that indeed the
callback happens "soon".
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