input/thread: use C++ exceptions instead of class Error

This commit is contained in:
Max Kellermann 2016-09-16 17:20:55 +02:00
parent 3cd07d0b54
commit 597e59f10d
3 changed files with 38 additions and 37 deletions

View File

@ -64,7 +64,10 @@ ThreadInputStream::ThreadFunc()
const ScopeLock lock(mutex);
if (!Open(postponed_error)) {
try {
Open();
} catch (...) {
postponed_exception = std::current_exception();
cond.broadcast();
return;
}
@ -73,25 +76,27 @@ ThreadInputStream::ThreadFunc()
SetReady();
while (!close) {
assert(!postponed_error.IsDefined());
assert(!postponed_exception);
auto w = buffer->Write();
if (w.IsEmpty()) {
wake_cond.wait(mutex);
} else {
Error error;
size_t nbytes;
{
try {
const ScopeUnlock unlock(mutex);
nbytes = ThreadRead(w.data, w.size, error);
nbytes = ThreadRead(w.data, w.size);
} catch (...) {
postponed_exception = std::current_exception();
cond.broadcast();
break;
}
cond.broadcast();
if (nbytes == 0) {
eof = true;
postponed_error = std::move(error);
break;
}
@ -110,14 +115,12 @@ ThreadInputStream::ThreadFunc(void *ctx)
}
bool
ThreadInputStream::Check(Error &error)
ThreadInputStream::Check(Error &)
{
assert(!thread.IsInside());
if (postponed_error.IsDefined()) {
error = std::move(postponed_error);
return false;
}
if (postponed_exception)
std::rethrow_exception(postponed_exception);
return true;
}
@ -127,19 +130,17 @@ ThreadInputStream::IsAvailable()
{
assert(!thread.IsInside());
return !buffer->IsEmpty() || eof || postponed_error.IsDefined();
return !buffer->IsEmpty() || eof || postponed_exception;
}
inline size_t
ThreadInputStream::Read(void *ptr, size_t read_size, Error &error)
ThreadInputStream::Read(void *ptr, size_t read_size, Error &)
{
assert(!thread.IsInside());
while (true) {
if (postponed_error.IsDefined()) {
error = std::move(postponed_error);
return 0;
}
if (postponed_exception)
std::rethrow_exception(postponed_exception);
auto r = buffer->Read();
if (!r.IsEmpty()) {

View File

@ -24,7 +24,8 @@
#include "InputStream.hxx"
#include "thread/Thread.hxx"
#include "thread/Cond.hxx"
#include "util/Error.hxx"
#include <exception>
#include <stdint.h>
@ -51,7 +52,7 @@ class ThreadInputStream : public InputStream {
*/
Cond wake_cond;
Error postponed_error;
std::exception_ptr postponed_exception;
const size_t buffer_size;
CircularBuffer<uint8_t> *buffer = nullptr;
@ -103,9 +104,10 @@ protected:
*
* The #InputStream is locked. Unlock/relock it if you do a
* blocking operation.
*
* Throws std::runtime_error on error.
*/
virtual bool Open(gcc_unused Error &error) {
return true;
virtual void Open() {
}
/**
@ -113,9 +115,11 @@ protected:
*
* The #InputStream is not locked.
*
* @return 0 on end-of-file or on error
* Throws std::runtime_error on error.
*
* @return 0 on end-of-file
*/
virtual size_t ThreadRead(void *ptr, size_t size, Error &error) = 0;
virtual size_t ThreadRead(void *ptr, size_t size) = 0;
/**
* Optional deinitialization before leaving the thread.

View File

@ -21,12 +21,13 @@
#include "MmsInputPlugin.hxx"
#include "input/ThreadInputStream.hxx"
#include "input/InputPlugin.hxx"
#include "system/Error.hxx"
#include "util/StringCompare.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <libmms/mmsx.h>
#include <stdexcept>
static constexpr size_t MMS_BUFFER_SIZE = 256 * 1024;
class MmsInputStream final : public ThreadInputStream {
@ -39,27 +40,23 @@ public:
}
protected:
virtual bool Open(gcc_unused Error &error) override;
virtual size_t ThreadRead(void *ptr, size_t size,
Error &error) override;
virtual void Open() override;
virtual size_t ThreadRead(void *ptr, size_t size) override;
void Close() override {
mmsx_close(mms);
}
};
static constexpr Domain mms_domain("mms");
bool
MmsInputStream::Open(Error &error)
void
MmsInputStream::Open()
{
Unlock();
mms = mmsx_connect(nullptr, nullptr, GetURI(), 128 * 1024);
if (mms == nullptr) {
Lock();
error.Set(mms_domain, "mmsx_connect() failed");
return false;
throw std::runtime_error("mmsx_connect() failed");
}
Lock();
@ -67,7 +64,6 @@ MmsInputStream::Open(Error &error)
/* TODO: is this correct? at least this selects the ffmpeg
decoder, which seems to work fine */
SetMimeType("audio/x-ms-wma");
return true;
}
static InputStream *
@ -86,7 +82,7 @@ input_mms_open(const char *url,
}
size_t
MmsInputStream::ThreadRead(void *ptr, size_t read_size, Error &error)
MmsInputStream::ThreadRead(void *ptr, size_t read_size)
{
/* unfortunately, mmsx_read() blocks until the whole buffer
has been filled; to avoid big latencies, limit the size of
@ -98,7 +94,7 @@ MmsInputStream::ThreadRead(void *ptr, size_t read_size, Error &error)
int nbytes = mmsx_read(nullptr, mms, (char *)ptr, read_size);
if (nbytes <= 0) {
if (nbytes < 0)
error.SetErrno("mmsx_read() failed");
throw MakeErrno("mmsx_read() failed");
return 0;
}