decoder/Control: convert error from Error to std::exception_ptr
Prepare full C++ exception support in the decoder thread.
This commit is contained in:
parent
0ce72cbf9d
commit
308010794a
@ -22,6 +22,7 @@
|
|||||||
#include "DecoderError.hxx"
|
#include "DecoderError.hxx"
|
||||||
#include "MusicPipe.hxx"
|
#include "MusicPipe.hxx"
|
||||||
#include "DetachedSong.hxx"
|
#include "DetachedSong.hxx"
|
||||||
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
#include "thread/Cond.hxx"
|
#include "thread/Cond.hxx"
|
||||||
#include "thread/Thread.hxx"
|
#include "thread/Thread.hxx"
|
||||||
#include "Chrono.hxx"
|
#include "Chrono.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#undef ERROR
|
#undef ERROR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class Error;
|
||||||
class DetachedSong;
|
class DetachedSong;
|
||||||
class MusicBuffer;
|
class MusicBuffer;
|
||||||
class MusicPipe;
|
class MusicPipe;
|
||||||
@ -97,7 +99,7 @@ struct DecoderControl {
|
|||||||
* The object must be freed when this object transitions to
|
* The object must be freed when this object transitions to
|
||||||
* any other state (usually #DecoderState::START).
|
* any other state (usually #DecoderState::START).
|
||||||
*/
|
*/
|
||||||
Error error;
|
std::exception_ptr error;
|
||||||
|
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
||||||
@ -242,29 +244,25 @@ struct DecoderControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an error has occurred, and if so, returns a
|
* Checks whether an error has occurred, and if so, rethrows
|
||||||
* copy of the #Error object.
|
* it.
|
||||||
*
|
*
|
||||||
* Caller must lock the object.
|
* Caller must lock the object.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
void CheckRethrowError() const {
|
||||||
Error GetError() const {
|
|
||||||
assert(command == DecoderCommand::NONE);
|
assert(command == DecoderCommand::NONE);
|
||||||
assert(state != DecoderState::ERROR || error.IsDefined());
|
assert(state != DecoderState::ERROR || error);
|
||||||
|
|
||||||
Error result;
|
|
||||||
if (state == DecoderState::ERROR)
|
if (state == DecoderState::ERROR)
|
||||||
result.Set(error);
|
std::rethrow_exception(error);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like GetError(), but locks and unlocks the object.
|
* Like CheckRethrowError(), but locks and unlocks the object.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
void LockCheckRethrowError() const {
|
||||||
Error LockGetError() const {
|
|
||||||
const ScopeLock protect(mutex);
|
const ScopeLock protect(mutex);
|
||||||
return GetError();
|
CheckRethrowError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,7 +272,7 @@ struct DecoderControl {
|
|||||||
*/
|
*/
|
||||||
void ClearError() {
|
void ClearError() {
|
||||||
if (state == DecoderState::ERROR) {
|
if (state == DecoderState::ERROR) {
|
||||||
error.Clear();
|
error = std::exception_ptr();
|
||||||
state = DecoderState::STOP;
|
state = DecoderState::STOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "util/MimeType.hxx"
|
#include "util/MimeType.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "thread/Name.hxx"
|
#include "thread/Name.hxx"
|
||||||
#include "tag/ApeReplayGain.hxx"
|
#include "tag/ApeReplayGain.hxx"
|
||||||
@ -415,7 +416,7 @@ decoder_run_song(DecoderControl &dc,
|
|||||||
/* copy the Error from struct Decoder to
|
/* copy the Error from struct Decoder to
|
||||||
DecoderControl */
|
DecoderControl */
|
||||||
dc.state = DecoderState::ERROR;
|
dc.state = DecoderState::ERROR;
|
||||||
dc.error = std::move(decoder.error);
|
dc.error = std::make_exception_ptr(std::move(decoder.error));
|
||||||
} else if (success)
|
} else if (success)
|
||||||
dc.state = DecoderState::STOP;
|
dc.state = DecoderState::STOP;
|
||||||
else {
|
else {
|
||||||
@ -426,8 +427,7 @@ decoder_run_song(DecoderControl &dc,
|
|||||||
if (!allocated.empty())
|
if (!allocated.empty())
|
||||||
error_uri = allocated.c_str();
|
error_uri = allocated.c_str();
|
||||||
|
|
||||||
dc.error.Format(decoder_domain,
|
dc.error = std::make_exception_ptr(FormatRuntimeError("Failed to decode %s", error_uri));
|
||||||
"Failed to decode %s", error_uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.client_cond.signal();
|
dc.client_cond.signal();
|
||||||
@ -450,9 +450,11 @@ decoder_run(DecoderControl &dc)
|
|||||||
Path path_fs = Path::Null();
|
Path path_fs = Path::Null();
|
||||||
AllocatedPath path_buffer = AllocatedPath::Null();
|
AllocatedPath path_buffer = AllocatedPath::Null();
|
||||||
if (PathTraitsUTF8::IsAbsolute(uri_utf8)) {
|
if (PathTraitsUTF8::IsAbsolute(uri_utf8)) {
|
||||||
path_buffer = AllocatedPath::FromUTF8(uri_utf8, dc.error);
|
Error error;
|
||||||
|
path_buffer = AllocatedPath::FromUTF8(uri_utf8, error);
|
||||||
if (path_buffer.IsNull()) {
|
if (path_buffer.IsNull()) {
|
||||||
dc.state = DecoderState::ERROR;
|
dc.state = DecoderState::ERROR;
|
||||||
|
dc.error = std::make_exception_ptr(std::move(error));
|
||||||
dc.CommandFinishedLocked();
|
dc.CommandFinishedLocked();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -485,8 +487,16 @@ decoder_task(void *arg)
|
|||||||
|
|
||||||
decoder_run(dc);
|
decoder_run(dc);
|
||||||
|
|
||||||
if (dc.state == DecoderState::ERROR)
|
if (dc.state == DecoderState::ERROR) {
|
||||||
LogError(dc.error);
|
try {
|
||||||
|
std::rethrow_exception(dc.error);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
} catch (const Error &error) {
|
||||||
|
LogError(error);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
#include "util/Error.hxx"
|
||||||
#include "thread/Name.hxx"
|
#include "thread/Name.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -372,9 +373,10 @@ Player::StopDecoder()
|
|||||||
bool
|
bool
|
||||||
Player::ForwardDecoderError()
|
Player::ForwardDecoderError()
|
||||||
{
|
{
|
||||||
Error error = dc.GetError();
|
try {
|
||||||
if (error.IsDefined()) {
|
dc.CheckRethrowError();
|
||||||
pc.SetError(PlayerError::DECODER, std::move(error));
|
} catch (...) {
|
||||||
|
pc.SetError(PlayerError::DECODER, std::current_exception());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user