mirror of https://github.com/procxx/kepka.git
Add lambda-based checked timers.
Also ApiWrap is now not a QObject.
This commit is contained in:
parent
6b242a982b
commit
34ab04cbe6
|
@ -36,15 +36,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kReloadChannelMembersTimeout = 1000; // 1 second wait before reload members in channel after adding
|
constexpr auto kReloadChannelMembersTimeout = 1000; // 1 second wait before reload members in channel after adding
|
||||||
|
constexpr auto kSaveCloudDraftTimeout = 1000; // save draft to the cloud with 1 sec extra delay
|
||||||
constexpr auto kSmallDelayMs = 5;
|
constexpr auto kSmallDelayMs = 5;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ApiWrap::ApiWrap() : _messageDataResolveDelayed([this] { resolveMessageDatas(); }) {
|
ApiWrap::ApiWrap()
|
||||||
|
: _messageDataResolveDelayed([this] { resolveMessageDatas(); })
|
||||||
|
, _webPagesTimer([this] { resolveWebPages(); })
|
||||||
|
, _draftsSaveTimer([this] { saveDraftsToCloud(); }) {
|
||||||
Window::Theme::Background()->start();
|
Window::Theme::Background()->start();
|
||||||
|
|
||||||
connect(&_webPagesTimer, &QTimer::timeout, [this] { resolveWebPages(); });
|
|
||||||
connect(&_draftsSaveTimer, &QTimer::timeout, [this] { saveDraftsToCloud(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback) {
|
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback) {
|
||||||
|
@ -948,7 +949,7 @@ void ApiWrap::requestNotifySetting(PeerData *peer) {
|
||||||
void ApiWrap::saveDraftToCloudDelayed(History *history) {
|
void ApiWrap::saveDraftToCloudDelayed(History *history) {
|
||||||
_draftsSaveRequestIds.insert(history, 0);
|
_draftsSaveRequestIds.insert(history, 0);
|
||||||
if (!_draftsSaveTimer.isActive()) {
|
if (!_draftsSaveTimer.isActive()) {
|
||||||
_draftsSaveTimer.start(SaveCloudDraftTimeout);
|
_draftsSaveTimer.callOnce(kSaveCloudDraftTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,20 +1264,22 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
||||||
void ApiWrap::requestWebPageDelayed(WebPageData *page) {
|
void ApiWrap::requestWebPageDelayed(WebPageData *page) {
|
||||||
if (page->pendingTill <= 0) return;
|
if (page->pendingTill <= 0) return;
|
||||||
_webPagesPending.insert(page, 0);
|
_webPagesPending.insert(page, 0);
|
||||||
int32 left = (page->pendingTill - unixtime()) * 1000;
|
auto left = (page->pendingTill - unixtime()) * 1000;
|
||||||
if (!_webPagesTimer.isActive() || left <= _webPagesTimer.remainingTime()) {
|
if (!_webPagesTimer.isActive() || left <= _webPagesTimer.remainingTime()) {
|
||||||
_webPagesTimer.start((left < 0 ? 0 : left) + 1);
|
_webPagesTimer.callOnce((left < 0 ? 0 : left) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::clearWebPageRequest(WebPageData *page) {
|
void ApiWrap::clearWebPageRequest(WebPageData *page) {
|
||||||
_webPagesPending.remove(page);
|
_webPagesPending.remove(page);
|
||||||
if (_webPagesPending.isEmpty() && _webPagesTimer.isActive()) _webPagesTimer.stop();
|
if (_webPagesPending.isEmpty() && _webPagesTimer.isActive()) {
|
||||||
|
_webPagesTimer.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::clearWebPageRequests() {
|
void ApiWrap::clearWebPageRequests() {
|
||||||
_webPagesPending.clear();
|
_webPagesPending.clear();
|
||||||
_webPagesTimer.stop();
|
_webPagesTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::resolveWebPages() {
|
void ApiWrap::resolveWebPages() {
|
||||||
|
@ -1342,11 +1345,13 @@ void ApiWrap::resolveWebPages() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m < INT_MAX) _webPagesTimer.start(m * 1000);
|
if (m < INT_MAX) {
|
||||||
|
_webPagesTimer.callOnce(m * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestParticipantsCountDelayed(ChannelData *channel) {
|
void ApiWrap::requestParticipantsCountDelayed(ChannelData *channel) {
|
||||||
QTimer::singleShot(kReloadChannelMembersTimeout, this, [this, channel] {
|
_participantsCountRequestTimer.call(kReloadChannelMembersTimeout, [this, channel] {
|
||||||
channel->updateFull(true);
|
channel->updateFull(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/timer.h"
|
||||||
#include "core/single_timer.h"
|
#include "core/single_timer.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Cha
|
||||||
|
|
||||||
} // namespace Api
|
} // namespace Api
|
||||||
|
|
||||||
class ApiWrap : public QObject, private MTP::Sender {
|
class ApiWrap : private MTP::Sender {
|
||||||
public:
|
public:
|
||||||
ApiWrap();
|
ApiWrap();
|
||||||
|
|
||||||
|
@ -124,6 +125,7 @@ private:
|
||||||
|
|
||||||
PeerRequests _participantsRequests;
|
PeerRequests _participantsRequests;
|
||||||
PeerRequests _botsRequests;
|
PeerRequests _botsRequests;
|
||||||
|
base::DelayedCallTimer _participantsCountRequestTimer;
|
||||||
|
|
||||||
typedef QPair<PeerData*, UserData*> KickRequest;
|
typedef QPair<PeerData*, UserData*> KickRequest;
|
||||||
typedef QMap<KickRequest, mtpRequestId> KickRequests;
|
typedef QMap<KickRequest, mtpRequestId> KickRequests;
|
||||||
|
@ -132,7 +134,7 @@ private:
|
||||||
QMap<ChannelData*, mtpRequestId> _selfParticipantRequests;
|
QMap<ChannelData*, mtpRequestId> _selfParticipantRequests;
|
||||||
|
|
||||||
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
||||||
SingleTimer _webPagesTimer;
|
base::Timer _webPagesTimer;
|
||||||
|
|
||||||
QMap<uint64, QPair<uint64, mtpRequestId> > _stickerSetRequests;
|
QMap<uint64, QPair<uint64, mtpRequestId> > _stickerSetRequests;
|
||||||
|
|
||||||
|
@ -143,7 +145,7 @@ private:
|
||||||
QMap<PeerData*, mtpRequestId> _notifySettingRequests;
|
QMap<PeerData*, mtpRequestId> _notifySettingRequests;
|
||||||
|
|
||||||
QMap<History*, mtpRequestId> _draftsSaveRequestIds;
|
QMap<History*, mtpRequestId> _draftsSaveRequestIds;
|
||||||
SingleTimer _draftsSaveTimer;
|
base::Timer _draftsSaveTimer;
|
||||||
|
|
||||||
OrderedSet<mtpRequestId> _stickerSetDisenableRequests;
|
OrderedSet<mtpRequestId> _stickerSetDisenableRequests;
|
||||||
Stickers::Order _stickersOrder;
|
Stickers::Order _stickersOrder;
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "autoupdater.h"
|
#include "autoupdater.h"
|
||||||
#include "window/notifications_manager.h"
|
#include "window/notifications_manager.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -546,6 +547,7 @@ void adjustSingleTimers() {
|
||||||
if (auto a = application()) {
|
if (auto a = application()) {
|
||||||
a->adjustSingleTimers();
|
a->adjustSingleTimers();
|
||||||
}
|
}
|
||||||
|
base::Timer::Adjust();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QObject *TimersAdjuster() {
|
||||||
|
static QObject adjuster;
|
||||||
|
return &adjuster;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Timer::Timer(base::lambda<void()> callback) : QObject(nullptr)
|
||||||
|
, _callback(std::move(callback))
|
||||||
|
, _type(Qt::PreciseTimer)
|
||||||
|
, _adjusted(false)
|
||||||
|
, _repeat(Repeat::Interval) {
|
||||||
|
connect(TimersAdjuster(), &QObject::destroyed, this, [this] { adjust(); }, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::start(TimeMs timeout, Qt::TimerType type, Repeat repeat) {
|
||||||
|
cancel();
|
||||||
|
|
||||||
|
_type = type;
|
||||||
|
_repeat = repeat;
|
||||||
|
_adjusted = false;
|
||||||
|
setTimeout(timeout);
|
||||||
|
_timerId = startTimer(_timeout, _type);
|
||||||
|
if (_timerId) {
|
||||||
|
_next = getms(true) + _timeout;
|
||||||
|
} else {
|
||||||
|
_next = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::cancel() {
|
||||||
|
if (isActive()) {
|
||||||
|
killTimer(base::take(_timerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeMs Timer::remainingTime() const {
|
||||||
|
if (!isActive()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto now = getms(true);
|
||||||
|
return (_next > now) ? (_next - now) : TimeMs(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::Adjust() {
|
||||||
|
QObject emitter;
|
||||||
|
connect(&emitter, &QObject::destroyed, TimersAdjuster(), &QObject::destroyed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::adjust() {
|
||||||
|
auto remaining = remainingTime();
|
||||||
|
if (remaining >= 0) {
|
||||||
|
cancel();
|
||||||
|
_timerId = startTimer(remaining, _type);
|
||||||
|
_adjusted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::setTimeout(TimeMs timeout) {
|
||||||
|
Expects(timeout >= 0 && timeout <= std::numeric_limits<int>::max());
|
||||||
|
_timeout = static_cast<unsigned int>(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Timer::timeout() const {
|
||||||
|
return _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::timerEvent(QTimerEvent *e) {
|
||||||
|
if (_repeat == Repeat::Interval) {
|
||||||
|
if (_adjusted) {
|
||||||
|
start(_timeout, _type, _repeat);
|
||||||
|
} else {
|
||||||
|
_next = getms(true) + _timeout;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_callback) {
|
||||||
|
_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DelayedCallTimer::call(TimeMs timeout, lambda_once<void()> callback, Qt::TimerType type) {
|
||||||
|
Expects(timeout >= 0);
|
||||||
|
if (!callback) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto timerId = startTimer(static_cast<int>(timeout), type);
|
||||||
|
if (timerId) {
|
||||||
|
_callbacks.emplace(timerId, std::move(callback));
|
||||||
|
}
|
||||||
|
return timerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedCallTimer::cancel(int callId) {
|
||||||
|
if (callId) {
|
||||||
|
killTimer(callId);
|
||||||
|
_callbacks.erase(callId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedCallTimer::timerEvent(QTimerEvent *e) {
|
||||||
|
auto timerId = e->timerId();
|
||||||
|
killTimer(timerId);
|
||||||
|
|
||||||
|
auto it = _callbacks.find(timerId);
|
||||||
|
if (it != _callbacks.end()) {
|
||||||
|
auto callback = std::move(it->second);
|
||||||
|
_callbacks.erase(it);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace base
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/lambda.h"
|
||||||
|
#include "base/observer.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
|
class Timer final : private QObject {
|
||||||
|
public:
|
||||||
|
Timer(base::lambda<void()> callback = base::lambda<void()>());
|
||||||
|
|
||||||
|
static Qt::TimerType DefaultType(TimeMs timeout) {
|
||||||
|
constexpr auto kThreshold = TimeMs(1000);
|
||||||
|
return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCallback(base::lambda<void()> callback) {
|
||||||
|
_callback = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callOnce(TimeMs timeout) {
|
||||||
|
callOnce(timeout, DefaultType(timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
void callEach(TimeMs timeout) {
|
||||||
|
callEach(timeout, DefaultType(timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
void callOnce(TimeMs timeout, Qt::TimerType type) {
|
||||||
|
start(timeout, type, Repeat::SingleShot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callEach(TimeMs timeout, Qt::TimerType type) {
|
||||||
|
start(timeout, type, Repeat::Interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isActive() const {
|
||||||
|
return (_timerId != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel();
|
||||||
|
TimeMs remainingTime() const;
|
||||||
|
|
||||||
|
static void Adjust();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Repeat {
|
||||||
|
Interval = 0,
|
||||||
|
SingleShot = 1,
|
||||||
|
};
|
||||||
|
void start(TimeMs timeout, Qt::TimerType type, Repeat repeat);
|
||||||
|
void adjust();
|
||||||
|
|
||||||
|
void setTimeout(TimeMs timeout);
|
||||||
|
int timeout() const;
|
||||||
|
|
||||||
|
base::lambda<void()> _callback;
|
||||||
|
TimeMs _next = 0;
|
||||||
|
int _timeout = 0;
|
||||||
|
int _timerId = 0;
|
||||||
|
|
||||||
|
Qt::TimerType _type : 2;
|
||||||
|
bool _adjusted : 1;
|
||||||
|
Repeat _repeat : 1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class DelayedCallTimer final : private QObject {
|
||||||
|
public:
|
||||||
|
int call(TimeMs timeout, lambda_once<void()> callback) {
|
||||||
|
return call(timeout, std::move(callback), Timer::DefaultType(timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
int call(TimeMs timeout, lambda_once<void()> callback, Qt::TimerType type);
|
||||||
|
void cancel(int callId);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<int, lambda_once<void()>> _callbacks; // Better to use flatmap.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace base
|
|
@ -124,7 +124,6 @@ enum {
|
||||||
SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text
|
SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text
|
||||||
SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs
|
SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs
|
||||||
SaveCloudDraftIdleTimeout = 14000, // save draft to the cloud after 14 more seconds
|
SaveCloudDraftIdleTimeout = 14000, // save draft to the cloud after 14 more seconds
|
||||||
SaveCloudDraftTimeout = 1000, // save draft to the cloud with 1 sec extra delay
|
|
||||||
SaveDraftBeforeQuitTimeout = 1500, // give the app 1.5 secs to save drafts to cloud when quitting
|
SaveDraftBeforeQuitTimeout = 1500, // give the app 1.5 secs to save drafts to cloud when quitting
|
||||||
|
|
||||||
SetOnlineAfterActivity = 30, // user with hidden last seen stays online for such amount of seconds in the interface
|
SetOnlineAfterActivity = 30, // user with hidden last seen stays online for such amount of seconds in the interface
|
||||||
|
|
|
@ -362,7 +362,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
gsl::not_null<Instance*> _instance;
|
gsl::not_null<Instance*> _instance;
|
||||||
std::set<RequestWrap, RequestWrapComparator> _requests;
|
std::set<RequestWrap, RequestWrapComparator> _requests; // Better to use flatmap.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,10 @@
|
||||||
<(src_loc)/base/qthelp_url.h
|
<(src_loc)/base/qthelp_url.h
|
||||||
<(src_loc)/base/runtime_composer.cpp
|
<(src_loc)/base/runtime_composer.cpp
|
||||||
<(src_loc)/base/runtime_composer.h
|
<(src_loc)/base/runtime_composer.h
|
||||||
<(src_loc)/base/task_queue.h
|
|
||||||
<(src_loc)/base/task_queue.cpp
|
<(src_loc)/base/task_queue.cpp
|
||||||
|
<(src_loc)/base/task_queue.h
|
||||||
|
<(src_loc)/base/timer.cpp
|
||||||
|
<(src_loc)/base/timer.h
|
||||||
<(src_loc)/base/type_traits.h
|
<(src_loc)/base/type_traits.h
|
||||||
<(src_loc)/base/variant.h
|
<(src_loc)/base/variant.h
|
||||||
<(src_loc)/base/virtual_method.h
|
<(src_loc)/base/virtual_method.h
|
||||||
|
|
Loading…
Reference in New Issue