mirror of https://github.com/procxx/kepka.git
Rewrite base::lambda_guard, use only one pointer.
(cherry picked from commit f6ed3df
)
This commit is contained in:
parent
f488d5f9c1
commit
e7bace9ab3
|
@ -21,134 +21,76 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "base/lambda.h"
|
||||
#include "base/weak_unique_ptr.h"
|
||||
#include <QPointer>
|
||||
|
||||
// Guard lambda call by QObject* or enable_weak_from_this* pointers.
|
||||
|
||||
namespace base {
|
||||
|
||||
// Guard lambda call by one or many QObject* weak pointers.
|
||||
|
||||
namespace lambda_internal {
|
||||
|
||||
template <int N, typename Lambda> class guard_data {
|
||||
template <typename Lambda> class guard_with_QObject {
|
||||
public:
|
||||
template <typename... PointersAndLambda>
|
||||
inline guard_data(PointersAndLambda &&... qobjectsAndLambda)
|
||||
: _lambda(init(_pointers, std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {}
|
||||
template <typename OtherLambda>
|
||||
guard_with_QObject(const QObject *object, OtherLambda &&other)
|
||||
: _guard(object)
|
||||
, _callable(std::forward<OtherLambda>(other)) {}
|
||||
|
||||
inline guard_data(const guard_data &other)
|
||||
: _lambda(other._lambda) {
|
||||
for (auto i = 0; i != N; ++i) {
|
||||
_pointers[i] = other._pointers[i];
|
||||
}
|
||||
template <typename... OtherArgs, typename Return = decltype(std::declval<Lambda>()(std::declval<OtherArgs>()...))>
|
||||
Return operator()(OtherArgs &&... args) {
|
||||
return _guard ? _callable(std::forward<OtherArgs>(args)...) : Return();
|
||||
}
|
||||
|
||||
template <typename... Args, typename return_type = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
inline auto operator()(Args &&... args) {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
if (!_pointers[i]) {
|
||||
return return_type();
|
||||
}
|
||||
}
|
||||
return _lambda(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args, typename return_type = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
inline auto operator()(Args &&... args) const {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
if (!_pointers[i]) {
|
||||
return return_type();
|
||||
}
|
||||
}
|
||||
return _lambda(std::forward<Args>(args)...);
|
||||
template <typename... OtherArgs, typename Return = decltype(std::declval<Lambda>()(std::declval<OtherArgs>()...))>
|
||||
Return operator()(OtherArgs &&... args) const {
|
||||
return _guard ? _callable(std::forward<OtherArgs>(args)...) : Return();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename... PointersAndLambda>
|
||||
Lambda init(QPointer<QObject> *pointers, QObject *qobject, PointersAndLambda &&... qobjectsAndLambda) {
|
||||
*pointers = qobject;
|
||||
return init(++pointers, std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
}
|
||||
Lambda init(QPointer<QObject> *pointers, Lambda &&lambda) {
|
||||
return std::move(lambda);
|
||||
}
|
||||
|
||||
QPointer<QObject> _pointers[N];
|
||||
mutable Lambda _lambda;
|
||||
QPointer<const QObject> _guard;
|
||||
Lambda _callable;
|
||||
};
|
||||
|
||||
template <int N, typename Lambda> struct lambda_call_type<guard_data<N, Lambda>> {
|
||||
using type = lambda_call_type_t<Lambda>;
|
||||
};
|
||||
|
||||
template <int N, typename Lambda> class guard {
|
||||
template <typename Lambda> class guard_with_weak {
|
||||
public:
|
||||
template <typename Pointer, typename Other, typename... PointersAndLambda>
|
||||
inline guard(Pointer &&qobject, Other &&other, PointersAndLambda &&... qobjectsAndLambda)
|
||||
: _data(std::make_unique<guard_data<N, Lambda>>(std::forward<Pointer>(qobject), std::forward<Other>(other),
|
||||
std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {
|
||||
static_assert(1 + 1 + sizeof...(PointersAndLambda) == N + 1, "Wrong argument count!");
|
||||
template <typename OtherLambda>
|
||||
guard_with_weak(const base::enable_weak_from_this *object, OtherLambda &&other)
|
||||
: _guard(base::make_weak_unique(object))
|
||||
, _callable(std::forward<OtherLambda>(other)) {}
|
||||
|
||||
template <typename... OtherArgs, typename Return = decltype(std::declval<Lambda>()(std::declval<OtherArgs>()...))>
|
||||
Return operator()(OtherArgs &&... args) {
|
||||
return _guard ? _callable(std::forward<OtherArgs>(args)...) : Return{};
|
||||
}
|
||||
|
||||
inline guard(const guard &other)
|
||||
: _data(std::make_unique<guard_data<N, Lambda>>(static_cast<const guard_data<N, Lambda> &>(*other._data))) {}
|
||||
|
||||
inline guard(guard &&other)
|
||||
: _data(std::move(other._data)) {}
|
||||
|
||||
inline guard &operator=(const guard &&other) {
|
||||
_data = std::move(other._data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline guard &operator=(guard &&other) {
|
||||
_data = std::move(other._data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
inline decltype(auto) operator()(Args &&... args) {
|
||||
return (*_data)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args, typename = decltype(std::declval<Lambda>()(std::declval<Args>()...))>
|
||||
inline decltype(auto) operator()(Args &&... args) const {
|
||||
return (*_data)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return !_data;
|
||||
template <typename... OtherArgs, typename Return = decltype(std::declval<Lambda>()(std::declval<OtherArgs>()...))>
|
||||
Return operator()(OtherArgs &&... args) const {
|
||||
return _guard ? _callable(std::forward<OtherArgs>(args)...) : Return{};
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::unique_ptr<guard_data<N, Lambda>> _data;
|
||||
base::weak_unique_ptr<const base::enable_weak_from_this> _guard;
|
||||
Lambda _callable;
|
||||
};
|
||||
|
||||
template <int N, typename Lambda> struct lambda_call_type<guard<N, Lambda>> {
|
||||
template <typename Lambda> struct lambda_call_type<guard_with_QObject<Lambda>> {
|
||||
using type = lambda_call_type_t<Lambda>;
|
||||
};
|
||||
|
||||
template <int N, int K, typename... PointersAndLambda> struct guard_type;
|
||||
|
||||
template <int N, int K, typename Pointer, typename... PointersAndLambda>
|
||||
struct guard_type<N, K, Pointer, PointersAndLambda...> {
|
||||
using type = typename guard_type<N, K - 1, PointersAndLambda...>::type;
|
||||
template <typename Lambda> struct lambda_call_type<guard_with_weak<Lambda>> {
|
||||
using type = lambda_call_type_t<Lambda>;
|
||||
};
|
||||
|
||||
template <int N, typename Lambda> struct guard_type<N, 0, Lambda> { using type = guard<N, std::decay_t<Lambda>>; };
|
||||
|
||||
template <typename... PointersAndLambda> struct guard_type_helper {
|
||||
static constexpr int N = sizeof...(PointersAndLambda);
|
||||
using type = typename guard_type<N - 1, N - 1, PointersAndLambda...>::type;
|
||||
};
|
||||
|
||||
template <typename... PointersAndLambda> using guard_t = typename guard_type_helper<PointersAndLambda...>::type;
|
||||
|
||||
} // namespace lambda_internal
|
||||
|
||||
template <typename... PointersAndLambda>
|
||||
inline lambda_internal::guard_t<PointersAndLambda...> lambda_guarded(PointersAndLambda &&... qobjectsAndLambda) {
|
||||
static_assert(sizeof...(PointersAndLambda) > 0, "Lambda should be passed here.");
|
||||
return lambda_internal::guard_t<PointersAndLambda...>(std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
template <typename Lambda> inline auto lambda_guarded(const QObject *object, Lambda &&lambda) {
|
||||
using Guarded = lambda_internal::guard_with_QObject<std::decay_t<Lambda>>;
|
||||
return Guarded(object, std::forward<Lambda>(lambda));
|
||||
}
|
||||
|
||||
template <typename Lambda> inline auto lambda_guarded(const base::enable_weak_from_this *object, Lambda &&lambda) {
|
||||
using Guarded = lambda_internal::guard_with_weak<std::decay_t<Lambda>>;
|
||||
return Guarded(object, std::forward<Lambda>(lambda));
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -46,14 +46,15 @@ public:
|
|||
private:
|
||||
template <typename Child> friend class weak_unique_ptr;
|
||||
|
||||
std::shared_ptr<enable_weak_from_this *> getGuarded() {
|
||||
std::shared_ptr<enable_weak_from_this *> getGuarded() const {
|
||||
if (!_guarded) {
|
||||
_guarded = std::make_shared<enable_weak_from_this *>(static_cast<enable_weak_from_this *>(this));
|
||||
_guarded = std::make_shared<enable_weak_from_this *>(
|
||||
const_cast<enable_weak_from_this *>(static_cast<const enable_weak_from_this *>(this)));
|
||||
}
|
||||
return _guarded;
|
||||
}
|
||||
|
||||
std::shared_ptr<enable_weak_from_this *> _guarded;
|
||||
mutable std::shared_ptr<enable_weak_from_this *> _guarded;
|
||||
};
|
||||
|
||||
template <typename T> class weak_unique_ptr {
|
||||
|
|
|
@ -44,32 +44,53 @@ void CallDelayed(int duration, base::lambda_once<void()> &&lambda);
|
|||
|
||||
} // namespace internal
|
||||
|
||||
template <int N, typename Lambda>
|
||||
inline void CallDelayed(int duration, base::lambda_internal::guard<N, Lambda> &&guarded) {
|
||||
return internal::CallDelayed(duration, [guarded = std::move(guarded)] { guarded(); });
|
||||
template <typename Lambda>
|
||||
inline void CallDelayed(int duration, base::lambda_internal::guard_with_QObject<Lambda> &&guarded) {
|
||||
return internal::CallDelayed(duration, std::move(guarded));
|
||||
}
|
||||
|
||||
template <typename Pointer, typename... PointersAndLambda>
|
||||
inline void CallDelayed(int duration, Pointer &&qobject, PointersAndLambda &&... qobjectsAndLambda) {
|
||||
auto guarded =
|
||||
base::lambda_guarded(std::forward<Pointer>(qobject), std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
return CallDelayed(duration, std::move(guarded));
|
||||
template <typename Lambda>
|
||||
inline void CallDelayed(int duration, base::lambda_internal::guard_with_weak<Lambda> &&guarded) {
|
||||
return internal::CallDelayed(duration, std::move(guarded));
|
||||
}
|
||||
|
||||
template <typename... PointersAndLambda>
|
||||
inline base::lambda<void()> LambdaDelayed(int duration, PointersAndLambda &&... qobjectsAndLambda) {
|
||||
auto guarded = base::lambda_guarded(std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
return [guarded = std::move(guarded), duration] { internal::CallDelayed(duration, [guarded] { guarded(); }); };
|
||||
template <typename Lambda> inline void CallDelayed(int duration, const QObject *object, Lambda &&lambda) {
|
||||
return internal::CallDelayed(duration, base::lambda_guarded(object, std::forward<Lambda>(lambda)));
|
||||
}
|
||||
|
||||
template <typename... PointersAndLambda>
|
||||
inline base::lambda_once<void()> LambdaDelayedOnce(int duration, PointersAndLambda &&... qobjectsAndLambda) {
|
||||
auto guarded = base::lambda_guarded(std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
return [guarded = std::move(guarded), duration]() mutable {
|
||||
internal::CallDelayed(duration, [guarded = std::move(guarded)] { guarded(); });
|
||||
template <typename Lambda>
|
||||
inline void CallDelayed(int duration, const base::enable_weak_from_this *object, Lambda &&lambda) {
|
||||
return internal::CallDelayed(duration, base::lambda_guarded(object, std::forward<Lambda>(lambda)));
|
||||
}
|
||||
|
||||
template <typename Lambda> inline auto LambdaDelayed(int duration, const QObject *object, Lambda &&lambda) {
|
||||
auto guarded = base::lambda_guarded(object, std::forward<Lambda>(lambda));
|
||||
return [saved = std::move(guarded), duration] {
|
||||
auto copy = saved;
|
||||
internal::CallDelayed(duration, std::move(copy));
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Lambda>
|
||||
inline auto LambdaDelayed(int duration, const base::enable_weak_from_this *object, Lambda &&lambda) {
|
||||
auto guarded = base::lambda_guarded(object, std::forward<Lambda>(lambda));
|
||||
return [saved = std::move(guarded), duration] {
|
||||
auto copy = saved;
|
||||
internal::CallDelayed(duration, std::move(copy));
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Lambda> inline auto LambdaDelayedOnce(int duration, const QObject *object, Lambda &&lambda) {
|
||||
auto guarded = base::lambda_guarded(object, std::forward<Lambda>(lambda));
|
||||
return [saved = std::move(guarded), duration]() mutable { internal::CallDelayed(duration, std::move(saved)); };
|
||||
}
|
||||
|
||||
template <typename Lambda>
|
||||
inline auto LambdaDelayedOnce(int duration, const base::enable_weak_from_this *object, Lambda &&lambda) {
|
||||
auto guarded = base::lambda_guarded(object, std::forward<Lambda>(lambda));
|
||||
return [saved = std::move(guarded), duration]() mutable { internal::CallDelayed(duration, std::move(saved)); };
|
||||
}
|
||||
|
||||
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0);
|
||||
bool insertBotCommand(const QString &cmd);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col);
|
||||
|
|
Loading…
Reference in New Issue