Switch to exception_ptr for async exceptions

This commit is contained in:
badaix 2020-03-12 23:33:10 +01:00
parent 5e508cae2e
commit d49b5c251c
5 changed files with 24 additions and 36 deletions

View file

@ -211,13 +211,10 @@ void ClientConnection::reader()
getNextMessage(); getNextMessage();
} }
} }
catch (const std::exception& e)
{
if (messageReceiver_ != nullptr)
messageReceiver_->onException(this, make_shared<SnapException>(e.what()));
}
catch (...) catch (...)
{ {
if (messageReceiver_ != nullptr)
messageReceiver_->onException(this, std::current_exception());
} }
active_ = false; active_ = false;
} }

View file

@ -78,17 +78,13 @@ private:
}; };
/// would be nicer to use std::exception_ptr
/// but not supported on all plattforms
typedef std::shared_ptr<std::exception> shared_exception_ptr;
/// Interface: callback for a received message and error reporting /// Interface: callback for a received message and error reporting
class MessageReceiver class MessageReceiver
{ {
public: public:
virtual ~MessageReceiver() = default; virtual ~MessageReceiver() = default;
virtual void onMessageReceived(ClientConnection* connection, const msg::BaseMessage& baseMessage, char* buffer) = 0; virtual void onMessageReceived(ClientConnection* connection, const msg::BaseMessage& baseMessage, char* buffer) = 0;
virtual void onException(ClientConnection* connection, shared_exception_ptr exception) = 0; virtual void onException(ClientConnection* connection, std::exception_ptr exception) = 0;
}; };

View file

@ -46,9 +46,9 @@ Controller::Controller(const ClientSettings& settings, std::unique_ptr<MetadataA
} }
void Controller::onException(ClientConnection* /*connection*/, shared_exception_ptr exception) void Controller::onException(ClientConnection* /*connection*/, std::exception_ptr exception)
{ {
LOG(ERROR) << "Controller::onException: " << exception->what() << "\n"; LOG(ERROR) << "Controller::onException\n";
async_exception_ = exception; async_exception_ = exception;
} }
@ -159,16 +159,16 @@ void Controller::onMessageReceived(ClientConnection* /*connection*/, const msg::
} }
} }
if (baseMessage.type != message_type::kTime) // if (baseMessage.type != message_type::kTime)
if (sendTimeSyncMessage(1000)) // if (sendTimeSyncMessage(1000))
LOG(DEBUG) << "time sync onMessageReceived\n"; // LOG(DEBUG) << "time sync onMessageReceived\n";
} }
bool Controller::sendTimeSyncMessage(long after) bool Controller::sendTimeSyncMessage(const std::chrono::milliseconds& after)
{ {
static long lastTimeSync(0); static chronos::time_point_clk lastTimeSync(chronos::clk::now());
long now = chronos::getTickCount(); auto now = chronos::clk::now();
if (lastTimeSync + after > now) if (lastTimeSync + after > now)
return false; return false;
@ -227,8 +227,8 @@ void Controller::worker()
{ {
if (async_exception_) if (async_exception_)
{ {
LOG(DEBUG) << "Async exception: " << async_exception_->what() << "\n"; LOG(DEBUG) << "Async exception\n";
throw SnapException(async_exception_->what()); std::rethrow_exception(async_exception_);
} }
auto reply = clientConnection_->sendReq<msg::Time>(&timeReq, chronos::msec(2000)); auto reply = clientConnection_->sendReq<msg::Time>(&timeReq, chronos::msec(2000));
@ -249,12 +249,12 @@ void Controller::worker()
chronos::sleep(100); chronos::sleep(100);
if (async_exception_) if (async_exception_)
{ {
LOG(DEBUG) << "Async exception: " << async_exception_->what() << "\n"; LOG(DEBUG) << "Async exception\n";
throw SnapException(async_exception_->what()); std::rethrow_exception(async_exception_);
} }
} }
if (sendTimeSyncMessage(5000)) if (sendTimeSyncMessage(1000ms))
LOG(DEBUG) << "time sync main loop\n"; LOG(DEBUG) << "time sync main loop\n";
} }
} }

View file

@ -42,6 +42,7 @@
#include "metadata.hpp" #include "metadata.hpp"
#include "stream.hpp" #include "stream.hpp"
using namespace std::chrono_literals;
/// Forwards PCM data to the audio player /// Forwards PCM data to the audio player
/** /**
@ -64,11 +65,11 @@ public:
/// Implementation of MessageReceiver. /// Implementation of MessageReceiver.
/// Used for async exception reporting /// Used for async exception reporting
void onException(ClientConnection* connection, shared_exception_ptr exception) override; void onException(ClientConnection* connection, std::exception_ptr exception) override;
private: private:
void worker(); void worker();
bool sendTimeSyncMessage(long after = 1000); bool sendTimeSyncMessage(const std::chrono::milliseconds& after = 1000ms);
ClientSettings settings_; ClientSettings settings_;
std::string meta_callback_; std::string meta_callback_;
std::atomic<bool> active_; std::atomic<bool> active_;
@ -83,7 +84,7 @@ private:
std::unique_ptr<msg::CodecHeader> headerChunk_; std::unique_ptr<msg::CodecHeader> headerChunk_;
std::mutex receiveMutex_; std::mutex receiveMutex_;
shared_exception_ptr async_exception_; std::exception_ptr async_exception_;
}; };

View file

@ -117,16 +117,10 @@ void Stream::clearChunks()
void Stream::addChunk(unique_ptr<msg::PcmChunk> chunk) void Stream::addChunk(unique_ptr<msg::PcmChunk> chunk)
{ {
// drop chunks that should have been played 10s before. Just in case, this shouldn't happen. // drop chunk if it's too old. Just in case, this shouldn't happen.
while (!chunks_.empty()) cs::usec age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - chunk->start());
{ if (age > 5s + bufferMs_)
auto first_chunk = chunks_.front(); return;
cs::usec age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - first_chunk->start());
if (age > 10s + bufferMs_)
chunks_.pop();
else
break;
}
// LOG(DEBUG, LOG_TAG) << "new chunk: " << chunk->durationMs() << " ms, Chunks: " << chunks_.size() << "\n"; // LOG(DEBUG, LOG_TAG) << "new chunk: " << chunk->durationMs() << " ms, Chunks: " << chunks_.size() << "\n";