2
0
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:
John Preston
2016-09-29 00:16:02 +03:00
114 changed files with 743 additions and 1196 deletions

View File

@@ -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));
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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));
}

View File

@@ -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();
}

View File

@@ -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";