mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 14:38:15 +00:00
Merge branch 'master' into player
Conflicts: Telegram/SourceFiles/core/observer.h Telegram/SourceFiles/mainwindow.h Telegram/SourceFiles/media/view/media_clip_playback.cpp Telegram/SourceFiles/media/view/media_clip_playback.h
This commit is contained in:
@@ -20,6 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <QtCore/QReadWriteLock>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
#include <memory>
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
template <typename T>
|
||||
void deleteAndMark(T *&link) {
|
||||
delete link;
|
||||
@@ -259,13 +270,6 @@ typedef float float32;
|
||||
typedef double float64;
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <QtCore/QReadWriteLock>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
using std::string;
|
||||
using std::exception;
|
||||
#ifdef OS_MAC_OLD
|
||||
@@ -1035,13 +1039,15 @@ struct ComponentWrapStruct {
|
||||
// global scope, so it will be filled by zeros from the start
|
||||
ComponentWrapStruct() {
|
||||
}
|
||||
ComponentWrapStruct(int size, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move)
|
||||
ComponentWrapStruct(std::size_t size, std::size_t align, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move)
|
||||
: Size(size)
|
||||
, Align(align)
|
||||
, Construct(construct)
|
||||
, Destruct(destruct)
|
||||
, Move(move) {
|
||||
}
|
||||
int Size;
|
||||
std::size_t Size;
|
||||
std::size_t Align;
|
||||
ComponentConstruct Construct;
|
||||
ComponentDestruct Destruct;
|
||||
ComponentMove Move;
|
||||
@@ -1058,6 +1064,7 @@ extern QAtomicInt ComponentIndexLast;
|
||||
template <typename Type>
|
||||
struct BaseComponent {
|
||||
BaseComponent() {
|
||||
static_assert(alignof(Type) <= alignof(SmallestSizeType), "Components should align to a pointer!");
|
||||
}
|
||||
BaseComponent(const BaseComponent &other) = delete;
|
||||
BaseComponent &operator=(const BaseComponent &other) = delete;
|
||||
@@ -1075,8 +1082,11 @@ struct BaseComponent {
|
||||
t_assert(last < 64);
|
||||
if (_index.testAndSetOrdered(0, last + 1)) {
|
||||
ComponentWraps[last] = ComponentWrapStruct(
|
||||
CeilDivideMinimumOne<sizeof(Type), sizeof(uint64)>::Result * sizeof(uint64),
|
||||
Type::ComponentConstruct, Type::ComponentDestruct, Type::ComponentMove);
|
||||
CeilDivideMinimumOne<sizeof(Type), sizeof(SmallestSizeType)>::Result * sizeof(SmallestSizeType),
|
||||
alignof(Type),
|
||||
Type::ComponentConstruct,
|
||||
Type::ComponentDestruct,
|
||||
Type::ComponentMove);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1088,6 +1098,8 @@ struct BaseComponent {
|
||||
}
|
||||
|
||||
protected:
|
||||
using SmallestSizeType = void*;
|
||||
|
||||
static void ComponentConstruct(void *location, Composer *composer) {
|
||||
new (location) Type();
|
||||
}
|
||||
@@ -1102,7 +1114,6 @@ protected:
|
||||
|
||||
class ComposerMetadata {
|
||||
public:
|
||||
|
||||
ComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
uint64 m = (1ULL << i);
|
||||
@@ -1147,15 +1158,13 @@ const ComposerMetadata *GetComposerMetadata(uint64 mask);
|
||||
|
||||
class Composer {
|
||||
public:
|
||||
|
||||
Composer(uint64 mask = 0) : _data(zerodata()) {
|
||||
if (mask) {
|
||||
const ComposerMetadata *meta = GetComposerMetadata(mask);
|
||||
int size = sizeof(meta) + meta->size;
|
||||
void *data = operator new(size);
|
||||
if (!data) { // terminate if we can't allocate memory
|
||||
throw "Can't allocate memory!";
|
||||
}
|
||||
|
||||
auto data = operator new(size);
|
||||
t_assert(data != nullptr);
|
||||
|
||||
_data = data;
|
||||
_meta() = meta;
|
||||
@@ -1163,7 +1172,13 @@ public:
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
try {
|
||||
ComponentWraps[i].Construct(_dataptrunsafe(offset), this);
|
||||
auto constructAt = _dataptrunsafe(offset);
|
||||
#ifndef OS_MAC_OLD
|
||||
auto space = ComponentWraps[i].Size;
|
||||
auto alignedAt = std::align(ComponentWraps[i].Align, space, constructAt, space);
|
||||
t_assert(alignedAt == constructAt);
|
||||
#endif // OS_MAC_OLD
|
||||
ComponentWraps[i].Construct(constructAt, this);
|
||||
} catch (...) {
|
||||
while (i > 0) {
|
||||
--i;
|
||||
@@ -1182,7 +1197,7 @@ public:
|
||||
Composer &operator=(const Composer &other) = delete;
|
||||
~Composer() {
|
||||
if (_data != zerodata()) {
|
||||
const ComposerMetadata *meta = _meta();
|
||||
auto meta = _meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i];
|
||||
if (offset >= 0) {
|
||||
@@ -1213,7 +1228,7 @@ protected:
|
||||
Composer tmp(mask);
|
||||
tmp.swap(*this);
|
||||
if (_data != zerodata() && tmp._data != zerodata()) {
|
||||
const ComposerMetadata *meta = _meta(), *wasmeta = tmp._meta();
|
||||
auto meta = _meta(), wasmeta = tmp._meta();
|
||||
for (int i = 0; i < meta->last; ++i) {
|
||||
int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i];
|
||||
if (offset >= 0 && wasoffset >= 0) {
|
||||
@@ -1252,103 +1267,3 @@ private:
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class SharedCallback {
|
||||
public:
|
||||
virtual R call(Args... args) const = 0;
|
||||
virtual ~SharedCallback() {
|
||||
}
|
||||
using Ptr = QSharedPointer<SharedCallback<R, Args...>>;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class FunctionImplementation {
|
||||
public:
|
||||
virtual R call(Args... args) = 0;
|
||||
virtual void destroy() { delete this; }
|
||||
virtual ~FunctionImplementation() {}
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class NullFunctionImplementation : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
R call(Args... args) override { return R(); }
|
||||
void destroy() override {}
|
||||
static NullFunctionImplementation<R, Args...> SharedInstance;
|
||||
|
||||
};
|
||||
template <typename R, typename... Args>
|
||||
NullFunctionImplementation<R, Args...> NullFunctionImplementation<R, Args...>::SharedInstance;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class Function {
|
||||
public:
|
||||
Function() : _implementation(nullImpl()) {}
|
||||
Function(FunctionImplementation<R, Args...> *implementation) : _implementation(implementation) {}
|
||||
Function(const Function<R, Args...> &other) = delete;
|
||||
Function<R, Args...> &operator=(const Function<R, Args...> &other) = delete;
|
||||
Function(Function<R, Args...> &&other) : _implementation(other._implementation) {
|
||||
other._implementation = nullImpl();
|
||||
}
|
||||
Function<R, Args...> &operator=(Function<R, Args...> &&other) {
|
||||
std::swap(_implementation, other._implementation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return (_implementation == nullImpl());
|
||||
}
|
||||
|
||||
R call(Args... args) { return _implementation->call(args...); }
|
||||
~Function() {
|
||||
if (_implementation) {
|
||||
_implementation->destroy();
|
||||
_implementation = nullptr;
|
||||
}
|
||||
deleteAndMark(_implementation);
|
||||
}
|
||||
|
||||
private:
|
||||
static FunctionImplementation<R, Args...> *nullImpl() {
|
||||
return &NullFunctionImplementation<R, Args...>::SharedInstance;
|
||||
}
|
||||
|
||||
FunctionImplementation<R, Args...> *_implementation;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class WrappedFunction : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
using Method = R(*)(Args... args);
|
||||
WrappedFunction(Method method) : _method(method) {}
|
||||
R call(Args... args) override { return (*_method)(args...); }
|
||||
|
||||
private:
|
||||
Method _method;
|
||||
|
||||
};
|
||||
template <typename R, typename... Args>
|
||||
inline Function<R, Args...> func(R(*method)(Args... args)) {
|
||||
return Function<R, Args...>(new WrappedFunction<R, Args...>(method));
|
||||
}
|
||||
|
||||
template <typename O, typename I, typename R, typename... Args>
|
||||
class ObjectFunction : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
using Method = R(I::*)(Args... args);
|
||||
ObjectFunction(O *obj, Method method) : _obj(obj), _method(method) {}
|
||||
R call(Args... args) override { return (_obj->*_method)(args...); }
|
||||
|
||||
private:
|
||||
O *_obj;
|
||||
Method _method;
|
||||
|
||||
};
|
||||
template <typename O, typename I, typename R, typename... Args>
|
||||
inline Function<R, Args...> func(O *obj, R(I::*method)(Args...)) {
|
||||
return Function<R, Args...>(new ObjectFunction<O, I, R, Args...>(obj, method));
|
||||
}
|
||||
|
@@ -20,6 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
#include <memory>
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
@@ -50,7 +54,7 @@ struct lambda_wrap_helper_base {
|
||||
const call_type call;
|
||||
const destruct_type destruct;
|
||||
|
||||
static constexpr size_t kFullStorageSize = 40U;
|
||||
static constexpr size_t kFullStorageSize = sizeof(void*) + 24U;
|
||||
static constexpr size_t kStorageSize = kFullStorageSize - sizeof(void*);
|
||||
|
||||
template <typename Lambda>
|
||||
@@ -90,43 +94,47 @@ const lambda_wrap_empty<Return, Args...> lambda_wrap_empty<Return, Args...>::ins
|
||||
|
||||
template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_move_impl;
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
struct lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
|
||||
using JustLambda = std_::decay_simple_t<Lambda>;
|
||||
using LambdaPtr = std_::unique_ptr<JustLambda>;
|
||||
using Parent = lambda_wrap_helper_base<Return, Args...>;
|
||||
static void construct_move_other_method(void *lambda, void *source) {
|
||||
auto source_lambda = static_cast<LambdaPtr*>(source);
|
||||
new (lambda) LambdaPtr(std_::move(*source_lambda));
|
||||
}
|
||||
static void construct_move_lambda_method(void *lambda, void *source) {
|
||||
auto source_lambda = static_cast<JustLambda*>(source);
|
||||
new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda)));
|
||||
}
|
||||
static Return call_method(const void *lambda, Args... args) {
|
||||
return (**static_cast<const LambdaPtr*>(lambda))(std_::forward<Args>(args)...);
|
||||
}
|
||||
static void destruct_method(const void *lambda) {
|
||||
static_cast<const LambdaPtr*>(lambda)->~LambdaPtr();
|
||||
}
|
||||
lambda_wrap_helper_move_impl() : Parent(
|
||||
&Parent::bad_construct_copy,
|
||||
&lambda_wrap_helper_move_impl::construct_move_other_method,
|
||||
&lambda_wrap_helper_move_impl::call_method,
|
||||
&lambda_wrap_helper_move_impl::destruct_method) {
|
||||
}
|
||||
|
||||
protected:
|
||||
lambda_wrap_helper_move_impl(
|
||||
typename Parent::construct_copy_other_type construct_copy_other
|
||||
) : Parent(
|
||||
construct_copy_other,
|
||||
&lambda_wrap_helper_move_impl::construct_move_other_method,
|
||||
&lambda_wrap_helper_move_impl::call_method,
|
||||
&lambda_wrap_helper_move_impl::destruct_method) {
|
||||
}
|
||||
|
||||
};
|
||||
//
|
||||
// Disable large lambda support.
|
||||
// If you really need it, just store data in some std_::unique_ptr<struct>.
|
||||
//
|
||||
//template <typename Lambda, typename Return, typename ...Args>
|
||||
//struct lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
|
||||
// using JustLambda = std_::decay_simple_t<Lambda>;
|
||||
// using LambdaPtr = std_::unique_ptr<JustLambda>;
|
||||
// using Parent = lambda_wrap_helper_base<Return, Args...>;
|
||||
// static void construct_move_other_method(void *lambda, void *source) {
|
||||
// auto source_lambda = static_cast<LambdaPtr*>(source);
|
||||
// new (lambda) LambdaPtr(std_::move(*source_lambda));
|
||||
// }
|
||||
// static void construct_move_lambda_method(void *lambda, void *source) {
|
||||
// auto source_lambda = static_cast<JustLambda*>(source);
|
||||
// new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda)));
|
||||
// }
|
||||
// static Return call_method(const void *lambda, Args... args) {
|
||||
// return (**static_cast<const LambdaPtr*>(lambda))(std_::forward<Args>(args)...);
|
||||
// }
|
||||
// static void destruct_method(const void *lambda) {
|
||||
// static_cast<const LambdaPtr*>(lambda)->~LambdaPtr();
|
||||
// }
|
||||
// lambda_wrap_helper_move_impl() : Parent(
|
||||
// &Parent::bad_construct_copy,
|
||||
// &lambda_wrap_helper_move_impl::construct_move_other_method,
|
||||
// &lambda_wrap_helper_move_impl::call_method,
|
||||
// &lambda_wrap_helper_move_impl::destruct_method) {
|
||||
// }
|
||||
//
|
||||
//protected:
|
||||
// lambda_wrap_helper_move_impl(
|
||||
// typename Parent::construct_copy_other_type construct_copy_other
|
||||
// ) : Parent(
|
||||
// construct_copy_other,
|
||||
// &lambda_wrap_helper_move_impl::construct_move_other_method,
|
||||
// &lambda_wrap_helper_move_impl::call_method,
|
||||
// &lambda_wrap_helper_move_impl::destruct_method) {
|
||||
// }
|
||||
//
|
||||
//};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
|
||||
@@ -137,6 +145,12 @@ struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> :
|
||||
new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda));
|
||||
}
|
||||
static void construct_move_lambda_method(void *lambda, void *source) {
|
||||
static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment.");
|
||||
#ifndef OS_MAC_OLD
|
||||
auto space = sizeof(JustLambda);
|
||||
auto aligned = std::align(alignof(JustLambda), space, lambda, space);
|
||||
t_assert(aligned == lambda);
|
||||
#endif // OS_MAC_OLD
|
||||
auto source_lambda = static_cast<JustLambda*>(source);
|
||||
new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda));
|
||||
}
|
||||
@@ -177,23 +191,27 @@ const lambda_wrap_helper_move<Lambda, Return, Args...> lambda_wrap_helper_move<L
|
||||
|
||||
template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_copy_impl;
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
struct lambda_wrap_helper_copy_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> {
|
||||
using JustLambda = std_::decay_simple_t<Lambda>;
|
||||
using LambdaPtr = std_::unique_ptr<JustLambda>;
|
||||
using Parent = lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...>;
|
||||
static void construct_copy_other_method(void *lambda, const void *source) {
|
||||
auto source_lambda = static_cast<const LambdaPtr*>(source);
|
||||
new (lambda) LambdaPtr(std_::make_unique<JustLambda>(*source_lambda->get()));
|
||||
}
|
||||
static void construct_copy_lambda_method(void *lambda, const void *source) {
|
||||
auto source_lambda = static_cast<const JustLambda*>(source);
|
||||
new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<const JustLambda &>(*source_lambda)));
|
||||
}
|
||||
lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) {
|
||||
}
|
||||
|
||||
};
|
||||
//
|
||||
// Disable large lambda support.
|
||||
// If you really need it, just store data in some QSharedPointer<struct>.
|
||||
//
|
||||
//template <typename Lambda, typename Return, typename ...Args>
|
||||
//struct lambda_wrap_helper_copy_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> {
|
||||
// using JustLambda = std_::decay_simple_t<Lambda>;
|
||||
// using LambdaPtr = std_::unique_ptr<JustLambda>;
|
||||
// using Parent = lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...>;
|
||||
// static void construct_copy_other_method(void *lambda, const void *source) {
|
||||
// auto source_lambda = static_cast<const LambdaPtr*>(source);
|
||||
// new (lambda) LambdaPtr(std_::make_unique<JustLambda>(*source_lambda->get()));
|
||||
// }
|
||||
// static void construct_copy_lambda_method(void *lambda, const void *source) {
|
||||
// auto source_lambda = static_cast<const JustLambda*>(source);
|
||||
// new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<const JustLambda &>(*source_lambda)));
|
||||
// }
|
||||
// lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) {
|
||||
// }
|
||||
//
|
||||
//};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> {
|
||||
@@ -204,6 +222,12 @@ struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> :
|
||||
new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda));
|
||||
}
|
||||
static void construct_copy_lambda_method(void *lambda, const void *source) {
|
||||
static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment.");
|
||||
#ifndef OS_MAC_OLD
|
||||
auto space = sizeof(JustLambda);
|
||||
auto aligned = std::align(alignof(JustLambda), space, lambda, space);
|
||||
t_assert(aligned == lambda);
|
||||
#endif // OS_MAC_OLD
|
||||
auto source_lambda = static_cast<const JustLambda*>(source);
|
||||
new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda));
|
||||
}
|
||||
@@ -356,7 +380,7 @@ public:
|
||||
auto temp = other;
|
||||
this->helper_->destruct(this->storage_);
|
||||
this->helper_ = &internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance;
|
||||
internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_move_lambda_method(this->storage_, &other);
|
||||
internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_copy_lambda_method(this->storage_, &other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -373,48 +397,20 @@ public:
|
||||
|
||||
} // namespace base
|
||||
|
||||
// While we still use Function<>
|
||||
// While we still use rpcDone() and rpcFail()
|
||||
|
||||
#include "mtproto/rpc_sender.h"
|
||||
|
||||
template <typename FunctionType>
|
||||
struct LambdaFunctionHelper;
|
||||
struct LambdaUniqueHelper;
|
||||
|
||||
template <typename Lambda, typename R, typename ...Args>
|
||||
struct LambdaFunctionHelper<R(Lambda::*)(Args...) const> {
|
||||
using FunctionType = Function<R, Args...>;
|
||||
struct LambdaUniqueHelper<R(Lambda::*)(Args...) const> {
|
||||
using UniqueType = base::lambda_unique<R(Args...)>;
|
||||
};
|
||||
|
||||
template <typename FunctionType>
|
||||
using LambdaGetFunction = typename LambdaFunctionHelper<FunctionType>::FunctionType;
|
||||
|
||||
template <typename FunctionType>
|
||||
using LambdaGetUnique = typename LambdaFunctionHelper<FunctionType>::UniqueType;
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
class LambdaFunctionImplementation : public FunctionImplementation<R, Args...> {
|
||||
public:
|
||||
LambdaFunctionImplementation(base::lambda_unique<R(Args...)> &&lambda) : _lambda(std_::move(lambda)) {
|
||||
}
|
||||
R call(Args... args) override { return _lambda(std_::forward<Args>(args)...); }
|
||||
|
||||
private:
|
||||
base::lambda_unique<R(Args...)> _lambda;
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
inline Function<R, Args...> func_lambda_wrap_helper(base::lambda_unique<R(Args...)> &&lambda) {
|
||||
return Function<R, Args...>(new LambdaFunctionImplementation<R, Args...>(std_::move(lambda)));
|
||||
}
|
||||
|
||||
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
||||
inline LambdaGetFunction<decltype(&Lambda::operator())> func(Lambda &&lambda) {
|
||||
return func_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
||||
}
|
||||
|
||||
// While we still use rpcDone() and rpcFail()
|
||||
|
||||
#include "mtproto/rpc_sender.h"
|
||||
using LambdaGetUnique = typename LambdaUniqueHelper<FunctionType>::UniqueType;
|
||||
|
||||
template <typename Base, typename FunctionType>
|
||||
class RPCHandlerImplementation : public Base {
|
||||
|
@@ -21,99 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
#include "core/observer.h"
|
||||
|
||||
namespace Notify {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
struct StartCallbackData {
|
||||
void *that;
|
||||
StartCallback call;
|
||||
};
|
||||
struct FinishCallbackData {
|
||||
void *that;
|
||||
FinishCallback call;
|
||||
};
|
||||
struct UnregisterCallbackData {
|
||||
void *that;
|
||||
UnregisterCallback call;
|
||||
};
|
||||
using StartCallbacksList = QVector<StartCallbackData>;
|
||||
using FinishCallbacksList = QVector<FinishCallbackData>;
|
||||
NeverFreedPointer<StartCallbacksList> StartCallbacks;
|
||||
NeverFreedPointer<FinishCallbacksList> FinishCallbacks;
|
||||
UnregisterCallbackData UnregisterCallbacks[256]/* = { nullptr }*/;
|
||||
|
||||
ObservedEvent LastRegisteredEvent/* = 0*/;
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
|
||||
void startObservers() {
|
||||
if (!internal::StartCallbacks) return;
|
||||
|
||||
for (auto &callback : *internal::StartCallbacks) {
|
||||
callback.call(callback.that);
|
||||
}
|
||||
}
|
||||
|
||||
void finishObservers() {
|
||||
if (!internal::FinishCallbacks) return;
|
||||
|
||||
for (auto &callback : *internal::FinishCallbacks) {
|
||||
callback.call(callback.that);
|
||||
}
|
||||
internal::StartCallbacks.clear();
|
||||
internal::FinishCallbacks.clear();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
BaseObservedEventRegistrator::BaseObservedEventRegistrator(void *that
|
||||
, StartCallback startCallback
|
||||
, FinishCallback finishCallback
|
||||
, UnregisterCallback unregisterCallback) {
|
||||
_event = LastRegisteredEvent++;
|
||||
|
||||
StartCallbacks.makeIfNull();
|
||||
StartCallbacks->push_back({ that, startCallback });
|
||||
|
||||
FinishCallbacks.makeIfNull();
|
||||
FinishCallbacks->push_back({ that, finishCallback });
|
||||
|
||||
UnregisterCallbacks[_event] = { that, unregisterCallback };
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Observer base interface.
|
||||
Observer::~Observer() {
|
||||
for_const (auto connection, _connections) {
|
||||
unregisterObserver(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void Observer::observerRegistered(ConnectionId connection) {
|
||||
_connections.push_back(connection);
|
||||
}
|
||||
|
||||
void unregisterObserver(ConnectionId connection) {
|
||||
auto event = static_cast<internal::ObservedEvent>(connection >> 24);
|
||||
auto connectionIndex = int(connection & 0x00FFFFFFU) - 1;
|
||||
auto &callback = internal::UnregisterCallbacks[event];
|
||||
if (connectionIndex >= 0 && callback.call && callback.that) {
|
||||
callback.call(callback.that, connectionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
void observerRegisteredDefault(Observer *observer, ConnectionId connection) {
|
||||
observer->observerRegistered(connection);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Notify
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
@@ -22,230 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "core/vector_of_moveable.h"
|
||||
|
||||
namespace Notify {
|
||||
|
||||
using ConnectionId = uint32;
|
||||
|
||||
// startObservers() must be called after main() started (not in a global variable constructor).
|
||||
// finishObservers() must be called before main() finished (not in a global variable destructor).
|
||||
void startObservers();
|
||||
void finishObservers();
|
||||
|
||||
using StartObservedEventCallback = void(*)();
|
||||
using FinishObservedEventCallback = void(*)();
|
||||
|
||||
namespace internal {
|
||||
|
||||
using ObservedEvent = uchar;
|
||||
using StartCallback = void(*)(void*);
|
||||
using FinishCallback = void(*)(void*);
|
||||
using UnregisterCallback = void(*)(void*,int connectionIndex);
|
||||
|
||||
class BaseObservedEventRegistrator {
|
||||
public:
|
||||
BaseObservedEventRegistrator(void *that
|
||||
, StartCallback startCallback
|
||||
, FinishCallback finishCallback
|
||||
, UnregisterCallback unregisterCallback);
|
||||
|
||||
protected:
|
||||
inline ObservedEvent event() const {
|
||||
return _event;
|
||||
}
|
||||
|
||||
private:
|
||||
ObservedEvent _event;
|
||||
|
||||
};
|
||||
|
||||
// Handler is one of Function<> instantiations.
|
||||
template <typename Flags, typename Handler>
|
||||
struct ObserversList {
|
||||
struct Entry {
|
||||
Flags flags;
|
||||
Handler handler;
|
||||
};
|
||||
std_::vector_of_moveable<Entry> entries;
|
||||
QVector<int> freeIndices;
|
||||
};
|
||||
|
||||
// If no filtering by flags is done, you can use Flags=int and this value.
|
||||
constexpr int UniversalFlag = 0x01;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Objects of this class should be constructed in global scope.
|
||||
// startCallback will be called from Notify::startObservers().
|
||||
// finishCallback will be called from Notify::finishObservers().
|
||||
template <typename Flags, typename Handler>
|
||||
class ObservedEventRegistrator : public internal::BaseObservedEventRegistrator {
|
||||
public:
|
||||
ObservedEventRegistrator(StartObservedEventCallback startCallback,
|
||||
FinishObservedEventCallback finishCallback) : internal::BaseObservedEventRegistrator(static_cast<void*>(this),
|
||||
ObservedEventRegistrator<Flags, Handler>::start,
|
||||
ObservedEventRegistrator<Flags, Handler>::finish,
|
||||
ObservedEventRegistrator<Flags, Handler>::unregister)
|
||||
, _startCallback(startCallback), _finishCallback(finishCallback) {
|
||||
}
|
||||
|
||||
bool started() const {
|
||||
return _list != nullptr;
|
||||
}
|
||||
|
||||
ConnectionId registerObserver(Flags flags, Handler &&handler) {
|
||||
t_assert(started());
|
||||
|
||||
int connectionIndex = doRegisterObserver(flags, std_::forward<Handler>(handler));
|
||||
return (static_cast<uint32>(event()) << 24) | static_cast<uint32>(connectionIndex + 1);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void notify(Flags flags, Args&&... args) {
|
||||
t_assert(started());
|
||||
|
||||
auto &entries = _list->entries;
|
||||
// This way of iterating (i < entries.size() should be used
|
||||
// because some entries can be removed from the end of the
|
||||
// entries list while the loop is still running.
|
||||
for (int i = 0; i < entries.size(); ++i) {
|
||||
auto &entry = entries[i];
|
||||
if (!entry.handler.isNull() && (flags & entry.flags)) {
|
||||
entry.handler.call(std_::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using Self = ObservedEventRegistrator<Flags, Handler>;
|
||||
static void start(void *vthat) {
|
||||
Self *that = static_cast<Self*>(vthat);
|
||||
|
||||
t_assert(!that->started());
|
||||
if (that->_startCallback) that->_startCallback();
|
||||
that->_list = new internal::ObserversList<Flags, Handler>();
|
||||
}
|
||||
static void finish(void *vthat) {
|
||||
Self *that = static_cast<Self*>(vthat);
|
||||
|
||||
if (that->_finishCallback) that->_finishCallback();
|
||||
delete that->_list;
|
||||
that->_list = nullptr;
|
||||
}
|
||||
static void unregister(void *vthat, int connectionIndex) {
|
||||
Self *that = static_cast<Self*>(vthat);
|
||||
|
||||
t_assert(that->started());
|
||||
|
||||
auto &entries = that->_list->entries;
|
||||
if (entries.size() <= connectionIndex) return;
|
||||
|
||||
if (entries.size() == connectionIndex + 1) {
|
||||
for (entries.pop_back(); !entries.isEmpty() && entries.back().handler.isNull();) {
|
||||
entries.pop_back();
|
||||
}
|
||||
} else {
|
||||
entries[connectionIndex].handler = Handler();
|
||||
that->_list->freeIndices.push_back(connectionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
int doRegisterObserver(Flags flags, Handler &&handler) {
|
||||
while (!_list->freeIndices.isEmpty()) {
|
||||
auto freeIndex = _list->freeIndices.back();
|
||||
_list->freeIndices.pop_back();
|
||||
|
||||
if (freeIndex < _list->entries.size()) {
|
||||
_list->entries[freeIndex] = { flags, std_::move(handler) };
|
||||
return freeIndex;
|
||||
}
|
||||
}
|
||||
_list->entries.push_back({ flags, std_::move(handler) });
|
||||
return _list->entries.size() - 1;
|
||||
}
|
||||
|
||||
StartObservedEventCallback _startCallback;
|
||||
FinishObservedEventCallback _finishCallback;
|
||||
internal::ObserversList<Flags, Handler> *_list = nullptr;
|
||||
|
||||
};
|
||||
|
||||
// If no filtering of notifications by Flags is intended use this class.
|
||||
template <typename Handler>
|
||||
class SimpleObservedEventRegistrator {
|
||||
public:
|
||||
SimpleObservedEventRegistrator(StartObservedEventCallback startCallback,
|
||||
FinishObservedEventCallback finishCallback) : _implementation(startCallback, finishCallback) {
|
||||
}
|
||||
|
||||
bool started() const {
|
||||
return _implementation.started();
|
||||
}
|
||||
|
||||
ConnectionId registerObserver(Handler &&handler) {
|
||||
return _implementation.registerObserver(internal::UniversalFlag, std_::forward<Handler>(handler));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void notify(Args&&... args) {
|
||||
return _implementation.notify(internal::UniversalFlag, std_::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
ObservedEventRegistrator<int, Handler> _implementation;
|
||||
|
||||
};
|
||||
|
||||
// Each observer type should have observerRegistered(Notify::ConnectionId connection) method.
|
||||
// Usually it is done by deriving the type from the Notify::Observer base class.
|
||||
// In destructor it should call Notify::unregisterObserver(connection) for all the connections.
|
||||
|
||||
class Observer;
|
||||
namespace internal {
|
||||
void observerRegisteredDefault(Observer *observer, ConnectionId connection);
|
||||
} // namespace internal
|
||||
|
||||
void unregisterObserver(ConnectionId connection);
|
||||
|
||||
class Observer {
|
||||
public:
|
||||
virtual ~Observer() = 0;
|
||||
|
||||
private:
|
||||
void observerRegistered(ConnectionId connection);
|
||||
friend void internal::observerRegisteredDefault(Observer *observer, ConnectionId connection);
|
||||
|
||||
QVector<ConnectionId> _connections;
|
||||
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename ObserverType, int>
|
||||
struct ObserverRegisteredGeneric {
|
||||
static inline void call(ObserverType *observer, ConnectionId connection) {
|
||||
observer->observerRegistered(connection);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ObserverType>
|
||||
struct ObserverRegisteredGeneric<ObserverType, true> {
|
||||
static inline void call(ObserverType *observer, ConnectionId connection) {
|
||||
observerRegisteredDefault(observer, connection);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename ObserverType>
|
||||
inline void observerRegistered(ObserverType *observer, ConnectionId connection) {
|
||||
// For derivatives of the Observer class we call special friend function observerRegistered().
|
||||
// For all other classes we call just a member function observerRegistered().
|
||||
using ObserverRegistered = internal::ObserverRegisteredGeneric<ObserverType, std_::is_base_of<Observer, ObserverType>::value>;
|
||||
ObserverRegistered::call(observer, connection);
|
||||
}
|
||||
|
||||
} // namespace Notify
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
||||
@@ -271,10 +47,10 @@ using SubscriptionHandler = typename SubscriptionHandlerHelper<EventType>::type;
|
||||
class BaseObservableData {
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservableData;
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
class ObservableData;
|
||||
|
||||
} // namespace internal
|
||||
@@ -317,43 +93,41 @@ private:
|
||||
Node *_node = nullptr;
|
||||
RemoveMethod _removeMethod;
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
friend class internal::CommonObservableData;
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
friend class internal::ObservableData;
|
||||
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
class Observable;
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservable {
|
||||
public:
|
||||
using Handler = typename CommonObservableData<EventType>::Handler;
|
||||
|
||||
Subscription add_subscription(Handler &&handler) {
|
||||
if (!_data) {
|
||||
_data = MakeShared<ObservableData<EventType>>(this);
|
||||
_data = MakeShared<ObservableData<EventType, Handler>>(this);
|
||||
}
|
||||
return _data->append(std_::forward<Handler>(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
QSharedPointer<ObservableData<EventType>> _data;
|
||||
QSharedPointer<ObservableData<EventType, Handler>> _data;
|
||||
|
||||
friend class CommonObservableData<EventType>;
|
||||
friend class Observable<EventType>;
|
||||
friend class CommonObservableData<EventType, Handler>;
|
||||
friend class Observable<EventType, Handler>;
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename EventType>
|
||||
class Observable : public internal::CommonObservable<EventType> {
|
||||
template <typename EventType, typename Handler = internal::SubscriptionHandler<EventType>>
|
||||
class Observable : public internal::CommonObservable<EventType, Handler> {
|
||||
public:
|
||||
void notify(EventType &&event, bool sync = false) {
|
||||
if (this->_data) {
|
||||
@@ -368,12 +142,10 @@ public:
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename EventType>
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservableData : public BaseObservableData {
|
||||
public:
|
||||
using Handler = SubscriptionHandler<EventType>;
|
||||
|
||||
CommonObservableData(CommonObservable<EventType> *observable) : _observable(observable) {
|
||||
CommonObservableData(CommonObservable<EventType, Handler> *observable) : _observable(observable) {
|
||||
}
|
||||
|
||||
Subscription append(Handler &&handler) {
|
||||
@@ -444,20 +216,20 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
CommonObservable<EventType> *_observable = nullptr;
|
||||
CommonObservable<EventType, Handler> *_observable = nullptr;
|
||||
Node *_begin = nullptr;
|
||||
Node *_current = nullptr;
|
||||
Node *_end = nullptr;
|
||||
ObservableCallHandlers _callHandlers;
|
||||
|
||||
friend class ObservableData<EventType>;
|
||||
friend class ObservableData<EventType, Handler>;
|
||||
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
class ObservableData : public CommonObservableData<EventType> {
|
||||
template <typename EventType, typename Handler>
|
||||
class ObservableData : public CommonObservableData<EventType, Handler> {
|
||||
public:
|
||||
using CommonObservableData<EventType>::CommonObservableData;
|
||||
using CommonObservableData<EventType, Handler>::CommonObservableData;
|
||||
|
||||
void notify(EventType &&event, bool sync) {
|
||||
if (_handling) {
|
||||
@@ -501,10 +273,10 @@ private:
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
class ObservableData<void> : public CommonObservableData<void> {
|
||||
template <class Handler>
|
||||
class ObservableData<void, Handler> : public CommonObservableData<void, Handler> {
|
||||
public:
|
||||
using CommonObservableData<void>::CommonObservableData;
|
||||
using CommonObservableData<void, Handler>::CommonObservableData;
|
||||
|
||||
void notify(bool sync) {
|
||||
if (_handling) {
|
||||
@@ -514,20 +286,20 @@ public:
|
||||
++_eventsCount;
|
||||
callHandlers();
|
||||
} else {
|
||||
if (!_callHandlers) {
|
||||
_callHandlers = [this]() {
|
||||
if (!this->_callHandlers) {
|
||||
this->_callHandlers = [this]() {
|
||||
callHandlers();
|
||||
};
|
||||
}
|
||||
if (!_eventsCount) {
|
||||
RegisterPendingObservable(&_callHandlers);
|
||||
RegisterPendingObservable(&this->_callHandlers);
|
||||
}
|
||||
++_eventsCount;
|
||||
}
|
||||
}
|
||||
|
||||
~ObservableData() {
|
||||
UnregisterObservable(&_callHandlers);
|
||||
UnregisterObservable(&this->_callHandlers);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -535,12 +307,12 @@ private:
|
||||
_handling = true;
|
||||
auto eventsCount = createAndSwap(_eventsCount);
|
||||
for (int i = 0; i != eventsCount; ++i) {
|
||||
notifyEnumerate([this]() {
|
||||
_current->handler();
|
||||
this->notifyEnumerate([this]() {
|
||||
this->_current->handler();
|
||||
});
|
||||
}
|
||||
_handling = false;
|
||||
UnregisterActiveObservable(&_callHandlers);
|
||||
UnregisterActiveObservable(&this->_callHandlers);
|
||||
}
|
||||
|
||||
int _eventsCount = 0;
|
||||
@@ -550,12 +322,12 @@ private:
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <>
|
||||
class Observable<void> : public internal::CommonObservable<void> {
|
||||
template <typename Handler>
|
||||
class Observable<void, Handler> : public internal::CommonObservable<void, Handler> {
|
||||
public:
|
||||
void notify(bool sync = false) {
|
||||
if (_data) {
|
||||
_data->notify(sync);
|
||||
if (this->_data) {
|
||||
this->_data->notify(sync);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,14 +335,14 @@ public:
|
||||
|
||||
class Subscriber {
|
||||
protected:
|
||||
template <typename EventType, typename Lambda>
|
||||
int subscribe(base::Observable<EventType> &observable, Lambda &&handler) {
|
||||
template <typename EventType, typename Handler, typename Lambda>
|
||||
int subscribe(base::Observable<EventType, Handler> &observable, Lambda &&handler) {
|
||||
_subscriptions.push_back(observable.add_subscription(std_::forward<Lambda>(handler)));
|
||||
return _subscriptions.size() - 1;
|
||||
}
|
||||
|
||||
template <typename EventType, typename Lambda>
|
||||
int subscribe(base::Observable<EventType> *observable, Lambda &&handler) {
|
||||
template <typename EventType, typename Handler, typename Lambda>
|
||||
int subscribe(base::Observable<EventType, Handler> *observable, Lambda &&handler) {
|
||||
return subscribe(*observable, std_::forward<Lambda>(handler));
|
||||
}
|
||||
|
||||
|
@@ -93,6 +93,7 @@ public:
|
||||
*prev = std_::move(*next);
|
||||
}
|
||||
--_size;
|
||||
end()->~T();
|
||||
return it;
|
||||
}
|
||||
|
||||
@@ -143,15 +144,21 @@ public:
|
||||
}
|
||||
inline const T &at(int index) const {
|
||||
if (index < 0 || index >= _size) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
||||
throw std::exception();
|
||||
#else // QT_VERSION < 5.5.0
|
||||
#ifndef OS_MAC_OLD
|
||||
throw std::out_of_range("");
|
||||
#endif // QT_VERSION < 5.5.0
|
||||
#else // OS_MAC_OLD
|
||||
throw std::exception();
|
||||
#endif // OS_MAC_OLD
|
||||
}
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
void reserve(int newCapacity) {
|
||||
if (newCapacity > _capacity) {
|
||||
reallocate(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
inline ~vector_of_moveable() {
|
||||
clear();
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "core/basic_types.h"
|
||||
|
||||
#define BETA_VERSION_MACRO (0ULL)
|
||||
#define BETA_VERSION_MACRO (10008001ULL)
|
||||
|
||||
constexpr int AppVersion = 10008;
|
||||
constexpr str_const AppVersionStr = "0.10.8";
|
||||
|
Reference in New Issue
Block a user