Leka
A low-latency C++20 price-time-priority limit order book and matching engine
▶ Replay viewer
Toggle main menu visibility
Loading...
Searching...
No Matches
order_pool.hpp
1
// include/lob/book/order_pool.hpp
2
#ifndef ORDER_POOL_HPP
3
#define ORDER_POOL_HPP
4
5
#include "lob/order/order.hpp"
6
7
#include <array>
8
#include <cstddef>
9
#include <cstdint>
10
#include <memory>
11
#include <unordered_map>
12
#include <vector>
13
14
namespace
lob {
15
16
/**
17
* @brief Provides stable, pooled storage for Order objects.
18
*
19
* Storage is allocated in fixed 64 KiB pages. Orders are constructed in
20
* place, never compacted, and released slots are reused without moving live
21
* orders.
22
*/
23
class
OrderPool
{
24
public
:
25
static
constexpr
std::size_t PageSize = 64 * 1024;
26
static
constexpr
std::size_t SlotsPerPage = PageSize /
sizeof
(
Order
);
27
28
/** Creates an empty pool without allocating a page. */
29
OrderPool
();
30
OrderPool
(
OrderPool
&&) =
delete
;
31
OrderPool
& operator=(
OrderPool
&&) =
delete
;
32
OrderPool
(
const
OrderPool
&) =
delete
;
// Delete copy constructor to prevent copying
33
OrderPool
& operator=(
const
OrderPool
&) =
delete
;
// Delete copy assignment operator to prevent copying
34
/** Destroys all live orders and releases every allocated page. */
35
~OrderPool
();
36
37
/**
38
* @brief Constructs an Order in a stable pool slot.
39
* @return A pointer owned by this pool until release() is called.
40
*/
41
Order
*
allocate
(
OrderId
orderId,
Price
price,
Quantity
originalQuantity,
42
Timestamp
timestamp, OrderSide orderSide,
43
OrderType orderType,
SequenceNumber
sequenceNumber);
44
/** Constructs an Order with explicit original and remaining quantities. */
45
Order
*
allocate
(
OrderId
orderId,
Price
price,
Quantity
originalQuantity,
46
Quantity
remainingQuantity,
Timestamp
timestamp,
47
OrderSide orderSide, OrderType orderType,
48
SequenceNumber
sequenceNumber);
49
/** Destroys an order and returns its slot to the free list. */
50
void
release
(
Order
* order);
51
52
/**
53
* @brief Pre-allocates enough pages to hold at least @p orderCount
54
* live orders without allocate() creating a page on its own.
55
*
56
* A page is created lazily, on the first allocate() call that finds
57
* no free slot, via mmap — a syscall with a genuinely unbounded tail
58
* (page fault handling, kernel scheduling), which is why it shows up
59
* as the multi-order-of-magnitude outliers in a latency histogram
60
* (see ARCH_DECISIONS.md ADR-008). Calling this once, before trading
61
* begins, for a known or comfortably over-estimated maximum order
62
* count moves every one of those mmap calls out of the hot path
63
* entirely, the same trade PriceLadder already makes for price
64
* levels: pay a bounded, known cost once, in exchange for a flat
65
* tail afterward. Exceeding @p orderCount still falls back to the
66
* lazy per-allocation behavior rather than failing.
67
*/
68
void
reserve
(std::size_t orderCount);
69
70
/** Returns the number of allocated pages. */
71
std::size_t
getPageCount
()
const
{
return
pages.size(); }
72
/** Returns the number of live orders in the pool. */
73
std::size_t
getLiveOrderCount
()
const
{
return
liveOrderCount; }
74
75
private
:
76
struct
Page;
77
78
std::vector<std::unique_ptr<Page>> pages;
// Vector to hold all allocated pages
79
std::unordered_map<std::uintptr_t, Page*> pageIndex;
// Map to quickly find the page for a given order pointer
80
Page* firstPageWithFreeSlot{
nullptr
};
// Pointer to the first page that has at least one free slot
81
std::size_t liveOrderCount{0};
// Count of currently allocated orders
82
83
Page
* createPage();
// Create a new page and add it to the pool
84
void
addToFreePageList(
Page
* page);
// Add a page to the list of pages with free slots
85
void
removeFromFreePageList(
Page
* page);
// Remove a page from the list of pages with free slots
86
};
87
88
static_assert
(OrderPool::SlotsPerPage == 819);
// Ensure that the number of slots per page is as expected
89
90
}
// namespace lob
91
92
#endif
// ORDER_POOL_HPP
lob::OrderId
Type-safe identifier for an order; zero is reserved as invalid.
Definition
order_id.hpp:10
lob::OrderPool::release
void release(Order *order)
Destroys an order and returns its slot to the free list.
Definition
order_pool.cpp:183
lob::OrderPool::getPageCount
std::size_t getPageCount() const
Returns the number of allocated pages.
Definition
order_pool.hpp:71
lob::OrderPool::getLiveOrderCount
std::size_t getLiveOrderCount() const
Returns the number of live orders in the pool.
Definition
order_pool.hpp:73
lob::OrderPool::OrderPool
OrderPool()
Creates an empty pool without allocating a page.
lob::OrderPool::reserve
void reserve(std::size_t orderCount)
Pre-allocates enough pages to hold at least orderCount live orders without allocate() creating a page...
Definition
order_pool.cpp:175
lob::OrderPool::allocate
Order * allocate(OrderId orderId, Price price, Quantity originalQuantity, Timestamp timestamp, OrderSide orderSide, OrderType orderType, SequenceNumber sequenceNumber)
Constructs an Order in a stable pool slot.
Definition
order_pool.cpp:137
lob::Order
Represents a resting or incoming order and its lifecycle state.
Definition
order.hpp:17
lob::Price
Type-safe nonzero price value used for price ordering.
Definition
price.hpp:9
lob::Quantity
Type-safe unsigned order quantity; zero represents a filled state.
Definition
quantity.hpp:8
lob::SequenceNumber
Monotonic engine sequence used for deterministic processing order.
Definition
sequence_number.hpp:8
lob::Timestamp
Nanoseconds since the Unix epoch; zero is reserved as invalid.
Definition
timestamp.hpp:10
lob::OrderPool::Page
Definition
order_pool.cpp:17
include
lob
book
order_pool.hpp
Generated by
1.18.0