Skip to content

Split channel into sender/receiver - #88

Open
arnetheduck wants to merge 2 commits into
nim-lang:masterfrom
arnetheduck:txrx
Open

arnetheduck wants to merge 2 commits into
nim-lang:masterfrom
arnetheduck:txrx

Conversation

@arnetheduck

Copy link
Copy Markdown

By separating the handles responsible for the two sides of a channel, we get to support an intuitive api for closing channels that is safe by construction, ie there's no risk that senders write into a channel closed for sending and vice versa.

Both receivers and senders can be copied and moved around so that they can each be shared by multiple threads.

The principle of operation is simple:

  • senders and receivers have separate refcounts on the raw channel
  • with all senders gone, it means no more items will be pushed to the channel - all queued receivers are woken up and told it's over (once they've drained the channel)
  • with all receivers gone, it means no more messages can be pushed into the channel - we can free the buffer and sending becomes a no-op
  • with both gone, we release the channel resources.

On the sending side, we return a bool for "no more receivers" - on the receiving side, we return default(T) or a bool for the var-taking version - both sides can check if the channel was closed to disambiguate.

@Araq

Araq commented Sep 19, 2026

Copy link
Copy Markdown
Member

I need to fix the CI first, seems ready to go otherwise.

@arnetheduck

Copy link
Copy Markdown
Author

fix the CI first

Well, we can't meaningfully use createShared until 2.2.12 so probably the older versions will have to go away or #77 should be reverted for those version.

when bumping, atomics should probably be removed, but memory ordering is broken and needs fixing before it's meaningful to use.

@arnetheduck
arnetheduck marked this pull request as draft September 20, 2026 20:09
@arnetheduck

Copy link
Copy Markdown
Author

#91 is blocking this for now

By separating the handles responsible for the two sides of a channel, we
get to support an intuitive api for closing channels that is safe by
construction, ie there's no risk that senders write into a channel
closed for sending and vice versa.

Both receivers and senders can be copied and moved around so that they
can each be shared by multiple threads.

The principle of operation is simple:

* senders and receivers have separate refcounts on the raw channel
* with all senders gone, it means no more items will be pushed to the
channel - all queued receivers are woken up and told it's over (once
they've drained the channel)
* with all receivers gone, it means no more messages can be pushed into
the channel - we can free the buffer and sending becomes a no-op
* with both gone, we release the channel resources.

On the sending side, we return a `bool` for "no more receivers" - on the
receiving side, we return `default(T)` or a `bool` for the var-taking
version - both sides can check if the channel was closed to
disambiguate.
@arnetheduck
arnetheduck marked this pull request as ready for review October 19, 2026 07:54
@arnetheduck

Copy link
Copy Markdown
Author

So this is now minimally correct with respect to #91 at least, via a destructor call in the lock - not the best in terms of efficiency, but in line with other inefficiences already present (copying/destroying/etc inside the contended lock).

This branch has not been deployed

No deployments
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.

2 participants