Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync send method #11

Closed
xlc opened this issue Oct 16, 2024 · 9 comments
Closed

sync send method #11

xlc opened this issue Oct 16, 2024 · 9 comments

Comments

@xlc
Copy link
Contributor

xlc commented Oct 16, 2024

Can we have a send method that is not async that only does nonBlockingSend and return false if that failed due to buffer full?

Use case: I am working with a C networking library. When it received data, my callback is called, and I am doing

Task {
    await channel.send(data)
 }

and when the buffer is full, the back pressure essentially goes to the dispatch queue, which is not what I wanted. If there is a sync send that fails when buffer is full, then I can tell the networking library to close the connection and notify upstream.

I noted there is a count method so I can inspect it and implements the back pressure correctly, but still with async send, there is still some unnecessary overheads.

I can make a PR if needed.

@gh123man
Copy link
Owner

Hey, thanks for reaching out!

You can get the same effect as non blocking send by using select:

Task {
    await select {
        send("b", to: b)
        none { // called if send is not ready }
    }
}

In this case, the task will never block waiting to send.
Does this cover your use case? If not I am happy to work together to find the right API.

@xlc
Copy link
Contributor Author

xlc commented Oct 16, 2024

Unfortunately I am dealing with C callback here so no async/await allowed. I would like to return an error code when buffer is already full from the callback, which will indicate the library the data is not processed.

@gh123man
Copy link
Owner

Unfortunately I am dealing with C callback here so no async/await allowed.

Given the existing solution you shared - are you able to call that code? Since it also includes an async function as well wrapped in a task.

Conceptually you could also do this:

if channel.count < maxSize {
     Task {
        await channel.send(data)
     }
} else {
    // channel full
}

This would generally prevent you from stacking back pressure on the dispatch queue (assuming there are not competing threads writing to the channel).

@xlc
Copy link
Contributor Author

xlc commented Oct 16, 2024

Yes that will work. In my case there is only a singe writer and single reader. But I still think a sync API will be nice. For example, send in Rust channel is sync: https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html#method.send

@gh123man
Copy link
Owner

In my case there is only a singe writer and single reader. But I still think a sync API will be nice. For example, send in Rust channel is sync

Thanks for sharing this. Interesting context.
let me read up on this more and get back to you.

@gh123man
Copy link
Owner

What do you think of something like this: #19

@xlc
Copy link
Contributor Author

xlc commented Oct 18, 2024

looking good!

@gh123man
Copy link
Owner

Ill cut a new release with this change soon.

@gh123man
Copy link
Owner

Released! Thanks for the input!
https://github.com/gh123man/Async-Channels/releases/tag/1.0.2

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

No branches or pull requests

2 participants