You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its new position.
const_cursor &operator++() {
// 只需此处加锁即可
// Move forward until we get to a slot that is occupied, or we
// get to the end
++slot_;
for (; index_ < buckets_->size(); ++index_) {
for (; slot_ < slot_per_bucket(); ++slot_) {
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_value();
return *this;
}
}
slot_ = 0;
}
assert(std::make_pair(index_, slot_) == end_pos(*buckets_));
return *this;
}
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its old position.
const_cursor operator++(int) {
const_cursor old(*this);
++(*this);
return old;
}
size_type partition() const { return index_; }
private:
// cuckoohash_map's value
std::reference_wrapper<cuckoohash_map> map_;
size_type hp_;
buckets_t *buckets_;
// local value
bool good_ {false};
size_type index_ {0};
size_type slot_ {0};
value_type copyed_value_;
// Returns the position signifying the end of the table
static std::pair<size_type, size_type> end_pos(const buckets_t &buckets) {
return std::make_pair(buckets.size(), 0);
}
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its new position.
key_cursor &operator++() {
// 只需此处加锁即可
// Move forward until we get to a slot that is occupied, or we
// get to the end
++slot_;
for (; index_ < buckets_->size(); ++index_) {
for (; slot_ < slot_per_bucket(); ++slot_) {
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_key();
return *this;
}
}
slot_ = 0;
}
assert(std::make_pair(index_, slot_) == end_pos(*buckets_));
return *this;
}
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its old position.
key_cursor operator++(int) {
key_cursor old(*this);
++(*this);
return old;
}
size_type partition() const { return index_; }
private:
// cuckoohash_map's value
std::reference_wrapper<cuckoohash_map> map_;
size_type hp_;
buckets_t *buckets_;
// local value
bool good_ {false};
size_type index_ {0};
size_type slot_ {0};
key_type copyed_key_;
// Returns the position signifying the end of the table
static std::pair<size_type, size_type> end_pos(const buckets_t &buckets) {
return std::make_pair(buckets.size(), 0);
}
// The private constructor is used by cuckoohash_map to create
// iterators from scratch. If the given index_-slot_ pair is at the
// end of the table, or the given spot is occupied, stay. Otherwise,
// step forward to the next data item, or to the end of the table.
key_cursor(cuckoohash_map &map, size_type index,
size_type slot) noexcept
: map_(map), index_(index), slot_(slot) {
hp_ = map_.get().hashpower();
buckets_ = std::addressof(map_.get().buckets_);
if (std::make_pair(index_, slot_) != end_pos(*buckets_)) {
good_ = true;
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_key();
} else {
operator++();
}
}
}
void fill_copyed_key() {
try {
auto locker = map_.get().lock_one(hp_, index_, normal_mode());
copyed_key_ = (*buckets_)[index_].key(slot_);
} catch (...) {
good_ = false;
}
}
will you add this feature?
#ifndef CUCKOOHASH_UNSAFE_ITER_HH
#define CUCKOOHASH_UNSAFE_ITER_HH
// inner class of cuckoohash_map
class const_cursor {
public:
const_cursor() { }
bool good() const { return good; }
// Return true if the iterators are from the same locked table and
// location, false otherwise.
bool operator==(const const_cursor &it) const {
if (!good && !it.good_)
return true;
return buckets_ == it.buckets_ && index_ == it.index_ &&
slot_ == it.slot_;
}
bool operator!=(const const_cursor &it) const {
return !(operator==(it));
}
const_pointer operator->() const { return ©ed_value_; }
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its new position.
const_cursor &operator++() {
// 只需此处加锁即可
// Move forward until we get to a slot that is occupied, or we
// get to the end
++slot_;
for (; index_ < buckets_->size(); ++index_) {
for (; slot_ < slot_per_bucket(); ++slot_) {
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_value();
return *this;
}
}
slot_ = 0;
}
assert(std::make_pair(index_, slot_) == end_pos(*buckets_));
return *this;
}
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its old position.
const_cursor operator++(int) {
const_cursor old(*this);
++(*this);
return old;
}
size_type partition() const { return index_; }
private:
// cuckoohash_map's value
std::reference_wrapper<cuckoohash_map> map_;
size_type hp_;
buckets_t *buckets_;
// local value
bool good_ {false};
size_type index_ {0};
size_type slot_ {0};
value_type copyed_value_;
// Returns the position signifying the end of the table
static std::pair<size_type, size_type> end_pos(const buckets_t &buckets) {
return std::make_pair(buckets.size(), 0);
}
// The private constructor is used by cuckoohash_map to create
// iterators from scratch. If the given index_-slot_ pair is at the
// end of the table, or the given spot is occupied, stay. Otherwise,
// step forward to the next data item, or to the end of the table.
const_cursor(cuckoohash_map &map, size_type index,
size_type slot) noexcept
: map_(map), index_(index), slot_(slot) {
hp_ = map_.get().hashpower();
buckets_ = std::addressof(map_.get().buckets_);
if (std::make_pair(index_, slot_) != end_pos(*buckets_)) {
good_ = true;
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_value();
} else {
operator++();
}
}
}
void fill_copyed_value() {
try {
auto locker = map_.get().lock_one(hp_, index_, normal_mode());
auto ref = (*buckets_)[index_].kvpair(slot_);
const_cast<key_type>(©ed_value_.first) = ref.first;
copyed_value_.second = ref.second;
} catch (...) {
good_ = false;
}
}
friend class cuckoohash_map;
};
class key_cursor {
public:
key_cursor() {}
bool good() const { return good_; }
// Return true if the iterators are from the same locked table and
// location, false otherwise.
bool operator==(const key_cursor &it) const {
if (!good_ && !it.good_)
return true;
return buckets_ == it.buckets_ && index_ == it.index_ &&
slot_ == it.slot_;
}
bool operator!=(const key_cursor &it) const {
return !(operator==(it));
}
const key_type& operator*() const { return copyed_key_; }
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its new position.
key_cursor &operator++() {
// 只需此处加锁即可
// Move forward until we get to a slot that is occupied, or we
// get to the end
++slot_;
for (; index_ < buckets_->size(); ++index_) {
for (; slot_ < slot_per_bucket(); ++slot_) {
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_key();
return *this;
}
}
slot_ = 0;
}
assert(std::make_pair(index_, slot_) == end_pos(*buckets_));
return *this;
}
// Advance the iterator to the next item in the table, or to the end
// of the table. Returns the iterator at its old position.
key_cursor operator++(int) {
key_cursor old(*this);
++(*this);
return old;
}
size_type partition() const { return index_; }
private:
// cuckoohash_map's value
std::reference_wrapper<cuckoohash_map> map_;
size_type hp_;
buckets_t *buckets_;
// local value
bool good_ {false};
size_type index_ {0};
size_type slot_ {0};
key_type copyed_key_;
// Returns the position signifying the end of the table
static std::pair<size_type, size_type> end_pos(const buckets_t &buckets) {
return std::make_pair(buckets.size(), 0);
}
// The private constructor is used by cuckoohash_map to create
// iterators from scratch. If the given index_-slot_ pair is at the
// end of the table, or the given spot is occupied, stay. Otherwise,
// step forward to the next data item, or to the end of the table.
key_cursor(cuckoohash_map &map, size_type index,
size_type slot) noexcept
: map_(map), index_(index), slot_(slot) {
hp_ = map_.get().hashpower();
buckets_ = std::addressof(map_.get().buckets_);
if (std::make_pair(index_, slot_) != end_pos(*buckets_)) {
good_ = true;
if ((*buckets_)[index_].occupied(slot_)) {
fill_copyed_key();
} else {
operator++();
}
}
}
void fill_copyed_key() {
try {
auto locker = map_.get().lock_one(hp_, index_, normal_mode());
copyed_key_ = (*buckets_)[index_].key(slot_);
} catch (...) {
good_ = false;
}
}
friend class cuckoohash_map;
};
// // 注意 endpos = container.end(),每次调用 end 会有额外的成本
// auto cursor = container.begin();
// auto endpos = container.end();
// for (; cursor!= endpos; ++cursor) {
// // cursor->first;
// // cursor->second;
// }
// // 注意需要检查 cursor 的状态来判断是否完整遍历
// if (!cursor.good()) {
// // 遍历过程出现 rehash, 提前结束
// }
const_cursor begin() {
return const_cursor(*this, 0, 0);
}
const_cursor end() {
const auto end_pos = const_cursor::end_pos(buckets_);
return const_cursor(*this,
static_cast<size_type>(end_pos.first),
static_cast<size_type>(end_pos.second));
}
// // 注意 endpos = container.end(),每次调用 end 会有额外的成本
// auto key_cursor = container.key_begin();
// auto key_endpos = container.key_end();
// int key_count = 0;
// for (; key_cursor != key_endpos; ++key_cursor) {
// ++key_count;
// LOG_EVERY_N(INFO, 1000) << "fill key: " << *key_cursor;
// }
// // 注意需要检查 key_cursor 的状态来判断是否完整遍历
// if (!key_cursor.good()) {
// // 遍历过程出现 rehash, 提前结束
// }
key_cursor key_begin() {
return key_cursor(*this, 0, 0);
}
key_cursor key_end() {
const auto end_pos = key_cursor::end_pos(buckets_);
return key_cursor(*this,
static_cast<size_type>(end_pos.first),
static_cast<size_type>(end_pos.second));
}
#endif // _CUCKOOHASH_UNSAFE_ITER_HH
The text was updated successfully, but these errors were encountered: