dragonfly/core/tx_queue.h

112 lines
2.1 KiB
C++

// Copyright 2021, Roman Gershman. All rights reserved.
// See LICENSE for licensing terms.
//
#pragma once
#include <cstdint>
#include <functional>
#include <variant>
#include <vector>
namespace dfly {
class Transaction;
class TxQueue {
void Link(uint32_t p, uint32_t n) {
uint32_t next = vec_[p].next;
vec_[n].next = next;
vec_[n].prev = p;
vec_[p].next = n;
vec_[next].prev = n;
}
public:
// uint64_t is used for unit-tests.
using ValueType = std::variant<Transaction*, uint64_t>;
using Iterator = uint32_t;
enum { kEnd = Iterator(-1) };
TxQueue(std::function<uint64_t(const Transaction*)> score_fun = nullptr);
// returns iterator to that item the list
Iterator Insert(Transaction* t);
Iterator Insert(uint64_t val);
void Remove(Iterator);
ValueType At(Iterator it) const {
switch (vec_[it].tag) {
case TRANS_TAG:
return vec_[it].u.trans;
case UINT_TAG:
return vec_[it].u.uval;
}
return 0u;
}
ValueType Front() const {
return At(head_);
}
void PopFront() {
Remove(head_);
}
size_t size() const {
return size_;
}
bool Empty() const {
return size_ == 0;
}
//! returns the score of the tail record. Can be called only if !Empty().
uint64_t TailScore() const {
return Rank(vec_[vec_[head_].prev]);
}
//! returns the score of the head record. Can be called only if !Empty().
uint64_t HeadScore() const {
return Rank(vec_[head_]);
}
//! Can be called only if !Empty().
Iterator Head() const {
return head_;
}
private:
enum { TRANS_TAG = 0, UINT_TAG = 11, FREE_TAG = 12 };
void Grow();
void LinkFree(uint64_t rank);
struct QRecord {
union {
Transaction* trans;
uint64_t uval;
} u;
uint32_t tag : 8;
uint32_t next : 24;
uint32_t prev;
QRecord() : tag(FREE_TAG), prev(kEnd) {
}
};
static_assert(sizeof(QRecord) == 16, "");
uint64_t Rank(const QRecord& r) const;
std::function<uint64_t(const Transaction*)> score_fun_;
std::vector<QRecord> vec_;
uint32_t next_free_ = 0, head_ = 0;
size_t size_ = 0;
TxQueue(const TxQueue&) = delete;
};
} // namespace dfly