src/output: Use WinEvent for as a condition_variable without lock
This commit is contained in:
parent
db7caa2dac
commit
844dbd2ec5
|
@ -129,15 +129,11 @@ public:
|
|||
void Finish() noexcept { return SetStatus(Status::FINISH); }
|
||||
void Play() noexcept { return SetStatus(Status::PLAY); }
|
||||
void Pause() noexcept { return SetStatus(Status::PAUSE); }
|
||||
void WaitWrite() noexcept {
|
||||
std::unique_lock<Mutex> lock(write.mutex);
|
||||
write.cond.wait(lock);
|
||||
}
|
||||
void WaitDataPoped() noexcept { data_poped.Wait(200); }
|
||||
void CheckException() {
|
||||
std::unique_lock<Mutex> lock(error.mutex);
|
||||
if (error.error_ptr) {
|
||||
std::exception_ptr err = std::exchange(error.error_ptr, nullptr);
|
||||
error.cond.notify_all();
|
||||
if (error.occur.load()) {
|
||||
auto err = std::exchange(error.ptr, nullptr);
|
||||
error.thrown.Set();
|
||||
std::rethrow_exception(err);
|
||||
}
|
||||
}
|
||||
|
@ -145,6 +141,7 @@ public:
|
|||
private:
|
||||
friend class WasapiOutput;
|
||||
WinEvent event;
|
||||
WinEvent data_poped;
|
||||
IAudioClient *client;
|
||||
ComPtr<IAudioRenderClient> render_client;
|
||||
const UINT32 frame_size;
|
||||
|
@ -153,14 +150,10 @@ private:
|
|||
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) std::atomic<Status> status =
|
||||
Status::PAUSE;
|
||||
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) struct {
|
||||
Mutex mutex;
|
||||
Cond cond;
|
||||
} write{};
|
||||
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) struct {
|
||||
Mutex mutex;
|
||||
Cond cond;
|
||||
std::exception_ptr error_ptr = nullptr;
|
||||
} error{};
|
||||
std::atomic_bool occur = false;
|
||||
std::exception_ptr ptr = nullptr;
|
||||
WinEvent thrown;
|
||||
} error;
|
||||
boost::lockfree::spsc_queue<BYTE> spsc_buffer;
|
||||
|
||||
void SetStatus(Status s) noexcept {
|
||||
|
@ -255,8 +248,6 @@ void WasapiOutputThread::Work() noexcept {
|
|||
return;
|
||||
}
|
||||
|
||||
AtScopeExit(&) { write.cond.notify_all(); };
|
||||
|
||||
HRESULT result;
|
||||
UINT32 data_in_frames;
|
||||
result = client->GetCurrentPadding(&data_in_frames);
|
||||
|
@ -293,16 +284,16 @@ void WasapiOutputThread::Work() noexcept {
|
|||
new_data_size = spsc_buffer.pop(data, write_size);
|
||||
std::fill_n(data + new_data_size,
|
||||
write_size - new_data_size, 0);
|
||||
data_poped.Set();
|
||||
} else {
|
||||
mode = AUDCLNT_BUFFERFLAGS_SILENT;
|
||||
FormatDebug(wasapi_output_domain,
|
||||
"Working thread paused");
|
||||
}
|
||||
} catch (...) {
|
||||
std::unique_lock<Mutex> lock(error.mutex);
|
||||
error.error_ptr = std::current_exception();
|
||||
error.cond.wait(lock);
|
||||
assert(error.error_ptr == nullptr);
|
||||
error.ptr = std::current_exception();
|
||||
error.occur.store(true);
|
||||
error.thrown.Wait(INFINITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +482,7 @@ size_t WasapiOutput::Play(const void *chunk, size_t size) {
|
|||
thread->spsc_buffer.push(static_cast<const BYTE *>(chunk), size);
|
||||
if (consumed_size == 0) {
|
||||
assert(is_started);
|
||||
thread->WaitWrite();
|
||||
thread->WaitDataPoped();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue