Efficiently implementing a large shared array of structs

I am trying to re-implement in Rust something that I wrote in C (and in Zig).
I have an array of structs that I share among different threads.

Each element of the array contains various fields and an Atomic_bool which is used as a mutex to protect concurrent access to this particular element (using atomic_compare_exchange_weak() ); each element looks like that:

struct {
  int sig;
  int v;
  atomic_bool m;}

What would be the "idiomatic way" to do that in Rust?

What do you do if a thread encounters a locked element? Spin?

Assuming array refers to fixed-size array of static length…

…so the struct would be idiomatically put into a std::sync::Mutex instead of implementing your own “mutex” logic. The standard library implementation does have a fast-path that merely uses an atomic integer, and also a fast-path that spins for a short while before any OS-interaction happens and the thread is getting parked.

Let’s call the struct Foo, and the array length is 42 then you could just define

struct Foo {
    sig: i32,
    v: i32,

and then use a [Mutex<Foo>; 42] that’s shared between threads.

Either it can be shared between threads by shared reference – &[Mutex<Foo>; 42] – accessed from scoped threads, or by shared-ownership via Arc<[Mutex<Foo>; 42]>; or it could live in a global static variable.

By the way, there also is no memory overhead. E.g. Mutex<Foo> on linux would be an entirely flat struct, no heap allocations, and not significantly larger (if at all…) than your original C struct, as all it does is store a Foo struct along a single 32 bit atomic integer.

1 Like

In that particular case, it is highly improbable that 2 threads might access the same data at the same time. But all threads access the table very often. So spin in that particular case is acceptable, as atomic_compare_exchange_weak() is almost always OK (the possibility of spinlock is small), but as it is called very often, making an OS system call instead would be expensive.