mirror of
https://github.com/transmission/transmission
synced 2024-12-23 08:13:27 +00:00
d7930984ef
There're places where manual intervention is still required as uncrustify is not ideal (unfortunately), but at least one may rely on it to do the right thing most of the time (e.g. when sending in a patch). The style itself is quite different from what we had before but making it uniform across all the codebase is the key. I also hope that it'll make the code more readable (YMMV) and less sensitive to further changes.
148 lines
4.5 KiB
C++
148 lines
4.5 KiB
C++
/*
|
|
* This file Copyright (C) 2016 Mnemosyne LLC
|
|
*
|
|
* It may be used under the GNU GPL versions 2 or 3
|
|
* or any future license endorsed by Mnemosyne LLC.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
#include <type_traits>
|
|
|
|
#include <QFutureInterface>
|
|
#include <QFutureWatcher>
|
|
#include <QObject>
|
|
#include <QPair>
|
|
#include <QQueue>
|
|
|
|
#include "RpcClient.h"
|
|
|
|
class RpcQueue : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit RpcQueue(QObject* parent = nullptr);
|
|
|
|
void setTolerateErrors(bool tolerateErrors = true)
|
|
{
|
|
myTolerateErrors = tolerateErrors;
|
|
}
|
|
|
|
template<typename Func>
|
|
void add(Func func)
|
|
{
|
|
myQueue.enqueue(qMakePair(normalizeFunc(func), ErrorHandlerFunction()));
|
|
}
|
|
|
|
template<typename Func, typename ErrorHandler>
|
|
void add(Func func, ErrorHandler errorHandler)
|
|
{
|
|
myQueue.enqueue(qMakePair(normalizeFunc(func), normalizeErrorHandler(errorHandler)));
|
|
}
|
|
|
|
RpcResponseFuture future();
|
|
|
|
// The first function in queue is ran synchronously
|
|
// (hence it may be e. g. a lambda capturing local variables by reference).
|
|
void run();
|
|
|
|
private:
|
|
// Internally queued function. Takes the last response future, makes a
|
|
// request and returns a new response future.
|
|
typedef std::function<RpcResponseFuture (const RpcResponseFuture&)> QueuedFunction;
|
|
|
|
// Internally stored error handler function. Takes the last response future and returns nothing.
|
|
typedef std::function<void (const RpcResponseFuture&)> ErrorHandlerFunction;
|
|
|
|
private slots:
|
|
void stepFinished();
|
|
|
|
private:
|
|
void runNext(const RpcResponseFuture& response);
|
|
|
|
// These overloads convert various forms of input closures to what we store internally.
|
|
|
|
// normal closure, takes response and returns new future
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func(const RpcResponse&)>::type, RpcResponseFuture>::value
|
|
>::type* = nullptr>
|
|
QueuedFunction normalizeFunc(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture& r)
|
|
{
|
|
return func(r.result());
|
|
};
|
|
}
|
|
|
|
// closure without argument (first step), takes nothing and returns new future
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func()>::type, RpcResponseFuture>::value
|
|
>::type* = nullptr>
|
|
QueuedFunction normalizeFunc(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture&)
|
|
{
|
|
return func();
|
|
};
|
|
}
|
|
|
|
// closure without return value ("auxiliary"), takes response and returns nothing -- internally we reuse the last future
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func(const RpcResponse&)>::type, void>::value
|
|
>::type* = nullptr>
|
|
QueuedFunction normalizeFunc(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture& r)
|
|
{
|
|
func(r.result());
|
|
return r;
|
|
};
|
|
}
|
|
|
|
// closure without argument and return value, takes nothing and returns nothing -- next function will also get nothing
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func()>::type, void>::value
|
|
>::type* = nullptr>
|
|
QueuedFunction normalizeFunc(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture& r)
|
|
{
|
|
func();
|
|
return r;
|
|
};
|
|
}
|
|
|
|
// normal error handler, takes last response
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func(const RpcResponse&)>::type, void>::value
|
|
>::type* = nullptr>
|
|
ErrorHandlerFunction normalizeErrorHandler(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture& r)
|
|
{
|
|
func(r.result());
|
|
};
|
|
}
|
|
|
|
// error handler without an argument, takes nothing
|
|
template<typename Func, typename std::enable_if<
|
|
std::is_same<typename std::result_of<Func()>::type, void>::value
|
|
>::type* = nullptr>
|
|
ErrorHandlerFunction normalizeErrorHandler(const Func& func)
|
|
{
|
|
return [func](const RpcResponseFuture& r)
|
|
{
|
|
func();
|
|
};
|
|
}
|
|
|
|
private:
|
|
bool myTolerateErrors;
|
|
QFutureInterface<RpcResponse> myPromise;
|
|
QQueue<QPair<QueuedFunction, ErrorHandlerFunction>> myQueue;
|
|
ErrorHandlerFunction myNextErrorHandler;
|
|
QFutureWatcher<RpcResponse> myFutureWatcher;
|
|
};
|