Conversation
timkpaine
force-pushed
the
tkp/async
branch
4 times, most recently
from
January 29, 2026 23:08
51f67ea to
09f328e
Compare
timkpaine
force-pushed
the
tkp/async
branch
3 times, most recently
from
February 2, 2026 00:05
5695b7d to
ac2e73d
Compare
timkpaine
force-pushed
the
tkp/async
branch
14 times, most recently
from
February 24, 2026 21:51
630f881 to
f39ab39
Compare
timkpaine
force-pushed
the
tkp/async
branch
6 times, most recently
from
February 26, 2026 14:34
d92c799 to
0c8f2e6
Compare
timkpaine
force-pushed
the
tkp/async
branch
4 times, most recently
from
February 27, 2026 21:23
b1d21db to
ed71f55
Compare
Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
Member
Author
|
5 critical issues fixed:
|
Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
Member
Author
|
More key fixes:
|
… fd test Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
Async alarms were poll-only: nothing woke the node when a coroutine finished, so a node with no other ticking input never delivered results and every example had to hand-roll a 10ms csp.alarm loop. When an engine loop exists the alarm now borrows it, which puts completions on the engine thread and lets them fire the alarm's own slot directly. Failures wake the node too, so an exception surfaces instead of sitting in the queue. Without an engine loop the alarm keeps its background thread and the old poll semantics. csp.ticked() on an async alarm also consumed a result per evaluation, because get_result() dequeued. A per-cycle latch makes it idempotent, cleared by a start_cycle() call injected immediately after the per-cycle yield, which is the one point that runs exactly once per invocation. csp.run(realtime=True) accepted queue_wait_time and discarded it, cleared the caller's event loop instead of restoring it, and reported a nested call as "Cannot run the event loop while another loop is running". All three are fixed; the loop is captured without the event loop policy, which is deprecated in 3.14 and removed in 3.16. async_node queued input without limit, so a slow function grew memory until it ran out. maxsize and on_overflow are now explicit and default to the previous unbounded behaviour. maxsize bounds in-flight work as well as queued work, since bounding only the queue moves the backlog into the task set rather than removing it. The 10Hz shutdown poll is replaced by a sentinel, with cancellation still guaranteeing termination. Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
A signal handler runs on the thread it interrupts, and ours calls call_soon_threadsafe, which takes _csock_lock. When the signal arrived while that same thread already held the lock the process deadlocked, so the lock is now reentrant. csp.ticked() is a plain predicate everywhere else in csp, but on an async alarm it could raise the coroutine's exception. The failure is now latched and raised where the node reads the alarm's value, and an error the node never reads is logged rather than dropped. The shutdown sentinel left the async_node concurrency semaphore held on its way out, the engine ran a full cycle on every loop wakeup rather than only when a wakeup was signalled or an event was due, and the FastAPI example served an unauthenticated state-mutating endpoint on 0.0.0.0. The async_alarm docstring told users to call stop() themselves, which fails: the alarm name is rewritten to a value read, so aa.stop() becomes an attribute lookup on the result. The generated stop block already does this, verified by running graphs on both the borrowed-loop and owned-loop paths without leaking a thread. __all__ no longer advertises helpers that csp does not re-export. Tests: bridge tests now register cleanup so a failed assertion cannot leak the loop thread, wait on conditions instead of fixed sleeps, and scale the call_later bound by the platform timer resolution. Adds coverage for the parser's assign/delete guard, for alarm types that have no __name__, for the new ticked() semantics, and an FdWaiter construct/destroy-under-load stress test. Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
Asyncio-Integration.md and Event-Loop-Integration.md were near-identical: same title, 803 and 796 lines, 25 of 28 code blocks and 69 of 77 headings byte-identical. Neither was a superset, so deleting either would have lost content: one carried Part 0 on same-thread asyncio mode and the comparison table, the other carried simulation mode and the matching CspEventLoop constructor and set_simulation_time_range reference. Fold both sets into Event-Loop-Integration.md, whose filename matches the title the two shared, and drop the other along with its sidebar entry. Every heading and code block from the deleted page is present in the merged one. Async.md is a different document, about the adapters rather than the loop, and shares no code with either. It restated how same-thread mode works, so that is now a link to the page that owns the topic. Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Putting this up for some discussion, we've been talking/integrating csp with lots of other frameworks, and many of them are based on asyncio. This PR adds some bridging utilities. For now they are mostly one direction, but we can also add the other direction which should be easy (e.g. running csp in a background thread and making edges awaitable / async generators).