At my university, there is a course on concurrency in C++, a number of topics are covered there, for each week there are tasks like writing your own spinlock/thread pool/waitgroups from go and so on. As a result, students get a complex asynchronous framework.
I'm reading a book by Mara Bos right now. Rust Atomics and Locks by Mara Bos, the book is great, but there is no practice tasks. I can learn only with practice, theoritical knowledge is great, but it getting lost in memory.
I can't find anything to test such knowledge in practice. I can repeat the course, but I don't have a framework for correctness testing and verification of work results. I can't trust LLMs because of their hallucinations. Can you suggest any practical tasks or frameworks that will help test my solutions, even if i end up making tasks myself (something as correct, authoritative, and low-level as possible)?
Obviously "write your http server" is not what i'm looking for. More like "here is a pack of tests for optimised lock-free data structure"
loom is a pretty powerful library for testing concurrent programs. It is used as part of the tokio testsuite. It is not a ready-to-use testsuite for some concurrent data structure, but if I'd have to write such a thing myself, I'd probably use loom quite extensively.
You can try porting some concurrent data structures from C++ to Rust if you are looking for hard/long-term practical projects. But if you are just looking for practice, maybe implement what you already know from your course, in rust. That will deepen your understanding of both how C++ and rust handles concurrency (rust's concurrency model is very unique).
If by testing your solutions, you mean checking their correctness, then you can use loom and shuttle to 'assess' the correctness of your implementation by simulating a model under their framework. I have tried to use both, loom can be used to test small bounded models, but it becomes too expensive due to being exhaustive. shuttle on the hand is probabilistic. Another important tool is miri, because you will often be writing unsafe code while working on high-perf/complex concurrent code. It's quite common to end up with a UB or memory leak in unsafe code that may look alright at first.