player/Control: convert error from Error to std::exception_ptr
Prepare full C++ exception support in the player thread.
This commit is contained in:
		| @@ -32,6 +32,7 @@ | ||||
| #include "AudioFormat.hxx" | ||||
| #include "ReplayGainConfig.hxx" | ||||
| #include "util/ScopeExit.hxx" | ||||
| #include "util/Error.hxx" | ||||
|  | ||||
| #ifdef ENABLE_DATABASE | ||||
| #include "db/update/Service.hxx" | ||||
| @@ -191,10 +192,15 @@ handle_status(Client &client, gcc_unused Request args, Response &r) | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	Error error = client.player_control.LockGetError(); | ||||
| 	if (error.IsDefined()) | ||||
| 		r.Format(COMMAND_STATUS_ERROR ": %s\n", | ||||
| 			 error.GetMessage()); | ||||
| 	try { | ||||
| 		client.player_control.LockCheckRethrowError(); | ||||
| 	} catch (const std::exception &e) { | ||||
| 		r.Format(COMMAND_STATUS_ERROR ": %s\n", e.what()); | ||||
| 	} catch (const Error &error) { | ||||
| 		r.Format(COMMAND_STATUS_ERROR ": %s\n", error.GetMessage()); | ||||
| 	} catch (...) { | ||||
| 		r.Format(COMMAND_STATUS_ERROR ": unknown\n"); | ||||
| 	} | ||||
|  | ||||
| 	song = playlist.GetNextPosition(); | ||||
| 	if (song >= 0) | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "Control.hxx" | ||||
| #include "Idle.hxx" | ||||
| #include "DetachedSong.hxx" | ||||
| #include "util/Error.hxx" | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @@ -160,14 +161,23 @@ PlayerControl::LockGetStatus() | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| void | ||||
| PlayerControl::SetError(PlayerError type, std::exception_ptr &&_error) | ||||
| { | ||||
| 	assert(type != PlayerError::NONE); | ||||
| 	assert(_error); | ||||
|  | ||||
| 	error_type = type; | ||||
| 	error = std::move(_error); | ||||
| } | ||||
|  | ||||
| void | ||||
| PlayerControl::SetError(PlayerError type, Error &&_error) | ||||
| { | ||||
| 	assert(type != PlayerError::NONE); | ||||
| 	assert(_error.IsDefined()); | ||||
|  | ||||
| 	error_type = type; | ||||
| 	error = std::move(_error); | ||||
| 	SetError(type, std::make_exception_ptr(std::move(_error))); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -223,11 +233,11 @@ PlayerControl::SeekLocked(DetachedSong *song, SongTime t) | ||||
| 	assert(next_song == nullptr); | ||||
|  | ||||
| 	if (error_type != PlayerError::NONE) { | ||||
| 		assert(error.IsDefined()); | ||||
| 		throw error; | ||||
| 		assert(error); | ||||
| 		std::rethrow_exception(error); | ||||
| 	} | ||||
|  | ||||
| 	assert(!error.IsDefined()); | ||||
| 	assert(!error); | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
| @@ -24,12 +24,14 @@ | ||||
| #include "thread/Mutex.hxx" | ||||
| #include "thread/Cond.hxx" | ||||
| #include "thread/Thread.hxx" | ||||
| #include "util/Error.hxx" | ||||
| #include "CrossFade.hxx" | ||||
| #include "Chrono.hxx" | ||||
|  | ||||
| #include <exception> | ||||
|  | ||||
| #include <stdint.h> | ||||
|  | ||||
| class Error; | ||||
| class PlayerListener; | ||||
| class MultipleOutputs; | ||||
| class DetachedSong; | ||||
| @@ -135,7 +137,7 @@ struct PlayerControl { | ||||
| 	 * #PlayerError::NONE.  The object must be freed when this | ||||
| 	 * object transitions back to #PlayerError::NONE. | ||||
| 	 */ | ||||
| 	Error error; | ||||
| 	std::exception_ptr error; | ||||
|  | ||||
| 	/** | ||||
| 	 * A copy of the current #DetachedSong after its tags have | ||||
| @@ -327,7 +329,7 @@ private: | ||||
|  | ||||
| 	void ClearError() { | ||||
| 		error_type = PlayerError::NONE; | ||||
| 		error.Clear(); | ||||
| 		error = std::exception_ptr(); | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| @@ -356,28 +358,25 @@ public: | ||||
| 	 * @param error detailed error information; must be defined. | ||||
| 	 */ | ||||
| 	void SetError(PlayerError type, Error &&error); | ||||
| 	void SetError(PlayerError type, std::exception_ptr &&_error); | ||||
|  | ||||
| 	/** | ||||
| 	 * Checks whether an error has occurred, and if so, returns a | ||||
| 	 * copy of the #Error object. | ||||
| 	 * Checks whether an error has occurred, and if so, rethrows | ||||
| 	 * it. | ||||
| 	 * | ||||
| 	 * Caller must lock the object. | ||||
| 	 */ | ||||
| 	gcc_pure | ||||
| 	Error GetError() const { | ||||
| 		Error result; | ||||
| 	void CheckRethrowError() const { | ||||
| 		if (error_type != PlayerError::NONE) | ||||
| 			result.Set(error); | ||||
| 		return result; | ||||
| 			std::rethrow_exception(error); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Like GetError(), but locks and unlocks the object. | ||||
| 	 * Like CheckRethrowError(), but locks and unlocks the object. | ||||
| 	 */ | ||||
| 	gcc_pure | ||||
| 	Error LockGetError() const { | ||||
| 	void LockCheckRethrowError() const { | ||||
| 		const ScopeLock protect(mutex); | ||||
| 		return GetError(); | ||||
| 		CheckRethrowError(); | ||||
| 	} | ||||
|  | ||||
| 	void LockClearError(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann