Crossbeam_channel try_send into bounded(0) queue

Here's a cute little behavior. I want one thread (my render loop) to trigger another thread that runs in parallel with the render thread. The other thread is faster and should always finish before the render thread gets around the loop. I want to check that it does. (Use case: render thread is drawing, other thread is updating the positions of moving objects for the next frame.)

So I have a crossbeam_channel bounded(0) queue. The receiving thread is usually blocked on a recv, because it's fast, and a try_send on the send end starts it off. This works fine.

As a check, I check the status from the try_send. If it reports Full, I thought that meant the receiving thread hadn't made it back to the receive yet. But I looked at this with the Tracy profiler, and it does make it back with plenty of time to spare.

Turns out that the semantics of try_send are not quite what I'd expected for this case.
I thought that if a "try_send" reported Full, a send would block. No, try_send sends, never blocks, and always reports FULL on a queue of bounded(0).

Github Copilot gives me the right answer, with the query

crossbeam_channel bounded(0) try_send

Even if the receiver is blocked on recv(), try_send still fails because it does not wait for the rendezvous.

That seems to be correct. Then Github Copilot goes on, in typical LLM fashion:

To send successfully on a bounded(0) channel you must use send, not try_send, because send blocks until the receiver is ready.

That seems to be sort of wrong. try_send will do the send, and the recv wakes up, but the status returned by try_send is always FULL, whether or not the send occurred. Which is kind of bogus behavior.

I don't see how the code for try_send can ever both send and return FULL.

I'm missing something here.

no it cannot. otherwise, you'd be able to clone an arbitrary type T, one value is sent to the receiver, another one is returned in the full error.

whatever actually happened in your application, it is not this. I think what you have observed is not what you thought you were trying to observe.

I think you're right.

I tried the example suggested by Github Copilot:

It doesn't do what Copilot says it would. Note the comment

// Now try_send again — this still fails because try_send is non-blocking.

Then run the Playground. It doesn't fail where the comment says it should.

I'm using crossbeam-channel 0.5.10, while current is 0.5.15, but I looked at the Github and that's not it.

More later.

Found it. Crossbeam channel try send to bounded(0) is working properly. Github Copilot is wrong. My code is detecting an error because there's a startup transient which causes a lock to be held for 500ms, instead of the usual few microseconds, resulting in an internal stall.