_DEBUG-test ConcurrentSender generic handlers.

This commit is contained in:
John Preston 2018-06-17 21:29:46 +01:00
parent 1bfe409c93
commit c7aa5ed544
1 changed files with 84 additions and 54 deletions

View File

@ -13,6 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flat_map.h" #include "base/flat_map.h"
#include "mtproto/core_types.h" #include "mtproto/core_types.h"
#ifndef _DEBUG
#define MTP_SENDER_USE_GENERIC_HANDLERS
#endif // !_DEBUG
class RPCError; class RPCError;
namespace MTP { namespace MTP {
@ -21,7 +25,8 @@ class Instance;
class ConcurrentSender : public base::has_weak_ptr { class ConcurrentSender : public base::has_weak_ptr {
template <typename ...Args> template <typename ...Args>
static constexpr bool is_callable_v = rpl::details::is_callable_v<Args...>; static constexpr bool is_callable_v
= rpl::details::is_callable_v<Args...>;
template <typename Method> template <typename Method>
auto with_instance(Method &&method) auto with_instance(Method &&method)
@ -101,7 +106,7 @@ public:
[[nodiscard]] SpecificRequestBuilder &afterDelay( [[nodiscard]] SpecificRequestBuilder &afterDelay(
TimeMs ms) noexcept; TimeMs ms) noexcept;
#ifdef _DEBUG #ifndef MTP_SENDER_USE_GENERIC_HANDLERS
// Allow code completion to show response type. // Allow code completion to show response type.
[[nodiscard]] SpecificRequestBuilder &done(FnMut<void()> &&handler); [[nodiscard]] SpecificRequestBuilder &done(FnMut<void()> &&handler);
[[nodiscard]] SpecificRequestBuilder &done(FnMut<void( [[nodiscard]] SpecificRequestBuilder &done(FnMut<void(
@ -119,12 +124,12 @@ public:
RPCError &&)> &&handler); RPCError &&)> &&handler);
[[nodiscard]] SpecificRequestBuilder &fail(FnMut<void( [[nodiscard]] SpecificRequestBuilder &fail(FnMut<void(
RPCError &&)> &&handler); RPCError &&)> &&handler);
#else // _DEBUG #else // !MTP_SENDER_USE_GENERIC_HANDLERS
template <typename Handler> template <typename Handler>
[[nodiscard]] SpecificRequestBuilder &done(Handler &&handler); [[nodiscard]] SpecificRequestBuilder &done(Handler &&handler);
template <typename Handler> template <typename Handler>
[[nodiscard]] SpecificRequestBuilder &fail(Handler &&handler); [[nodiscard]] SpecificRequestBuilder &fail(Handler &&handler);
#endif // _DEBUG #endif // MTP_SENDER_USE_GENERIC_HANDLERS
[[nodiscard]] SpecificRequestBuilder &handleFloodErrors() noexcept; [[nodiscard]] SpecificRequestBuilder &handleFloodErrors() noexcept;
[[nodiscard]] SpecificRequestBuilder &handleAllErrors() noexcept; [[nodiscard]] SpecificRequestBuilder &handleAllErrors() noexcept;
@ -142,14 +147,14 @@ public:
class SentRequestWrap { class SentRequestWrap {
public: public:
void cancel() { void cancel();
_sender->senderRequestCancel(_requestId);
}
private: private:
friend class ConcurrentSender; friend class ConcurrentSender;
SentRequestWrap(not_null<ConcurrentSender*> sender, mtpRequestId requestId) : _sender(sender), _requestId(requestId) { SentRequestWrap(
} not_null<ConcurrentSender*> sender,
mtpRequestId requestId);
not_null<ConcurrentSender*> _sender; not_null<ConcurrentSender*> _sender;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
@ -164,11 +169,7 @@ public:
[[nodiscard]] SentRequestWrap request(mtpRequestId requestId) noexcept; [[nodiscard]] SentRequestWrap request(mtpRequestId requestId) noexcept;
[[nodiscard]] auto requestCanceller() noexcept { [[nodiscard]] auto requestCanceller() noexcept;
return [=](mtpRequestId requestId) {
request(requestId).cancel();
};
}
~ConcurrentSender(); ~ConcurrentSender();
@ -197,7 +198,8 @@ private:
template <typename Response, typename InvokeFullDone> template <typename Response, typename InvokeFullDone>
void ConcurrentSender::RequestBuilder::setDoneHandler( void ConcurrentSender::RequestBuilder::setDoneHandler(
InvokeFullDone &&invoke) noexcept { InvokeFullDone &&invoke
) noexcept {
_handlers.done = [handler = std::move(invoke)]( _handlers.done = [handler = std::move(invoke)](
mtpRequestId requestId, mtpRequestId requestId,
bytes::const_span result) mutable { bytes::const_span result) mutable {
@ -214,37 +216,40 @@ void ConcurrentSender::RequestBuilder::setDoneHandler(
template <typename InvokeFullFail> template <typename InvokeFullFail>
void ConcurrentSender::RequestBuilder::setFailHandler( void ConcurrentSender::RequestBuilder::setFailHandler(
InvokeFullFail &&invoke) noexcept { InvokeFullFail &&invoke
) noexcept {
_handlers.fail = std::move(invoke); _handlers.fail = std::move(invoke);
} }
template <typename Request> template <typename Request>
ConcurrentSender::SpecificRequestBuilder<Request>::SpecificRequestBuilder( ConcurrentSender::SpecificRequestBuilder<Request>::SpecificRequestBuilder(
not_null<ConcurrentSender*> sender, not_null<ConcurrentSender*> sender,
Request &&request) noexcept Request &&request
: RequestBuilder(sender, mtpRequestData::serialize(request)) { ) noexcept : RequestBuilder(sender, mtpRequestData::serialize(request)) {
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::toDC( auto ConcurrentSender::SpecificRequestBuilder<Request>::toDC(
ShiftedDcId dcId) noexcept -> SpecificRequestBuilder & { ShiftedDcId dcId
) noexcept -> SpecificRequestBuilder & {
setToDC(dcId); setToDC(dcId);
return *this; return *this;
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::afterDelay( auto ConcurrentSender::SpecificRequestBuilder<Request>::afterDelay(
TimeMs ms) noexcept -> SpecificRequestBuilder & { TimeMs ms
) noexcept -> SpecificRequestBuilder & {
setCanWait(ms); setCanWait(ms);
return *this; return *this;
} }
#ifdef _DEBUG #ifndef MTP_SENDER_USE_GENERIC_HANDLERS
// Allow code completion to show response type. // Allow code completion to show response type.
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::done( auto ConcurrentSender::SpecificRequestBuilder<Request>::done(
FnMut<void(Response &&)> &&handler) FnMut<void(Response &&)> &&handler
-> SpecificRequestBuilder & { ) -> SpecificRequestBuilder & {
setDoneHandler<Response>([handler = std::move(handler)]( setDoneHandler<Response>([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
Response &&result) mutable { Response &&result) mutable {
@ -254,16 +259,17 @@ template <typename Request>
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::done( auto ConcurrentSender::SpecificRequestBuilder<Request>::done(
FnMut<void(mtpRequestId, Response &&)> &&handler) FnMut<void(mtpRequestId, Response &&)> &&handler
-> SpecificRequestBuilder & { ) -> SpecificRequestBuilder & {
setDoneHandler<Response>(std::move(handler)); setDoneHandler<Response>(std::move(handler));
return *this; return *this;
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::done( auto ConcurrentSender::SpecificRequestBuilder<Request>::done(
FnMut<void(mtpRequestId)> &&handler) -> SpecificRequestBuilder & { FnMut<void(mtpRequestId)> &&handler
) -> SpecificRequestBuilder & {
setDoneHandler<Response>([handler = std::move(handler)]( setDoneHandler<Response>([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
Response &&result) mutable { Response &&result) mutable {
@ -273,8 +279,9 @@ template <typename Request>
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::done( auto ConcurrentSender::SpecificRequestBuilder<Request>::done(
FnMut<void()> &&handler) -> SpecificRequestBuilder & { FnMut<void()> &&handler
) -> SpecificRequestBuilder & {
setDoneHandler<Response>([handler = std::move(handler)]( setDoneHandler<Response>([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
Response &&result) mutable { Response &&result) mutable {
@ -284,8 +291,9 @@ template <typename Request>
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::fail( auto ConcurrentSender::SpecificRequestBuilder<Request>::fail(
FnMut<void(RPCError &&)> &&handler) -> SpecificRequestBuilder & { FnMut<void(RPCError &&)> &&handler
) -> SpecificRequestBuilder & {
setFailHandler([handler = std::move(handler)]( setFailHandler([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
RPCError &&error) mutable { RPCError &&error) mutable {
@ -295,16 +303,17 @@ template <typename Request>
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::fail( auto ConcurrentSender::SpecificRequestBuilder<Request>::fail(
FnMut<void(mtpRequestId, RPCError &&)> &&handler) FnMut<void(mtpRequestId, RPCError &&)> &&handler
-> SpecificRequestBuilder & { ) -> SpecificRequestBuilder & {
setFailHandler(std::move(handler)); setFailHandler(std::move(handler));
return *this; return *this;
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::fail( auto ConcurrentSender::SpecificRequestBuilder<Request>::fail(
FnMut<void(mtpRequestId)> &&handler) -> SpecificRequestBuilder & { FnMut<void(mtpRequestId)> &&handler
) -> SpecificRequestBuilder & {
setFailHandler([handler = std::move(handler)]( setFailHandler([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
RPCError &&error) mutable { RPCError &&error) mutable {
@ -314,8 +323,9 @@ template <typename Request>
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::fail( auto ConcurrentSender::SpecificRequestBuilder<Request>::fail(
FnMut<void()> &&handler) -> SpecificRequestBuilder & { FnMut<void()> &&handler
) -> SpecificRequestBuilder & {
setFailHandler([handler = std::move(handler)]( setFailHandler([handler = std::move(handler)](
mtpRequestId requestId, mtpRequestId requestId,
RPCError &&error) mutable { RPCError &&error) mutable {
@ -323,11 +333,12 @@ template <typename Request>
}); });
return *this; return *this;
} }
#else // _DEBUG #else // !MTP_SENDER_USE_GENERIC_HANDLERS
template <typename Request> template <typename Request>
template <typename Handler> template <typename Handler>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::done( auto ConcurrentSender::SpecificRequestBuilder<Request>::done(
Handler &&handler) -> SpecificRequestBuilder & { Handler &&handler
) -> SpecificRequestBuilder & {
using Response = typename Request::ResponseType; using Response = typename Request::ResponseType;
constexpr auto takesFull = rpl::details::is_callable_plain_v< constexpr auto takesFull = rpl::details::is_callable_plain_v<
Handler, Handler,
@ -369,8 +380,9 @@ template <typename Handler>
template <typename Request> template <typename Request>
template <typename Handler> template <typename Handler>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::fail( auto ConcurrentSender::SpecificRequestBuilder<Request>::fail(
Handler &&handler) -> SpecificRequestBuilder & { Handler &&handler
) -> SpecificRequestBuilder & {
constexpr auto takesFull = rpl::details::is_callable_plain_v< constexpr auto takesFull = rpl::details::is_callable_plain_v<
Handler, Handler,
mtpRequestId, mtpRequestId,
@ -409,35 +421,53 @@ template <typename Handler>
return *this; return *this;
} }
#endif // _DEBUG #endif // MTP_SENDER_USE_GENERIC_HANDLERS
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::handleFloodErrors() noexcept auto ConcurrentSender::SpecificRequestBuilder<Request>::handleFloodErrors(
-> SpecificRequestBuilder & { ) noexcept -> SpecificRequestBuilder & {
setFailSkipPolicy(FailSkipPolicy::HandleFlood); setFailSkipPolicy(FailSkipPolicy::HandleFlood);
return *this; return *this;
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::handleAllErrors() noexcept auto ConcurrentSender::SpecificRequestBuilder<Request>::handleAllErrors(
-> SpecificRequestBuilder & { ) noexcept -> SpecificRequestBuilder & {
setFailSkipPolicy(FailSkipPolicy::HandleAll); setFailSkipPolicy(FailSkipPolicy::HandleAll);
return *this; return *this;
} }
template <typename Request> template <typename Request>
[[nodiscard]] auto ConcurrentSender::SpecificRequestBuilder<Request>::afterRequest( auto ConcurrentSender::SpecificRequestBuilder<Request>::afterRequest(
mtpRequestId requestId) noexcept -> SpecificRequestBuilder & { mtpRequestId requestId
) noexcept -> SpecificRequestBuilder & {
setAfter(requestId); setAfter(requestId);
return *this; return *this;
} }
inline void ConcurrentSender::SentRequestWrap::cancel() {
_sender->senderRequestCancel(_requestId);
}
inline ConcurrentSender::SentRequestWrap::SentRequestWrap(
not_null<ConcurrentSender*> sender,
mtpRequestId requestId
) : _sender(sender)
, _requestId(requestId) {
}
template <typename Request, typename, typename> template <typename Request, typename, typename>
inline auto ConcurrentSender::request(Request &&request) noexcept inline auto ConcurrentSender::request(Request &&request) noexcept
-> SpecificRequestBuilder<Request> { -> SpecificRequestBuilder<Request> {
return SpecificRequestBuilder<Request>(this, std::move(request)); return SpecificRequestBuilder<Request>(this, std::move(request));
} }
inline auto ConcurrentSender::requestCanceller() noexcept {
return [=](mtpRequestId requestId) {
request(requestId).cancel();
};
}
inline auto ConcurrentSender::request(mtpRequestId requestId) noexcept inline auto ConcurrentSender::request(mtpRequestId requestId) noexcept
-> SentRequestWrap { -> SentRequestWrap {
return SentRequestWrap(this, requestId); return SentRequestWrap(this, requestId);