Skip to content

Utilities Reference

Pools, queues, decimal types, and performance utilities.

Decimal Types

Header: flox/util/base/decimal.h

Fixed-point arithmetic for prices and quantities.

template <typename Tag, int Scale_, int64_t TickSize_ = 1>
class Decimal
{
public:
  static constexpr int Scale = Scale_;
  static constexpr int64_t TickSize = TickSize_;

  constexpr Decimal();
  explicit constexpr Decimal(int64_t raw);

  // Construction
  static constexpr Decimal fromDouble(double val);
  static constexpr Decimal fromRaw(int64_t raw);

  // Conversion
  constexpr double toDouble() const;
  constexpr int64_t raw() const;
  std::string toString() const;

  // Tick operations
  constexpr Decimal roundToTick() const;

  // Arithmetic
  constexpr Decimal operator+(Decimal d) const;
  constexpr Decimal operator-(Decimal d) const;
  constexpr Decimal operator*(Decimal d) const;
  constexpr Decimal operator/(Decimal d) const;
  constexpr Decimal operator*(int64_t x) const;
  constexpr Decimal operator/(int64_t x) const;

  // Compound assignment
  constexpr Decimal& operator+=(const Decimal& other);
  constexpr Decimal& operator-=(const Decimal& other);
  constexpr Decimal& operator*=(const Decimal& other);
  constexpr Decimal& operator/=(const Decimal& other);

  // Comparison
  constexpr auto operator<=>(const Decimal&) const = default;
  constexpr bool operator==(const Decimal&) const = default;

  constexpr bool isZero() const;
};

Predefined Types

// All use Scale = 1,000,000 (6 decimal places)
using Price = Decimal<PriceTag, 1'000'000, 1>;
using Quantity = Decimal<QuantityTag, 1'000'000, 1>;
using Volume = Decimal<VolumeTag, 1'000'000, 1>;

Examples

Price p1 = Price::fromDouble(100.50);
Price p2 = Price::fromDouble(0.01);

Price sum = p1 + p2;           // 100.51
double d = sum.toDouble();     // 100.51
int64_t raw = sum.raw();       // 100510000

Quantity q = Quantity::fromDouble(10.5);
Volume v = Price::fromDouble(100.0) * q;  // Volume arithmetic

SPSCQueue

Header: flox/util/concurrency/spsc_queue.h

Lock-free single-producer single-consumer queue.

template <typename T, size_t Capacity>
class SPSCQueue
{
public:
  SPSCQueue();
  ~SPSCQueue();

  // Push (returns false if full)
  bool push(const T& item) noexcept;
  bool emplace(T&& item) noexcept;

  template <typename... Args>
  bool try_emplace(Args&&... args);

  // Pop (returns false if empty)
  bool pop(T& out) noexcept;
  T* try_pop();
  std::optional<std::reference_wrapper<T>> try_pop_ref();

  // State
  void clear() noexcept;
  bool empty() const noexcept;
  bool full() const noexcept;
  size_t size() const noexcept;
};

Requirements

  • Capacity must be > 1 and power of 2
  • T must be nothrow destructible

Example

SPSCQueue<int, 1024> queue;

// Producer thread
queue.push(42);
queue.emplace(43);

// Consumer thread
int value;
if (queue.pop(value)) {
  // Process value
}

Object Pool

Header: flox/util/memory/pool.h

Pre-allocated object pool for zero-allocation event handling.

Pool

template <typename T, size_t Capacity>
class Pool
{
public:
  using ObjectType = T;

  Pool();
  ~Pool();

  std::optional<Handle<T>> acquire();  // Get object from pool
  void release(T* obj);                // Return to pool (automatic via Handle)

  size_t inUse() const;
};

Handle

Reference-counted smart pointer for pooled objects.

template <typename T>
class Handle
{
public:
  explicit Handle(T* ptr) noexcept;
  Handle(const Handle& other) noexcept;     // Copy: increments refcount
  Handle(Handle&& other) noexcept;          // Move: transfers ownership
  ~Handle();                                 // Returns to pool when refcount=0

  T* get() const noexcept;
  T* operator->() const noexcept;
  T& operator*() const noexcept;

  template <typename U>
  Handle<U> upcast() const;
};

PoolableBase

Base class for pooled objects.

template <typename Derived>
struct PoolableBase : public RefCountable
{
  void setPool(void* pool);
  void releaseToPool();
  void clear();  // Override to reset object state
};

Example

struct MyEvent : public pool::PoolableBase<MyEvent>
{
  int data;
  std::pmr::vector<int> items;

  MyEvent(std::pmr::memory_resource* res) : items(res) {}

  void clear() {
    data = 0;
    items.clear();
  }
};

// Create pool
pool::Pool<MyEvent, 64> eventPool;

// Acquire
if (auto handle = eventPool.acquire()) {
  (*handle)->data = 42;
  (*handle)->items.push_back(1);

  // Pass to bus
  bus.publish(std::move(handle));
}
// Handle automatically returns to pool when refcount reaches 0

RefCountable

Header: flox/util/memory/ref_countable.h

Thread-safe reference counting.

class RefCountable
{
public:
  RefCountable() = default;
  virtual ~RefCountable() = default;

  void retain();                    // Increment refcount
  bool release();                   // Decrement; returns true if refcount hit 0
  void resetRefCount();             // Reset to 1
  uint32_t refCount() const;
};

BusyBackoff

Header: flox/util/performance/busy_backoff.h

Adaptive backoff strategy for spin loops.

class BusyBackoff
{
public:
  void pause();   // Spin, yield, or sleep based on iteration count
  void reset();   // Reset iteration counter
};

Strategy

  1. First ~100 iterations: CPU pause instruction
  2. Next ~100 iterations: std::this_thread::yield()
  3. Beyond: Short sleep (microseconds)

CPU Affinity

Header: flox/util/performance/cpu_affinity.h

Available when compiled with FLOX_ENABLE_CPU_AFFINITY=ON.

class CpuAffinity
{
public:
  bool pinToCore(int coreId);
  bool setRealTimePriority(int priority);
  bool disableCpuFrequencyScaling();

  CoreAssignment getRecommendedCoreAssignment(const CriticalComponentConfig& config);
  CoreAssignment getNumaAwareCoreAssignment(const CriticalComponentConfig& config);

  bool verifyCriticalCoreIsolation(const CoreAssignment& assignment);
};

struct CriticalComponentConfig
{
  bool preferIsolatedCores = true;
  bool exclusiveIsolatedCores = true;
  bool allowSharedCriticalCores = false;
};

struct CoreAssignment
{
  std::vector<int> marketDataCores;
  std::vector<int> executionCores;
  std::vector<int> strategyCores;
  std::vector<int> riskCores;
  std::vector<int> generalCores;
  std::vector<int> allIsolatedCores;
  bool hasIsolatedCores{false};
};

// Factory function
std::unique_ptr<CpuAffinity> createCpuAffinity();

Logging

Header: flox/log/log.h

// Macros
FLOX_LOG(message);      // Log message
FLOX_LOG_OFF();         // Disable logging
FLOX_LOG_ON();          // Enable logging

Example

FLOX_LOG("Trade received: " << ev.trade.price.toDouble());

Profiling

Header: flox/util/performance/profile.h

Tracy profiler integration (when FLOX_ENABLE_TRACY=ON).

// Scope profiling
FLOX_PROFILE_SCOPE("MyFunction");

// Without Tracy, these are no-ops

Time Utilities

Header: flox/util/base/time.h

using UnixNanos = int64_t;   // Nanoseconds since Unix epoch
using MonoNanos = int64_t;   // Nanoseconds from monotonic clock
using TimePoint = std::chrono::system_clock::time_point;

// Functions
UnixNanos nowNsWallclock();
MonoNanos nowNsMonotonic();
void init_timebase_mapping();  // Call once at startup

See Also