I am new to Rust, but I have significant background in low-level concurrency code in other languages. I am trying to build a CAS based lock-free ring buffer for function pointers (as part of building a thread pool implementation, just to give some background).
I use an array of AtomicPtr<Box<'static + Send + FnOnce()>> as the underlying data structure. Does that look like a good choice?
I have a couple of questions for which I would appreciate any suggestions and explanations:
- Ideally I would not need the
Boxindirection, but since FnOnce is a DST, I can not store a pointer to FnOnce directly in an AtomicPtr. Is this sound reasoning? Is there a better way?
- Is it sound to store a null pointer inside an AtomicPtr? I found nothing forbidding it in the documentation, but I'd like to make doubly sure. I'd like to represent an empty slot in the ring buffer by a null pointer, using CAS operations for thread synchronization. Does that make sense or is there a better idiomatic way of doing it in Rust?
- This is probably a real newby question, but here goes: The
push()method should take ownership of an FnOnce instance and store (a pointer to) it in the appropriate AtomicPtr - transferring ownership to the AtomicPtr, and preventing it from being dropped right away. How do I do that? And how do I reclaim ownership in the
pop()function that CASes out the pointer to the FnOnce?
Thanks for reading this - any help or discussion is greatly appreciated!