Leka
A low-latency C++20 price-time-priority limit order book and matching engine
▶ Replay viewer
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
14namespace 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 */
23class 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. */
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
88static_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
Type-safe identifier for an order; zero is reserved as invalid.
Definition order_id.hpp:10
void release(Order *order)
Destroys an order and returns its slot to the free list.
std::size_t getPageCount() const
Returns the number of allocated pages.
std::size_t getLiveOrderCount() const
Returns the number of live orders in the pool.
OrderPool()
Creates an empty pool without allocating a page.
void reserve(std::size_t orderCount)
Pre-allocates enough pages to hold at least orderCount live orders without allocate() creating a page...
Order * allocate(OrderId orderId, Price price, Quantity originalQuantity, Timestamp timestamp, OrderSide orderSide, OrderType orderType, SequenceNumber sequenceNumber)
Constructs an Order in a stable pool slot.
Represents a resting or incoming order and its lifecycle state.
Definition order.hpp:17
Type-safe nonzero price value used for price ordering.
Definition price.hpp:9
Type-safe unsigned order quantity; zero represents a filled state.
Definition quantity.hpp:8
Monotonic engine sequence used for deterministic processing order.
Nanoseconds since the Unix epoch; zero is reserved as invalid.
Definition timestamp.hpp:10