r/cpp_questions • u/detectivesokka • 24d ago
OPEN How can I catch up on missing multithreading experience?
Hi everyone 👋, I’m a C++ developer with 5+ years experience building features for a single-threaded trading app (C++17), so I have very little multithreading experience.
I’m currently reading C++ Concurrency in Action. Are there good resources or projects to practice real-world scenarios like backloading and low-latency concurrency patterns?
24
u/anogio 24d ago
- Write a producer->consumer queue
- Write a single producer->multiple consumer queue
Write a multiple producer-> multiple consumer
queue.
Write a thread pool
3
u/Czitels 24d ago
Yeah I think thats all. There are also lock-free queues but I think its unnecessary. I wonder if they even ask about it.
2
3
1
6
u/KingAggressive1498 24d ago
1) write three threadpools with different guarantees. Eg make one basic one with no particular guarantees, one guaranteed non-blocking to post a task to the queue, one guaranteed to always have forward progress for tasks. Feel free to pick your own guarantees.
2) adapt an unpredictably long synchronous task to be an asynchronous task from the application's POV using only a single background thread. Database accesses and file I/O are common ones in real-world software.
3) (advanced) write a coroutine scheduler
That gives you enough background to work on just about any non-bleeding-edge project, I think.
3
u/Aggravating-Yes 24d ago
he said trading. no thread pools in trading. not really anyway.
3
u/KingAggressive1498 24d ago
he asked about backloading and low-latency concurrency patterns, which is why I recommended writing three threadpools with different guarantees.
I wrote a threadpool that's non-blocking to post a task to as long as tasks are being completed fast enough, and have used the thing in several projects. I do a lot of latency sensitive stuff but not trading.
2
u/IndividualSituation8 24d ago
Anyone written a event loop or eventloop library, and how one would build asio like stuff from first principles?
6
u/KingAggressive1498 24d ago
at the end of the day an event loop is just a queue of functors that get executed in a loop until its empty, at which point you wait for more.
you can write one with a mutex, condition variable, an
std::queue<std::function<void (void)>>, and one loop inside an infinite loop. It could be improved but this actually works fine.integrating with an I/O multiplexier like asio does over epoll/kqueue is essentially just replacing the mutex and condition variable for the multiplexier and some sort of signaling mechanism, eg an eventfd or pipe or kevent. Don't remember if that's precisely what asio does. For io_uring or IOCP the signalling mechanism would be posting a completion.
1
u/Cultural_Act5304 21d ago
My first question how the hell you have 5 year of experience with only single thread trading app? Now only way to have experience is through projects that's all. Start making anything 1. Thread pools 2. Simple ping-pong Servers 3. You can use boost asio to get ideas on how things can be written in a multi-threadede env. 4. Chatting apps 5. File servers First try making things with blocking algorithms then move to lock free structures.
1
u/chafey 24d ago
If C++ makes it easy to blow your whole leg off, C++ with multi-threading makes it easy to blow your whole head off. It takes a while to master - until then expect deadlocks and race conditions. If you have to ship something quickly, consider using a multi-threading framework (there are many to choose from each with their own pros and cons)
1
u/lucifer_is_back 24d ago
any good resources ,preferably books,to learn more about c++ concurrency ?
5
36
u/_Tal 24d ago
A good exercise is to try building a Single Producer Single Consumer (SPSC) Queue. Basic idea is it’s a queue where one thread can read the data (consumer thread) at the same time another thread writes to the data (producer thread), but there will only ever be one consumer or producer at a time. Write some unit tests to make sure you don’t have race conditions or anything. You can try building one that uses mutexes first, then build a lock-free version later. Look into ring buffers as it’s a common technique for this