mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-14 11:58:02 +00:00
116 lines
2.4 KiB
C++
116 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
|