3#include "lob/index/order_index.hpp"
22bool inCyclicRange(std::size_t k, std::size_t i, std::size_t j, std::size_t capacity) {
25 return i < k && k <= j;
27 return k > i || k <= j;
32std::size_t OrderIndex::indexFor(
const OrderId&
id, std::size_t capacity)
const {
33 return std::hash<OrderId>{}(id) & (capacity - 1);
43std::size_t OrderIndex::findSlot(
const OrderId&
id)
const {
45 return static_cast<std::size_t
>(-1);
47 std::size_t index = indexFor(
id, slots.size());
48 while (slots[index].value !=
nullptr) {
49 if (slots[index].key ==
id) {
52 index = (index + 1) & (slots.size() - 1);
64 std::size_t capacity = slots.empty() ? InitialCapacity : slots.size();
65 while (
static_cast<double>(orderCount) >
static_cast<double>(capacity) * MaxLoadFactor) {
68 if (!slots.empty() && capacity <= slots.size()) {
72 std::vector<Slot> grown(capacity, Slot{});
73 for (
const Slot& slot : slots) {
74 if (slot.value ==
nullptr) {
77 std::size_t index = indexFor(slot.key, grown.size());
78 while (grown[index].value !=
nullptr) {
79 index = (index + 1) & (grown.size() - 1);
86void OrderIndex::growIfNeeded() {
88 slots.assign(InitialCapacity, Slot{});
91 if (
static_cast<double>(count + 1) <=
static_cast<double>(slots.size()) * MaxLoadFactor) {
94 std::vector<Slot> grown(slots.size() * 2, Slot{});
95 for (
const Slot& slot : slots) {
96 if (slot.value ==
nullptr) {
99 std::size_t index = indexFor(slot.key, grown.size());
100 while (grown[index].value !=
nullptr) {
101 index = (index + 1) & (grown.size() - 1);
116 if (order ==
nullptr) {
117 throw std::invalid_argument(
"Cannot add a null order");
125 std::size_t index = indexFor(key, slots.size());
126 while (slots[index].value !=
nullptr) {
127 if (slots[index].key == key) {
128 throw std::logic_error(
"Order with the same OrderId already exists in the index");
130 index = (index + 1) & (slots.size() - 1);
132 slots[index] = Slot{key, order};
138 if (order ==
nullptr) {
139 throw std::invalid_argument(
"Cannot remove a null order");
142 const std::size_t hole = findSlot(order->
getOrderId());
143 if (hole ==
static_cast<std::size_t
>(-1) || slots[hole].value ==
nullptr) {
144 throw std::logic_error(
"Order not found in the index");
146 if (slots[hole].value != order) {
147 throw std::logic_error(
"Order pointer does not match indexed order");
150 slots[hole] = Slot{};
156 std::size_t vacated = hole;
157 std::size_t scan = (vacated + 1) & (slots.size() - 1);
158 while (slots[scan].value !=
nullptr) {
159 const std::size_t natural = indexFor(slots[scan].key, slots.size());
160 if (!inCyclicRange(natural, vacated, scan, slots.size())) {
161 slots[vacated] = slots[scan];
162 slots[scan] = Slot{};
165 scan = (scan + 1) & (slots.size() - 1);
171 const std::size_t index = findSlot(orderId);
172 if (index ==
static_cast<std::size_t
>(-1)) {
175 return slots[index].value;
Type-safe identifier for an order; zero is reserved as invalid.
Order * findOrder(const OrderId &orderId) const
Finds an order by ID, or returns nullptr when absent.
void reserve(std::size_t orderCount)
Grows the table, if needed, so orderCount entries fit under MaxLoadFactor without a later doubling.
void removeOrder(Order *order)
Removes an order after verifying pointer identity.
void addOrder(Order *order)
Adds an order and rejects duplicate IDs.
Represents a resting or incoming order and its lifecycle state.
OrderId getOrderId() const
Returns the unique order identifier.