From 60b59524e7a8b44dab94d69b239d67362f3dbb3d Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Tue, 15 Apr 2014 13:14:16 +0200 Subject: [PATCH] when an error is detected on a channel, all subsequent and cached deferred objects are notified about the error too --- include/channelimpl.h | 9 +++++++++ include/connectionhandler.h | 3 +++ src/channelimpl.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/include/channelimpl.h b/include/channelimpl.h index 62cc70d..3d77fc2 100644 --- a/include/channelimpl.h +++ b/include/channelimpl.h @@ -485,6 +485,12 @@ public: if (!next) _newestCallback = nullptr; } + /** + * Report errors to all deferred objects already in an error state + * @param force Report errors even for objects not already in error state + */ + void reportErrors(bool force = false); + /** * Report an error message on a channel * @param message @@ -514,6 +520,9 @@ public: // if there was no next callback, the newest callback was just used if (!next) _newestCallback = nullptr; + + // when one error occured, all subsequent messages are in an error state too + reportErrors(true); } /** diff --git a/include/connectionhandler.h b/include/connectionhandler.h index 220e2dc..0fa28ee 100644 --- a/include/connectionhandler.h +++ b/include/connectionhandler.h @@ -31,6 +31,9 @@ public: * @param connection the connection that needs the timeout * @param timeout number of seconds to wait * @param callback function to execute once time runs out + * + * + * @todo this one should be removed */ virtual void setTimeout(Connection *connection, double seconds, const std::function& callback) {} diff --git a/src/channelimpl.cpp b/src/channelimpl.cpp index a3cc37e..27c1bea 100644 --- a/src/channelimpl.cpp +++ b/src/channelimpl.cpp @@ -121,6 +121,32 @@ Deferred &ChannelImpl::push(const Frame &frame) return push(new Deferred(send(frame))); } +/** + * Report errors to all deferred objects already in an error state + * @param force Report errors even for objects not already in error state + */ +void ChannelImpl::reportErrors(bool force) +{ + // keep looping for as long as the oldest callback is in an error state + while (_oldestCallback && (force || !*_oldestCallback)) + { + // construct monitor, because channel could be destructed + Monitor monitor(this); + + // report the error + auto *next = _oldestCallback->reportError("Frame could not be sent"); + + // leap out if object is no longer valid after the callback was called + if (!monitor.valid()) return; + + // install the next deferred object + _oldestCallback.reset(next); + + // was this also the newest callback + if (!next) _newestCallback = nullptr; + } +} + /** * Pause deliveries on a channel *