1
0
Fork 0
mirror of https://github.com/dragonflydb/dragonfly.git synced 2024-12-14 11:58:02 +00:00
dragonflydb-dragonfly/core/tx_queue.cc
2021-12-20 22:46:51 +02:00

115 lines
2.4 KiB
C++

// Copyright 2021, Roman Gershman. All rights reserved.
// See LICENSE for licensing terms.
//
#include "core/tx_queue.h"
#include "base/logging.h"
namespace dfly {
TxQueue::TxQueue(std::function<uint64_t(const Transaction*)> sf)
: score_fun_(sf), vec_(32) {
for (size_t i = 0; i < vec_.size(); ++i) {
vec_[i].next = i + 1;
}
}
auto TxQueue::Insert(Transaction* t) -> Iterator {
if (next_free_ >= vec_.size()) {
Grow();
}
DCHECK_LT(next_free_, vec_.size());
DCHECK_EQ(FREE_TAG, vec_[next_free_].tag);
Iterator res = next_free_;
vec_[next_free_].u.trans = t;
vec_[next_free_].tag = TRANS_TAG;
DVLOG(1) << "Insert " << next_free_ << " " << t;
LinkFree(score_fun_(t));
return res;
}
auto TxQueue::Insert(uint64_t val) -> Iterator {
if (next_free_ >= vec_.size()) {
Grow();
}
DCHECK_LT(next_free_, vec_.size());
Iterator res = next_free_;
vec_[next_free_].u.uval = val;
vec_[next_free_].tag = UINT_TAG;
LinkFree(val);
return res;
}
void TxQueue::LinkFree(uint64_t weight) {
uint32_t taken = next_free_;
next_free_ = vec_[taken].next;
if (size_ == 0) {
head_ = taken;
vec_[head_].next = vec_[head_].prev = head_;
} else {
uint32_t cur = vec_[head_].prev;
while (true) {
if (Rank(vec_[cur]) < weight) {
Link(cur, taken);
break;
}
if (cur == head_) {
Link(vec_[head_].prev, taken);
head_ = taken;
break;
}
cur = vec_[cur].prev;
}
}
++size_;
}
void TxQueue::Grow() {
size_t start = vec_.size();
DVLOG(1) << "Grow from " << start << " to " << start * 2;
vec_.resize(start * 2);
for (size_t i = start; i < vec_.size(); ++i) {
vec_[i].next = i + 1;
}
}
void TxQueue::Remove(Iterator it) {
DCHECK_GT(size_, 0u);
DCHECK_LT(it, vec_.size());
DCHECK_NE(FREE_TAG, vec_[it].tag);
DVLOG(1) << "Remove " << it << " " << vec_[it].u.trans;
Iterator next = kEnd;
if (size_ > 1) {
Iterator prev = vec_[it].prev;
next = vec_[it].next;
vec_[prev].next = next;
vec_[next].prev = prev;
}
--size_;
vec_[it].next = next_free_;
vec_[it].tag = FREE_TAG;
next_free_ = it;
if (head_ == it) {
head_ = next;
}
}
uint64_t TxQueue::Rank(const QRecord& r) const {
switch (r.tag) {
case UINT_TAG:
return r.u.uval;
case TRANS_TAG:
return score_fun_(r.u.trans);
}
return 0;
}
} // namespace dfly