From 6b12a5df6289921a55f26665cf83bf290154f8b9 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 30 Apr 2015 15:34:15 +0200 Subject: Moved resultprovider to separate file. --- common/clientapi.h | 196 +---------------------------------------------------- 1 file changed, 1 insertion(+), 195 deletions(-) (limited to 'common/clientapi.h') diff --git a/common/clientapi.h b/common/clientapi.h index 48177df..56247a7 100644 --- a/common/clientapi.h +++ b/common/clientapi.h @@ -24,212 +24,18 @@ #include #include #include -#include #include #include -#include #include #include #include "threadboundary.h" #include "async/src/async.h" +#include "resultprovider.h" namespace async { //This should abstract if we execute from eventloop or in thread. //It supposed to allow the caller to finish the current method before executing the runner. void run(const std::function &runner); - - /** - * Query result set - */ - - template - class ResultEmitter; - - /* - * The promise side for the result emitter - */ - template - class ResultProvider { - private: - void callInMainThreadOnEmitter(void (ResultEmitter::*f)()) - { - //We use the eventloop to call the addHandler directly from the main eventloop. - //That way the result emitter implementation doesn't have to care about threadsafety at all. - //The alternative would be to make all handlers of the emitter threadsafe. - if (auto emitter = mResultEmitter.toStrongRef()) { - auto weakEmitter = mResultEmitter; - //We don't want to keep the emitter alive here, so we only capture a weak reference - emitter->mThreadBoundary.callInMainThread([weakEmitter, f]() { - if (auto strongRef = weakEmitter.toStrongRef()) { - (strongRef.data()->*f)(); - } - }); - } - } - - void callInMainThreadOnEmitter(const std::function &f) - { - //We use the eventloop to call the addHandler directly from the main eventloop. - //That way the result emitter implementation doesn't have to care about threadsafety at all. - //The alternative would be to make all handlers of the emitter threadsafe. - if (auto emitter = mResultEmitter.toStrongRef()) { - emitter->mThreadBoundary.callInMainThread([f]() { - f(); - }); - } - } - - public: - //Called from worker thread - void add(const T &value) - { - //Because I don't know how to use bind - auto weakEmitter = mResultEmitter; - callInMainThreadOnEmitter([weakEmitter, value](){ - if (auto strongRef = weakEmitter.toStrongRef()) { - strongRef->addHandler(value); - } - }); - } - - void initialResultSetComplete() - { - callInMainThreadOnEmitter(&ResultEmitter::initialResultSetComplete); - } - - //Called from worker thread - void complete() - { - callInMainThreadOnEmitter(&ResultEmitter::complete); - } - - void clear() - { - callInMainThreadOnEmitter(&ResultEmitter::clear); - } - - - QSharedPointer > emitter() - { - if (!mResultEmitter) { - //We have to go over a separate var and return that, otherwise we'd delete the emitter immediately again - auto sharedPtr = QSharedPointer >(new ResultEmitter, [this](ResultEmitter *emitter){ done(); delete emitter; }); - mResultEmitter = sharedPtr; - return sharedPtr; - } - - return mResultEmitter.toStrongRef(); - } - - /** - * For lifetimemanagement only. - * We keep the runner alive as long as the result provider exists. - */ - void setQueryRunner(const QSharedPointer &runner) - { - mQueryRunner = runner; - } - - /** - * For lifetimemanagement only. - * We keep the runner alive as long as the result provider exists. - */ - void setFacade(const std::shared_ptr &facade) - { - mFacade = facade; - } - - void onDone(const std::function &callback) - { - mOnDoneCallback = callback; - } - - bool isDone() const - { - //The existance of the emitter currently defines wether we're done or not. - return mResultEmitter.toStrongRef().isNull(); - } - - private: - void done() - { - qWarning() << "done"; - if (mOnDoneCallback) { - mOnDoneCallback(); - mOnDoneCallback = std::function(); - } - } - - QWeakPointer > mResultEmitter; - QSharedPointer mQueryRunner; - std::shared_ptr mFacade; - std::function mOnDoneCallback; - }; - - /* - * The future side for the client. - * - * It does not directly hold the state. - * - * The advantage of this is that we can specialize it to: - * * do inline transformations to the data - * * directly store the state in a suitable datastructure: QList, QSet, std::list, QVector, ... - * * build async interfaces with signals - * * build sync interfaces that block when accessing the value - * - */ - template - class ResultEmitter { - public: - void onAdded(const std::function &handler) - { - addHandler = handler; - } - // void onRemoved(const std::function &handler); - void onInitialResultSetComplete(const std::function &handler) - { - initialResultSetCompleteHandler = handler; - } - void onComplete(const std::function &handler) - { - completeHandler = handler; - } - void onClear(const std::function &handler) - { - clearHandler = handler; - } - - void add(const DomainType &value) - { - addHandler(value); - } - - void initialResultSetComplete() - { - initialResultSetCompleteHandler(); - } - - void complete() - { - completeHandler(); - } - - void clear() - { - clearHandler(); - } - - private: - friend class ResultProvider; - - std::function addHandler; - // std::function removeHandler; - std::function initialResultSetCompleteHandler; - std::function completeHandler; - std::function clearHandler; - ThreadBoundary mThreadBoundary; - }; - } namespace Akonadi2 { -- cgit v1.2.3