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

v0.2.0-rc Async Close Not Waking #29

Closed
Congyuwang opened this issue Jul 28, 2023 · 4 comments
Closed

v0.2.0-rc Async Close Not Waking #29

Congyuwang opened this issue Jul 28, 2023 · 4 comments

Comments

@Congyuwang
Copy link
Contributor

Seems like the master branch async ringbuf is not yet complete? There is an async index.rs file not yet included in lib.rs.

Currently, the close() of AsyncProd and AsyncCons does not call wake() which can cause some problem. I see that close() of AsyncIndex calls wake().

The v0.1.3 Async-Ringbuf also wakes the other on close().

When will this be implemented?

@Congyuwang
Copy link
Contributor Author

My branch migrating from v0.1.3 to v0.2.0-rc.0 has shows some performance bug and occasion lock because the producer close() does not wake the consumer.

@Congyuwang
Copy link
Contributor Author

Congyuwang commented Jul 28, 2023

Looks like close on drop is implemented for AsyncProd, and AsyncCons

ringbuf/async/src/halves.rs

Lines 196 to 211 in 45cc3a8

impl<R: RbRef> Drop for AsyncProd<R>
where
R::Target: AsyncRingBuffer,
{
fn drop(&mut self) {
self.close()
}
}
impl<R: RbRef> Drop for AsyncCons<R>
where
R::Target: AsyncRingBuffer,
{
fn drop(&mut self) {
self.close()
}
}

But that close is REALLY DIFFICULT to find:

<AsyncProd<Arc<AsyncHeapRb<T>>> as AsyncObserver >::close is defined as self.base.rb().close(), which is <Arc<AsyncHeapRb<T>> as AsyncRingBuffer>::close() where AsyncHeapRb is an alias AsyncRb<Heap<T>>.

Now, AsyncRingBuffer = RingBuffer + AsyncProducer + AsyncConsumer, and AsyncProducer = AsyncObserver + Producer, and AsyncConsumer = AsyncObserver + Consumer, and RingBuffer = Observer + Consumer + Producer.
Therefore, AsyncRingBuffer = AsyncObserver + Observer + Producer + Consumer. I find this clearer without so many redirections. So, where is close? Looks like close is only implemented in AsyncObserver, which AsyncRb<Heap<T>> has a definition below:

ringbuf/async/src/rb.rs

Lines 66 to 73 in 45cc3a8

impl<S: Storage> AsyncObserver for AsyncRb<S> {
fn is_closed(&self) -> bool {
self.closed.load(Ordering::Relaxed)
}
fn close(&self) {
self.closed.store(true, Ordering::Relaxed);
}
}

Therefore:

  • <AsyncProd<Arc<AsyncRb<Heap<T>>>> as AsyncObserver >::close => <AsyncRb<Heap<T>> as AsyncObserver >::close
  • <AsyncCons<Arc<AsyncRb<Heap<T>>>> as AsyncObserver >::close => <AsyncRb<Heap<T>> as AsyncObserver >::close

So basically AsyncProd, AsyncCons and AsyncRb has the exact same underlying implementation of AsyncObserver, which is implemented for AsyncRb, which has two wakers read and write, but it does not know which waker should it call.

@Congyuwang
Copy link
Contributor Author

#30

@agerasev
Copy link
Owner

Thank you for reporting the issue and investigation you made!

Seems like the master branch async ringbuf is not yet complete?

It was planned to be final version but I've decided to not to release it yet to give some time to reveal possible bugs (like this one).

There is an async index.rs file not yet included in lib.rs.

index.rs is a remnant of previous iteration of rewriting the library, it needs to be removed. Thanks for noticing!

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