-
Who We Are
- What We Do
- News & Insights
Technical Spotlight: Async Programming with Sender/Receiver
At our annual Citadel Securities Technology Offsite, Accelerate, members of our technology and low latency teams from around the world gathered for three days in sunny Scottsdale, Arizona to learn, problem-solve and network.
Each year, we develop a series of “Spotlight” sessions to share technical knowledge developed in, and outside our walls. A top item on this year’s agenda was C++26, including a session on asynchronous programming. Our resident expert Gašper Ažman delved into why a std::execution-based structured concurrency approach to asynchrony is a game changer, how to think about it and where to use it.
“Introduction to Async Programming with Sender/Receiver” was as much an education as a call to action for our engineers to embrace the std::execution paradigm at our recent offsite. Why? We believe that by understanding and leveraging this approach, our engineers can create more efficient, reliable, and scalable software systems.
Why Asynchronous Programming?
We need to develop products with deterministic behavior in a non-deterministic world. But concurrency is challenging because manual management of the many aspects of execution (control flow, cancellation, suspension, lifetime etc.) proves difficult, error-prone, and detracts from business logic. Enter the sender/receiver paradigm – a clean approach to concurrency.
Asynchronous programming is a critical tool in building systems for financial markets because of its ability to handle multiple tasks concurrently without blocking the execution of other operations. This approach is particularly beneficial for our work as a market-maker, where systems need to process vast amounts of data, execute trades, and respond to market changes in real-time, at scale.
Sender/Receiver Paradigm
This approach provides for efficient composition of asynchronous operations across concurrency domains (such as threads, gpu, network, I/O, etcetera) without the need for a dedicated run loop or framework ownership. The paradigm is built on the composition of senders and asynchronous algorithms:
- A sender carries the data required to perform the operation and model the event when it completes.
- An asynchronous algorithm attaches a single operation to its input sender and produces a sender that represents them both.
Scale thus becomes simple: The result of the expression “sender | algorithm” is another sender, which composes cleanly and scales by allowing as many layers as needed.
Key Features and Benefits
The sender/receiver paradigm offers several advantages:
- Real-time Safe: It acquires resources, such as memory, deterministically.
- Composability: Operations can be composed using sender transformers, allowing for complex workflows to be built from simpler, named components.
- Cancellation and Error Handling: It provides robust and automatically composable mechanisms for handling cancellations and errors, ensuring that operations can be cancelled, and errors propagated correctly.
- Integration with Existing Systems: std::execution can bridge different asynchronous domains, allowing for seamless integration with various IO subsystems and frameworks.
- Correct by Construction: the wiring ensures no resource leaks, no race conditions.
Real-World Applications
Solving concurrency problems in our systems is vital to the operation of our business. Why? We need to:
- Reliably manage huge amounts of trades simultaneously in fractions of seconds, scaling up and down to accommodate volumes without degradation of performance.
- Process data in real-time to inform those trades and ensure we’re able to effectively project and manage the risk associated with them.
- Reduce latency, even down to the microsecond, to ensuring faster execution of trades and data processing.
Technical implementations we’re actively using include:
- In high-concurrency applications that require deterministic outcomes such as position aggregators
- For hardware startup to ensure all subsystems can launch concurrently despite beingly asynchronously interrelated
- For network bus APIs
Relevance for Engineers
By integrating these innovations early, we believe our engineers can lead modern software development and the wider industry.
Learn more about engineering at Citadel Securities and hear more perspectives from our team.
At Citadel Securities, we actively engage with the C++ community. We believe that contributing to the community is mutually beneficial – to the community of developers and to the strategic interests of our firm. We are proud of the active contributions of our C++ committee members and that of the many members on our team who are steering the community forward.
Explore
Engineering - What We Do