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/Global.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/WallpaperManager.h"
#include "td/telegram/WebPagesManager.h"
#include "td/actor/MultiPromise.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/overloaded.h"
#include "td/utils/Variant.h"
namespace td {

View File

@ -9,15 +9,16 @@
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/ChannelId.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/SetWithPosition.h"
#include "td/telegram/UserId.h"
#include "td/utils/logging.h"
#include "td/utils/Status.h"
#include "td/utils/Variant.h"
#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;
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_,
file_location.local_id_, file_location.secret_,
BufferSlice());
file_location.local_id_, file_location.secret_, BufferSlice());
}
// 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_)) {
from.mime_type_.clear();
}
return make_tl_object<telegram_api::document>(
from.id_, from.access_hash_, BufferSlice(), from.date_, from.mime_type_, from.size_,
secret_to_telegram<telegram_api::PhotoSize>(*from.thumb_), from.dc_id_, secret_to_telegram(from.attributes_));
return make_tl_object<telegram_api::document>(from.id_, from.access_hash_, BufferSlice(), from.date_, from.mime_type_,
from.size_, secret_to_telegram<telegram_api::PhotoSize>(*from.thumb_),
from.dc_id_, secret_to_telegram(from.attributes_));
}
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)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include <set>
#include <utility>
namespace td {
template <class T>
class FastSetWithPosition {
public:
void add(int x) {
void add(T x) {
if (checked_.count(x) != 0) {
return;
}
not_checked_.insert(x);
}
void remove(int x) {
void remove(T x) {
checked_.erase(x);
not_checked_.erase(x);
}
bool has_next() {
bool has_next() const {
return !not_checked_.empty();
}
void reset_position() {
not_checked_.insert(checked_.begin(), checked_.end());
checked_ = {};
if (not_checked_.empty()) {
not_checked_ = std::move(checked_);
} else {
not_checked_.insert(checked_.begin(), checked_.end());
}
reset_to_empty(checked_);
}
T next() {
CHECK(has_next());
auto res = *not_checked_.begin();
not_checked_.erase(not_checked_.begin());
auto it = not_checked_.begin();
auto res = *it;
not_checked_.erase(it);
checked_.insert(res);
return res;
}
void merge(FastSetWithPosition &&other) {
if (this == &other) {
return;
}
if (size() < other.size()) {
std::swap(*this, other);
}
@ -47,6 +64,7 @@ class FastSetWithPosition {
not_checked_.erase(x);
checked_.insert(x);
}
for (auto x : other.not_checked_) {
if (checked_.count(x) != 0) {
continue;
@ -54,6 +72,7 @@ class FastSetWithPosition {
not_checked_.insert(x);
}
}
size_t size() const {
return checked_.size() + not_checked_.size();
}
@ -66,7 +85,7 @@ class FastSetWithPosition {
template <class T>
class SetWithPosition {
public:
void add(int x) {
void add(T x) {
if (fast_) {
fast_->add(x);
return;
@ -74,7 +93,7 @@ class SetWithPosition {
if (!has_value_) {
value_ = x;
has_value_ = true;
is_cheched_ = false;
is_checked_ = false;
return;
}
if (value_ == x) {
@ -83,28 +102,31 @@ class SetWithPosition {
make_fast();
fast_->add(x);
}
void remove(int x) {
void remove(T x) {
if (fast_) {
fast_->remove(x);
return;
}
if (has_value_ && value_ == x) {
has_value_ = false;
is_cheched_ = false;
is_checked_ = false;
}
}
bool has_next() {
bool has_next() const {
if (fast_) {
return fast_->has_next();
}
return has_value_ && !is_cheched_;
return has_value_ && !is_checked_;
}
void reset_position() {
if (fast_) {
fast_->reset_position();
return;
}
is_cheched_ = false;
is_checked_ = false;
}
T next() {
@ -112,33 +134,46 @@ class SetWithPosition {
if (fast_) {
return fast_->next();
}
is_cheched_ = true;
is_checked_ = true;
return value_;
}
void merge(SetWithPosition &&other) {
if (this == &other) {
return;
}
if (size() < other.size()) {
std::swap(*this, other);
}
if (other.size() == 0) {
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();
other.make_fast();
fast_->merge(std::move(*other.fast_));
reset_to_empty(other);
}
size_t size() const {
if (fast_) {
return fast_->size();
}
return has_value_;
return static_cast<size_t>(has_value_);
}
private:
T value_;
T value_{};
bool has_value_{false};
bool is_cheched_{false};
bool is_checked_{false};
unique_ptr<FastSetWithPosition<T>> fast_;
void make_fast() {
if (fast_) {
return;
@ -146,61 +181,10 @@ class SetWithPosition {
fast_ = make_unique<FastSetWithPosition<T>>();
CHECK(has_value_);
fast_->add(value_);
if (is_cheched_) {
if (is_checked_) {
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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ class FileDbId {
public:
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>>
FileDbId(T1 file_db_id) = delete;

View File

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

View File

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

View File

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

View File

@ -4,16 +4,75 @@
// 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)
//
#include "td/utils/tests.h"
#include "td/utils/Random.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 <utility>
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 {
public:
void add(int x) {
@ -28,7 +87,7 @@ class CheckedSetWithPosition {
checked_.erase(x);
not_checked_.erase(x);
}
bool has_next() {
bool has_next() const {
auto res = !not_checked_.empty();
//LOG(ERROR) << res;
ASSERT_EQ(res, s_.has_next());
@ -74,11 +133,11 @@ class CheckedSetWithPosition {
private:
std::set<T> checked_;
std::set<T> not_checked_;
Set<T> s_;
SetWithPosition<T> s_;
};
template <template <class> class RawSet>
void test_hands() {
static void test_hands() {
using Set = CheckedSetWithPosition<int, RawSet>;
Set a;
@ -94,12 +153,13 @@ void test_hands() {
a.next();
}
}
template <template <class> class RawSet>
void test_stress() {
static void test_stress() {
Random::Xorshift128plus rnd(123);
using Set = CheckedSetWithPosition<int, RawSet>;
for (int t = 0; t < 100; t++) {
std::vector<unique_ptr<Set>> sets(1000);
for (int t = 0; t < 10; t++) {
std::vector<unique_ptr<Set>> sets(100);
for (auto &s : sets) {
s = make_unique<Set>();
}
@ -163,11 +223,12 @@ void test_stress() {
}
}
}
template <template <class> class RawSet>
void test_speed() {
static void test_speed() {
Random::Xorshift128plus rnd(123);
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++) {
sets[i] = make_unique<Set>();
sets[i]->add(int(i));
@ -187,11 +248,13 @@ TEST(SetWithPosition, hands) {
test_hands<OldSetWithPosition>();
test_hands<SetWithPosition>();
}
TEST(SetWithPosition, stress) {
test_stress<FastSetWithPosition>();
test_stress<OldSetWithPosition>();
test_stress<SetWithPosition>();
}
TEST(SetWithPosition, speed) {
test_speed<FastSetWithPosition>();
test_speed<SetWithPosition>();