input/{async,thread}: add an additional Cond field

This eliminates the ScopeExchangeInputStreamHandler kludge.
This commit is contained in:
Max Kellermann 2024-07-29 23:10:46 +02:00
parent cf962d94c7
commit b050e0132e
4 changed files with 25 additions and 17 deletions

View File

@ -2,9 +2,7 @@
// Copyright The Music Player Daemon Project
#include "AsyncInputStream.hxx"
#include "CondHandler.hxx"
#include "tag/Tag.hxx"
#include "thread/Cond.hxx"
#include "event/Loop.hxx"
#include <cassert>
@ -126,10 +124,7 @@ AsyncInputStream::Seek(std::unique_lock<Mutex> &lock,
deferred_seek.Schedule();
CondInputStreamHandler cond_handler;
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
cond_handler.cond.wait(lock,
[this]{ return seek_state == SeekState::NONE; });
caller_cond.wait(lock, [this]{ return seek_state == SeekState::NONE; });
Check();
}
@ -146,6 +141,7 @@ AsyncInputStream::SeekDone() noexcept
open = true;
seek_state = SeekState::NONE;
caller_cond.notify_one();
InvokeOnAvailable();
}
@ -169,8 +165,6 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
{
assert(!GetEventLoop().IsInside());
CondInputStreamHandler cond_handler;
/* wait for data */
CircularBuffer<std::byte>::Range r;
while (true) {
@ -180,8 +174,7 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
if (!r.empty() || IsEOF())
break;
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
cond_handler.cond.wait(lock);
caller_cond.wait(lock);
}
const size_t nbytes = std::min(dest.size(), r.size());
@ -203,8 +196,10 @@ AsyncInputStream::CommitWriteBuffer(size_t nbytes) noexcept
if (!IsReady())
SetReady();
else
else {
caller_cond.notify_one();
InvokeOnAvailable();
}
}
void
@ -234,8 +229,10 @@ AsyncInputStream::AppendToBuffer(std::span<const std::byte> src) noexcept
if (!IsReady())
SetReady();
else
else {
caller_cond.notify_one();
InvokeOnAvailable();
}
}
void
@ -247,6 +244,7 @@ AsyncInputStream::DeferredResume() noexcept
Resume();
} catch (...) {
postponed_exception = std::current_exception();
caller_cond.notify_one();
InvokeOnAvailable();
}
}
@ -269,6 +267,7 @@ AsyncInputStream::DeferredSeek() noexcept
} catch (...) {
seek_state = SeekState::NONE;
postponed_exception = std::current_exception();
caller_cond.notify_one();
InvokeOnAvailable();
}
}

View File

@ -4,6 +4,7 @@
#pragma once
#include "InputStream.hxx"
#include "thread/Cond.hxx"
#include "event/InjectEvent.hxx"
#include "util/HugeAllocator.hxx"
#include "util/CircularBuffer.hxx"
@ -21,6 +22,11 @@ class AsyncInputStream : public InputStream {
InjectEvent deferred_resume;
InjectEvent deferred_seek;
/**
* Signalled when the caller shall be woken up.
*/
Cond caller_cond;
HugeArray<std::byte> allocation;
CircularBuffer<std::byte> buffer{allocation};

View File

@ -2,7 +2,6 @@
// Copyright The Music Player Daemon Project
#include "ThreadInputStream.hxx"
#include "CondHandler.hxx"
#include "thread/Name.hxx"
#include <cassert>
@ -79,10 +78,12 @@ ThreadInputStream::ThreadFunc() noexcept
nbytes = ThreadRead(w);
} catch (...) {
postponed_exception = std::current_exception();
caller_cond.notify_one();
InvokeOnAvailable();
break;
}
caller_cond.notify_one();
InvokeOnAvailable();
if (nbytes == 0) {
@ -120,8 +121,6 @@ ThreadInputStream::Read(std::unique_lock<Mutex> &lock,
{
assert(!thread.IsInside());
CondInputStreamHandler cond_handler;
while (true) {
if (postponed_exception)
std::rethrow_exception(postponed_exception);
@ -139,8 +138,7 @@ ThreadInputStream::Read(std::unique_lock<Mutex> &lock,
if (eof)
return 0;
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
cond_handler.cond.wait(lock);
caller_cond.wait(lock);
}
}

View File

@ -39,6 +39,11 @@ class ThreadInputStream : public InputStream {
*/
Cond wake_cond;
/**
* Signalled when the caller shall be woken up.
*/
Cond caller_cond;
std::exception_ptr postponed_exception;
HugeArray<std::byte> allocation;