SetWithPosition CE and other fixes.

GitOrigin-RevId: 69278e7906c738924e1a4771b5b755ff349ea26f
This commit is contained in:
levlam 2019-01-19 20:19:29 +03:00
parent b2ad399bc9
commit cdefe9b1ee
12 changed files with 150 additions and 96 deletions

View File

@ -11,14 +11,12 @@
#include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileManager.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/MessagesManager.h" #include "td/telegram/MessagesManager.h"
#include "td/telegram/WallpaperManager.h"
#include "td/telegram/WebPagesManager.h" #include "td/telegram/WebPagesManager.h"
#include "td/actor/MultiPromise.h" #include "td/utils/logging.h"
#include "td/utils/format.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/overloaded.h" #include "td/utils/overloaded.h"
#include "td/utils/Variant.h"
namespace td { namespace td {

View File

@ -9,15 +9,16 @@
#include "td/actor/actor.h" #include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h" #include "td/actor/PromiseFuture.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/ChannelId.h" #include "td/telegram/ChannelId.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileSourceId.h" #include "td/telegram/files/FileSourceId.h"
#include "td/telegram/MessageId.h" #include "td/telegram/MessageId.h"
#include "td/telegram/SetWithPosition.h" #include "td/telegram/SetWithPosition.h"
#include "td/telegram/UserId.h" #include "td/telegram/UserId.h"
#include "td/utils/logging.h"
#include "td/utils/Status.h"
#include "td/utils/Variant.h" #include "td/utils/Variant.h"
#include <unordered_map> #include <unordered_map>

View File

@ -3158,8 +3158,7 @@ static auto secret_to_telegram(secret_api::fileLocationUnavailable &file_locatio
// fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation; // fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
static auto secret_to_telegram(secret_api::fileLocation &file_location) { static auto secret_to_telegram(secret_api::fileLocation &file_location) {
return make_tl_object<telegram_api::fileLocation>(file_location.dc_id_, file_location.volume_id_, return make_tl_object<telegram_api::fileLocation>(file_location.dc_id_, file_location.volume_id_,
file_location.local_id_, file_location.secret_, file_location.local_id_, file_location.secret_, BufferSlice());
BufferSlice());
} }
// photoSizeEmpty#e17e23c type:string = PhotoSize; // photoSizeEmpty#e17e23c type:string = PhotoSize;
@ -3307,9 +3306,9 @@ static auto secret_to_telegram_document(secret_api::decryptedMessageMediaExterna
if (!clean_input_string(from.mime_type_)) { if (!clean_input_string(from.mime_type_)) {
from.mime_type_.clear(); from.mime_type_.clear();
} }
return make_tl_object<telegram_api::document>( return make_tl_object<telegram_api::document>(from.id_, from.access_hash_, BufferSlice(), from.date_, from.mime_type_,
from.id_, from.access_hash_, BufferSlice(), from.date_, from.mime_type_, from.size_, from.size_, secret_to_telegram<telegram_api::PhotoSize>(*from.thumb_),
secret_to_telegram<telegram_api::PhotoSize>(*from.thumb_), from.dc_id_, secret_to_telegram(from.attributes_)); from.dc_id_, secret_to_telegram(from.attributes_));
} }
template <class ToT, class FromT> template <class ToT, class FromT>

View File

@ -5,41 +5,58 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include <set> #include <set>
#include <utility>
namespace td { namespace td {
template <class T> template <class T>
class FastSetWithPosition { class FastSetWithPosition {
public: public:
void add(int x) { void add(T x) {
if (checked_.count(x) != 0) { if (checked_.count(x) != 0) {
return; return;
} }
not_checked_.insert(x); not_checked_.insert(x);
} }
void remove(int x) {
void remove(T x) {
checked_.erase(x); checked_.erase(x);
not_checked_.erase(x); not_checked_.erase(x);
} }
bool has_next() {
bool has_next() const {
return !not_checked_.empty(); return !not_checked_.empty();
} }
void reset_position() { void reset_position() {
not_checked_.insert(checked_.begin(), checked_.end()); if (not_checked_.empty()) {
checked_ = {}; not_checked_ = std::move(checked_);
} else {
not_checked_.insert(checked_.begin(), checked_.end());
}
reset_to_empty(checked_);
} }
T next() { T next() {
CHECK(has_next()); CHECK(has_next());
auto res = *not_checked_.begin(); auto it = not_checked_.begin();
not_checked_.erase(not_checked_.begin()); auto res = *it;
not_checked_.erase(it);
checked_.insert(res); checked_.insert(res);
return res; return res;
} }
void merge(FastSetWithPosition &&other) { void merge(FastSetWithPosition &&other) {
if (this == &other) {
return;
}
if (size() < other.size()) { if (size() < other.size()) {
std::swap(*this, other); std::swap(*this, other);
} }
@ -47,6 +64,7 @@ class FastSetWithPosition {
not_checked_.erase(x); not_checked_.erase(x);
checked_.insert(x); checked_.insert(x);
} }
for (auto x : other.not_checked_) { for (auto x : other.not_checked_) {
if (checked_.count(x) != 0) { if (checked_.count(x) != 0) {
continue; continue;
@ -54,6 +72,7 @@ class FastSetWithPosition {
not_checked_.insert(x); not_checked_.insert(x);
} }
} }
size_t size() const { size_t size() const {
return checked_.size() + not_checked_.size(); return checked_.size() + not_checked_.size();
} }
@ -66,7 +85,7 @@ class FastSetWithPosition {
template <class T> template <class T>
class SetWithPosition { class SetWithPosition {
public: public:
void add(int x) { void add(T x) {
if (fast_) { if (fast_) {
fast_->add(x); fast_->add(x);
return; return;
@ -74,7 +93,7 @@ class SetWithPosition {
if (!has_value_) { if (!has_value_) {
value_ = x; value_ = x;
has_value_ = true; has_value_ = true;
is_cheched_ = false; is_checked_ = false;
return; return;
} }
if (value_ == x) { if (value_ == x) {
@ -83,28 +102,31 @@ class SetWithPosition {
make_fast(); make_fast();
fast_->add(x); fast_->add(x);
} }
void remove(int x) {
void remove(T x) {
if (fast_) { if (fast_) {
fast_->remove(x); fast_->remove(x);
return; return;
} }
if (has_value_ && value_ == x) { if (has_value_ && value_ == x) {
has_value_ = false; has_value_ = false;
is_cheched_ = false; is_checked_ = false;
} }
} }
bool has_next() {
bool has_next() const {
if (fast_) { if (fast_) {
return fast_->has_next(); return fast_->has_next();
} }
return has_value_ && !is_cheched_; return has_value_ && !is_checked_;
} }
void reset_position() { void reset_position() {
if (fast_) { if (fast_) {
fast_->reset_position(); fast_->reset_position();
return; return;
} }
is_cheched_ = false; is_checked_ = false;
} }
T next() { T next() {
@ -112,33 +134,46 @@ class SetWithPosition {
if (fast_) { if (fast_) {
return fast_->next(); return fast_->next();
} }
is_cheched_ = true; is_checked_ = true;
return value_; return value_;
} }
void merge(SetWithPosition &&other) { void merge(SetWithPosition &&other) {
if (this == &other) {
return;
}
if (size() < other.size()) { if (size() < other.size()) {
std::swap(*this, other); std::swap(*this, other);
} }
if (other.size() == 0) { if (other.size() == 0) {
return; return;
} }
if (other.fast_ == nullptr && fast_ == nullptr && value_ == other.value_) {
is_checked_ |= other.is_checked_;
other.value_ = T();
other.has_value_ = false;
other.is_checked_ = false;
return;
}
make_fast(); make_fast();
other.make_fast(); other.make_fast();
fast_->merge(std::move(*other.fast_)); fast_->merge(std::move(*other.fast_));
reset_to_empty(other);
} }
size_t size() const { size_t size() const {
if (fast_) { if (fast_) {
return fast_->size(); return fast_->size();
} }
return has_value_; return static_cast<size_t>(has_value_);
} }
private: private:
T value_; T value_{};
bool has_value_{false}; bool has_value_{false};
bool is_cheched_{false}; bool is_checked_{false};
unique_ptr<FastSetWithPosition<T>> fast_; unique_ptr<FastSetWithPosition<T>> fast_;
void make_fast() { void make_fast() {
if (fast_) { if (fast_) {
return; return;
@ -146,61 +181,10 @@ class SetWithPosition {
fast_ = make_unique<FastSetWithPosition<T>>(); fast_ = make_unique<FastSetWithPosition<T>>();
CHECK(has_value_); CHECK(has_value_);
fast_->add(value_); fast_->add(value_);
if (is_cheched_) { if (is_checked_) {
fast_->next(); fast_->next();
} }
} }
}; };
template <class T>
class OldSetWithPosition {
public:
void add(T value) {
auto it = std::find(values_.begin(), values_.end(), value);
if (it != end(values_)) {
return;
}
values_.push_back(value);
}
void remove(T value) {
auto it = std::find(values_.begin(), values_.end(), value);
if (it == end(values_)) {
return;
}
size_t i = it - values_.begin();
values_.erase(it);
if (pos_ > i) {
pos_--;
}
}
void reset_position() {
pos_ = 0;
}
T next() {
return values_[pos_++];
}
bool has_next() {
return pos_ < values_.size();
}
void merge(OldSetWithPosition &&other) {
OldSetWithPosition res;
for (size_t i = 0; i < pos_; i++) {
res.add(values_[i]);
}
for (size_t i = 0; i < other.pos_; i++) {
res.add(other.values_[i]);
}
res.pos_ = res.values_.size();
for (size_t i = pos_; i < values_.size(); i++) {
res.add(values_[i]);
}
for (size_t i = other.pos_; i < other.values_.size(); i++) {
res.add(other.values_[i]);
}
*this = std::move(res);
}
private:
std::vector<T> values_;
size_t pos_{0};
};
} // namespace td } // namespace td

View File

@ -8,8 +8,8 @@
#include "td/telegram/TdParameters.h" #include "td/telegram/TdParameters.h"
#include "td/db/binlog/BinlogInterface.h"
#include "td/db/binlog/BinlogEvent.h" #include "td/db/binlog/BinlogEvent.h"
#include "td/db/binlog/BinlogInterface.h"
#include "td/db/DbKey.h" #include "td/db/DbKey.h"
#include "td/db/KeyValueSyncInterface.h" #include "td/db/KeyValueSyncInterface.h"

View File

@ -9,10 +9,13 @@
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/utils/buffer.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
namespace td { namespace td {

View File

@ -8,6 +8,7 @@
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h" #include "td/actor/PromiseFuture.h"

View File

@ -19,7 +19,7 @@ class FileDbId {
public: public:
FileDbId() = default; FileDbId() = default;
FileDbId(uint64 file_db_id) : id(file_db_id) { explicit FileDbId(uint64 file_db_id) : id(file_db_id) {
} }
template <class T1, typename = std::enable_if_t<std::is_convertible<T1, uint64>::value>> template <class T1, typename = std::enable_if_t<std::is_convertible<T1, uint64>::value>>
FileDbId(T1 file_db_id) = delete; FileDbId(T1 file_db_id) = delete;

View File

@ -8,6 +8,7 @@
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileManager.hpp" #include "td/telegram/files/FileManager.hpp"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"

View File

@ -33,6 +33,10 @@ class FileSourceId {
return id; return id;
} }
bool operator<(const FileSourceId &other) const {
return id < other.id;
}
bool operator==(const FileSourceId &other) const { bool operator==(const FileSourceId &other) const {
return id == other.id; return id == other.id;
} }

View File

@ -6,9 +6,9 @@
// //
#include "td/db/binlog/BinlogHelper.h" #include "td/db/binlog/BinlogHelper.h"
#include "td/db/binlog/ConcurrentBinlog.h" #include "td/db/binlog/ConcurrentBinlog.h"
#include "td/db/SqliteConnectionSafe.h"
#include "td/db/BinlogKeyValue.h" #include "td/db/BinlogKeyValue.h"
#include "td/db/SeqKeyValue.h" #include "td/db/SeqKeyValue.h"
#include "td/db/SqliteConnectionSafe.h"
#include "td/db/SqliteKeyValue.h" #include "td/db/SqliteKeyValue.h"
#include "td/db/SqliteKeyValueSafe.h" #include "td/db/SqliteKeyValueSafe.h"
#include "td/db/TsSeqKeyValue.h" #include "td/db/TsSeqKeyValue.h"

View File

@ -4,16 +4,75 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying // Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#include "td/utils/tests.h"
#include "td/utils/Random.h"
#include "td/telegram/SetWithPosition.h" #include "td/telegram/SetWithPosition.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/tests.h"
#include <algorithm>
#include <functional>
#include <set> #include <set>
#include <utility>
using namespace td; using namespace td;
template <class T, template <class> class Set = SetWithPosition> template <class T>
class OldSetWithPosition {
public:
void add(T value) {
auto it = std::find(values_.begin(), values_.end(), value);
if (it != values_.end()) {
return;
}
values_.push_back(value);
}
void remove(T value) {
auto it = std::find(values_.begin(), values_.end(), value);
if (it == values_.end()) {
return;
}
size_t i = it - values_.begin();
values_.erase(it);
if (pos_ > i) {
pos_--;
}
}
void reset_position() {
pos_ = 0;
}
T next() {
CHECK(has_next());
return values_[pos_++];
}
bool has_next() const {
return pos_ < values_.size();
}
void merge(OldSetWithPosition &&other) {
OldSetWithPosition res;
for (size_t i = 0; i < pos_; i++) {
res.add(values_[i]);
}
for (size_t i = 0; i < other.pos_; i++) {
res.add(other.values_[i]);
}
res.pos_ = res.values_.size();
for (size_t i = pos_; i < values_.size(); i++) {
res.add(values_[i]);
}
for (size_t i = other.pos_; i < other.values_.size(); i++) {
res.add(other.values_[i]);
}
*this = std::move(res);
}
private:
std::vector<T> values_;
size_t pos_{0};
};
template <class T, template <class> class SetWithPosition>
class CheckedSetWithPosition { class CheckedSetWithPosition {
public: public:
void add(int x) { void add(int x) {
@ -28,7 +87,7 @@ class CheckedSetWithPosition {
checked_.erase(x); checked_.erase(x);
not_checked_.erase(x); not_checked_.erase(x);
} }
bool has_next() { bool has_next() const {
auto res = !not_checked_.empty(); auto res = !not_checked_.empty();
//LOG(ERROR) << res; //LOG(ERROR) << res;
ASSERT_EQ(res, s_.has_next()); ASSERT_EQ(res, s_.has_next());
@ -74,11 +133,11 @@ class CheckedSetWithPosition {
private: private:
std::set<T> checked_; std::set<T> checked_;
std::set<T> not_checked_; std::set<T> not_checked_;
Set<T> s_; SetWithPosition<T> s_;
}; };
template <template <class> class RawSet> template <template <class> class RawSet>
void test_hands() { static void test_hands() {
using Set = CheckedSetWithPosition<int, RawSet>; using Set = CheckedSetWithPosition<int, RawSet>;
Set a; Set a;
@ -94,12 +153,13 @@ void test_hands() {
a.next(); a.next();
} }
} }
template <template <class> class RawSet> template <template <class> class RawSet>
void test_stress() { static void test_stress() {
Random::Xorshift128plus rnd(123); Random::Xorshift128plus rnd(123);
using Set = CheckedSetWithPosition<int, RawSet>; using Set = CheckedSetWithPosition<int, RawSet>;
for (int t = 0; t < 100; t++) { for (int t = 0; t < 10; t++) {
std::vector<unique_ptr<Set>> sets(1000); std::vector<unique_ptr<Set>> sets(100);
for (auto &s : sets) { for (auto &s : sets) {
s = make_unique<Set>(); s = make_unique<Set>();
} }
@ -163,11 +223,12 @@ void test_stress() {
} }
} }
} }
template <template <class> class RawSet> template <template <class> class RawSet>
void test_speed() { static void test_speed() {
Random::Xorshift128plus rnd(123); Random::Xorshift128plus rnd(123);
using Set = CheckedSetWithPosition<int, RawSet>; using Set = CheckedSetWithPosition<int, RawSet>;
std::vector<unique_ptr<Set>> sets(1 << 18); std::vector<unique_ptr<Set>> sets(1 << 13);
for (size_t i = 0; i < sets.size(); i++) { for (size_t i = 0; i < sets.size(); i++) {
sets[i] = make_unique<Set>(); sets[i] = make_unique<Set>();
sets[i]->add(int(i)); sets[i]->add(int(i));
@ -187,11 +248,13 @@ TEST(SetWithPosition, hands) {
test_hands<OldSetWithPosition>(); test_hands<OldSetWithPosition>();
test_hands<SetWithPosition>(); test_hands<SetWithPosition>();
} }
TEST(SetWithPosition, stress) { TEST(SetWithPosition, stress) {
test_stress<FastSetWithPosition>(); test_stress<FastSetWithPosition>();
test_stress<OldSetWithPosition>(); test_stress<OldSetWithPosition>();
test_stress<SetWithPosition>(); test_stress<SetWithPosition>();
} }
TEST(SetWithPosition, speed) { TEST(SetWithPosition, speed) {
test_speed<FastSetWithPosition>(); test_speed<FastSetWithPosition>();
test_speed<SetWithPosition>(); test_speed<SetWithPosition>();