Задать вопрос
mrjbom
@mrjbom

Ссылка на трейт-объект в статической переменной?

У меня есть структура представляющая кэш и требующая для своей работы ссылку на трейт-объект MemoryBackend.
Я принимаю ссылку на трейт-объект и это нормально работает в обычных ситуациях.

pub struct Cache<'a, T> {
    memory_backend: &'a mut dyn MemoryBackend,
    phantom_data: core::marker::PhantomData<T>,
}

pub trait MemoryBackend {}


Однако мне потребовалось хранить объект Cache как статическую переменную:
use spin::{Mutex, Once};

static SLAB_INFO_CACHE: Mutex<Once<Cache<SlabInfo>>> = Mutex::new(Once::new());

И у меня возникают проблемы:
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`


Я не совсем понимаю эту ошибку, полагаю это связно с тем, что трейт объект лишь MemoryBackend, а не Sync + Send.
Я не могу просто взять и изменить поле memory_backend: &'a mut dyn MemoryBackend на
memory_backend: &'a mut (dyn MemoryBackend + Send + Sync)
, поскольку это заставит реализовывать эти трейты тогда, когда это не требуется.
Я мог бы попробовать заставить Cache владеть MemoryBackend, но поскольку я нахожусь в no_std среде, я не могу использовать Box.

Как я могу решить эту проблему?
  • Вопрос задан
  • 41 просмотр
Подписаться 1 Простой 1 комментарий
Решения вопроса 1
@historydev
Редактирую файлы с непонятными расширениями
Я не могу просто взять и изменить поле memory_backend: &'a mut dyn MemoryBackend на


Значит раздели модули на Sync / not Sync, реализуй одну структуру с Sync, а другую без.
- Имя и api структуры будут одинаковыми, а модули разные.

// crate::sync::cache;

pub struct Cache<'a, T> {
    memory_backend: &'a mut dyn MemoryBackend + Send + Sync,
    phantom_data: core::marker::PhantomData<T>,
}


// crate::cache;

pub struct Cache<'a, T> {
    memory_backend: &'a mut dyn MemoryBackend,
    phantom_data: core::marker::PhantomData<T>,
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы