Skip to content

Implement stop token in ChannelRaw for improved control#86

Open
planetis-m wants to merge 5 commits intonim-lang:masterfrom
planetis-m:patch-4
Open

Implement stop token in ChannelRaw for improved control#86
planetis-m wants to merge 5 commits intonim-lang:masterfrom
planetis-m:patch-4

Conversation

@planetis-m
Copy link
Contributor

@planetis-m planetis-m commented Feb 20, 2026

Summary

This PR makes Chan safer to shut down and easier to use in real-world threaded systems:

  • Adds a channel stop token (Atomic[bool]) and public control APIs:
    • chan.stop() to request shutdown and wake blocked waiters
    • chan.stopToken() to query stop state
  • Adds optional timeout support to blocking operations:
    • send(..., timeout = default(Duration)) -> bool
    • recv(..., timeout = default(Duration)) -> bool
    • timeout logic only activates when timeout != default(Duration)
  • Adds auto-drain on final channel destroy:
    • remaining queued items are destroyed in-place before channel memory is freed

Why this should be merged

Today, blocking channel operations can wait indefinitely unless callers build their own cancellation/time budget logic around them. This PR moves those concerns into the primitive itself, which improves correctness and reduces boilerplate in every caller.

Concretely, this improves:

  • Graceful shutdown: blocked producers/consumers can be unblocked cleanly via stop().
  • Bounded waiting: callers can cap blocking time using Duration.
  • Resource safety on teardown: queued items are destructed during final drain, reducing leak risk for non-trivial payloads.

Behavioral details

  • trySend/tryRecv stay non-blocking.
  • Existing callsites that used send/recv as statements continue to compile; return values are now available for timeout/stop outcomes.
  • recv()/recvIso() value-returning forms now raise "channel stopped" if they cannot receive due to stop.
  • Final-destroy path drains remaining queued elements in-place (=destroy on slot storage).

Tests

Added: tests/tchannels_stop_timeout.nim

Covers:

  • stop unblocks blocked recv
  • stop unblocks blocked send
  • recv timeout behavior
  • send timeout behavior
  • destroy-time draining of pending items

Also validated existing channel tests still pass:

  • tests/tchannels_simple.nim
  • tests/tchannels_singlebuf.nim
  • tests/tchannels_cooperative.nim

Risk / compatibility

  • Main API change is that blocking send/recv now return bool.
  • This is source-compatible for existing statement-style usage and adds explicit failure signaling for stop/timeout paths.
  • Timeout implementation uses periodic polling (sleep(1ms)) because locks condvars in this runtime do not expose timed wait primitives.

Added stop token functionality to ChannelRaw for better control over channel state. Updated channelSend and channelReceive to handle timeout and stop conditions.
Add tests for channel stop behavior and timeouts.
@planetis-m
Copy link
Contributor Author

Ready I think.

@planetis-m
Copy link
Contributor Author

planetis-m commented Feb 20, 2026

I use this implementation in my app: https://github.com/planetis-m/pdfocr
so it is currently being evaluated. The API additions allowed me to simplify communication between threads. For example, under fatal or stop conditions, I no longer need to drain the channels. There’s no need to add sentinel values. The only timeouts are not used.

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