output/wasapi: implement Cancel() properly
Calling consume_all() is illegal in the producer thread.
This commit is contained in:
parent
8a045207a7
commit
1fe0c673bc
|
@ -170,7 +170,10 @@ class WasapiOutputThread {
|
||||||
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
|
|
||||||
|
std::atomic_bool cancel = false;
|
||||||
|
|
||||||
enum class Status : uint32_t { FINISH, PLAY, PAUSE };
|
enum class Status : uint32_t { FINISH, PLAY, PAUSE };
|
||||||
|
|
||||||
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) std::atomic<Status> status =
|
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) std::atomic<Status> status =
|
||||||
Status::PAUSE;
|
Status::PAUSE;
|
||||||
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) struct {
|
alignas(BOOST_LOCKFREE_CACHELINE_BYTES) struct {
|
||||||
|
@ -201,6 +204,24 @@ public:
|
||||||
void Play() noexcept { return SetStatus(Status::PLAY); }
|
void Play() noexcept { return SetStatus(Status::PLAY); }
|
||||||
void Pause() noexcept { return SetStatus(Status::PAUSE); }
|
void Pause() noexcept { return SetStatus(Status::PAUSE); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the thread to discard the buffer (and wait for
|
||||||
|
* completion). This needs to be done inside this thread,
|
||||||
|
* because only the consumer thread is allowed to do that.
|
||||||
|
*/
|
||||||
|
void Cancel() noexcept {
|
||||||
|
cancel.store(true);
|
||||||
|
event.Set();
|
||||||
|
|
||||||
|
while (cancel.load() && !error.occur.load())
|
||||||
|
Wait();
|
||||||
|
|
||||||
|
/* not rethrowing the exception here via
|
||||||
|
CheckException() because this method must be
|
||||||
|
"noexcept"; the next WasapiOutput::Play() call will
|
||||||
|
throw */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for the thread to finish some work (e.g. until some
|
* Wait for the thread to finish some work (e.g. until some
|
||||||
* buffer space becomes available).
|
* buffer space becomes available).
|
||||||
|
@ -366,6 +387,12 @@ try {
|
||||||
while (true) {
|
while (true) {
|
||||||
event.Wait();
|
event.Wait();
|
||||||
|
|
||||||
|
if (cancel.load()) {
|
||||||
|
spsc_buffer.consume_all([](auto &&) {});
|
||||||
|
cancel.store(false);
|
||||||
|
InterruptWaiter();
|
||||||
|
}
|
||||||
|
|
||||||
Status current_state = status.load();
|
Status current_state = status.load();
|
||||||
switch (current_state) {
|
switch (current_state) {
|
||||||
case Status::FINISH:
|
case Status::FINISH:
|
||||||
|
@ -707,7 +734,7 @@ WasapiOutput::Cancel() noexcept
|
||||||
{
|
{
|
||||||
assert(thread);
|
assert(thread);
|
||||||
|
|
||||||
thread->spsc_buffer.consume_all([](auto &&) {});
|
thread->Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// run inside COMWorkerThread
|
/// run inside COMWorkerThread
|
||||||
|
|
Loading…
Reference in New Issue