Enumerator: do not invalidate pointers to elements

GitOrigin-RevId: 0d535d7052b9cb95365eff4bf35ddf30966ec90f
This commit is contained in:
Arseny Smirnov 2018-03-07 10:47:33 +03:00
parent 8b0cce1610
commit 81776db03a
2 changed files with 18 additions and 58 deletions

View File

@ -377,7 +377,8 @@ class FileManager : public FileLoadManager::Callback {
FileIdInfo *get_file_id_info(FileId file_id); FileIdInfo *get_file_id_info(FileId file_id);
struct RemoteInfo { struct RemoteInfo {
FullRemoteFileLocation remote_; // mutible is set to to enable changing access hash
mutable FullRemoteFileLocation remote_;
FileId file_id_; FileId file_id_;
bool operator==(const RemoteInfo &other) const { bool operator==(const RemoteInfo &other) const {
return this->remote_ == other.remote_; return this->remote_ == other.remote_;

View File

@ -10,7 +10,7 @@
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include <set> #include <map>
#include <utility> #include <utility>
namespace td { namespace td {
@ -21,69 +21,28 @@ class Enumerator {
using Key = int32; using Key = int32;
Key add(ValueT v) { Key add(ValueT v) {
container_->set_zero_value(&v); int32 next_id = narrow_cast<int32>(arr_.size() + 1);
auto it = set_.lower_bound(Key{0}); bool was_inserted;
container_->set_zero_value(nullptr); decltype(map_.begin()) it;
if (it != set_.end() && container_->get_value(*it) == v) { std::tie(it, was_inserted) = map_.insert(std::make_pair(std::move(v), next_id));
return *it; if (was_inserted) {
arr_.push_back(&it->first);
} }
auto key = container_->add_value(std::move(v)); return it->second;
set_.insert(it, key);
return key;
} }
ValueT &get(Key key) { //ValueT &get(Key key) {
return container_->get_value(key); //CHECK(key != 0);
} //return *arr_[narrow_cast<size_t>(key - 1)];
//}
const ValueT &get(Key key) const { const ValueT &get(Key key) const {
return container_->get_value(key); CHECK(key != 0);
return *arr_[narrow_cast<size_t>(key - 1)];
} }
private: private:
class Container { std::map<ValueT, int32> map_;
public: std::vector<const ValueT *> arr_;
bool compare(Key a, Key b) const {
return get_value(a) < get_value(b);
}
const ValueT &get_value(Key key) const {
if (key == 0) {
CHECK(zero_value_);
return *zero_value_;
}
size_t pos = narrow_cast<size_t>(key - 1);
CHECK(pos < values_.size());
return values_[pos];
}
ValueT &get_value(Key key) {
return const_cast<ValueT &>(const_cast<const Container *>(this)->get_value(key));
}
void set_zero_value(ValueT *value) {
zero_value_ = value;
}
Key add_value(ValueT &&value) {
values_.push_back(std::move(value));
return narrow_cast<Key>(values_.size());
}
private:
std::vector<ValueT> values_;
ValueT *zero_value_ = nullptr;
};
class Comparator {
public:
explicit Comparator(Container *container) : container_(container) {
}
bool operator()(Key a, Key b) const {
return container_->compare(a, b);
}
private:
Container *container_;
};
std::unique_ptr<Container> container_{std::make_unique<Container>()};
std::set<Key, Comparator> set_{Comparator{container_.get()}};
}; };
} // namespace td } // namespace td