I have a structure that represents a cache and requires a reference to a MemoryBackend trait object for work.
I accept the trait-object reference and it works fine in normal situations.
#[no_std] // Important
pub struct Cache<'a, T> {
memory_backend: &'a mut dyn MemoryBackend,
phantom_data: core::marker::PhantomData<T>,
}
pub trait MemoryBackend {}
However, I needed to store the Cache object as a static variable:
use spin::{Mutex, Once};
static SLAB_INFO_CACHE: Mutex<Once<Cache<SlabInfo>>> = Mutex::new(Once::new());
And I'm having problems:
error[E0277]: `(dyn MemoryBackend + 'static)` cannot be sent between threads safely
5 | static SLAB_INFO_CACHE: Mutex<Once<Cache<SlabInfo>>> = Mutex::new(Once::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn MemoryBackend + 'static)` cannot be sent between threads safely
|
= help: within `slab_allocator::Cache<'static, SlabInfo>`, the trait `Send` is not implemented for `(dyn MemoryBackend + 'static)`
= note: required because it appears within the type `&'static mut (dyn MemoryBackend + 'static)`
16 | pub struct Cache<'a, T> {
| ^^^^^
= note: required for `spin::once::Once<slab_allocator::Cache<'static, SlabInfo>>` to implement `Send`
= note: required for `Mutex<spin::once::Once<slab_allocator::Cache<'static, SlabInfo>>>` to implement `Sync`
= note: shared static variables must have a type that implements `Sync`
I don't quite understand this error, I guess it is related to the fact that the trait object is only MemoryBackend and not Sync + Send.
I can't just go ahead and change the memory_backend: &‘a mut dyn MemoryBackend
field to memory_backend: &’a mut (dyn MemoryBackend + Send + Sync)
, as that would force these traits to be implemented when not required.
I could try to force Cache to own MemoryBackend, but since I'm in a no_std environment, I can't use Box.
It would be cool to have something in the style
if lifetime is not static: &'a mut (dyn MemoryBackend)
if lifetime is static: &'a mut (dyn MemoryBackend + Send + Sync)
How can I solve this problem?