gpt4 book ai didi

rust - 为共享静态变量避免 `Sync`

转载 作者:行者123 更新时间:2023-12-03 11:30:55 31 4
gpt4 key购买 nike

我有以下定义:

struct MyCustomFactory;

trait Factory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized;
}

impl Factory for MyCustomFactory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized,
{
Arc::new(entity)
}
}

更高层次的问题:

我正在尝试创建一个全局静态(和不可变)字符串映射到实现 Factory 的结构特征。目标是对于映射的任何值成员,我都可以将其视为 Factory。 , 调用 new反对它,反过来又会得到东西(在这种情况下)实现了Display特质。

我有以下内容:

static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
Lazy::new(|| {
let mut map = BTreeMap::new();
let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
map.insert("foo", value);
map
});

编译器提示:

77 | / static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
78 | | Lazy::new(|| {
79 | | let map = BTreeMap::new();
80 | | let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
... |
88 | | });
| |_______^ `(dyn Factory + 'static)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Factory + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<(dyn Factory + 'static)>`
= note: required because of the requirements on the impl of `std::marker::Send` for `alloc::collections::btree::node::Root<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because it appears within the type `std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because it appears within the type `once_cell::sync::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::sync::Lazy<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: shared static variables must have a type that implements `Sync`

我尝试过的事情:

  • 实现 Sync反对特征:声明特征具有trait Factory : Sync , (意味着所有实现该特征的项目都必须实现 Sync )和/或定义:

       |
    66 | unsafe impl Sync for dyn Factory {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
  • 包装 Arc<dyn Factory> :我试过使用 Mutex/RefCell/OnceCell和其他人,都导致相同的错误。似乎应该有一种方法来处理底层 MyCustomFactory作为一个可以被锁定的单例。这个结构在全局范围内只有一次实例,这很好(也是意料之中的)。

最佳答案

您已接近添加 Sync。如果您仔细观察,您会发现该错误建议添加 Send:

= help: the trait `std::marker::Send` is not implemented for `(dyn Factory + 'static)`

同时添加 SendSync 并编译。你可以这样做:

trait Factory: Send + Sync {
...
}

或者,我的偏好是在静态 map 中专门要求它们,因为那是需要它们的地方:

static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory + Send + Sync>>> =
Lazy::new(|| {
let mut map = BTreeMap::new();
let value = Arc::new(MyCustomFactory) as Arc<dyn Factory + Send + Sync>;
map.insert("foo", value);
map
});

您还可以通过让它推断第二个 Arc 来减少重复:

let value = Arc::new(MyCustomFactory) as Arc<_>;

关于rust - 为共享静态变量避免 `Sync`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62096074/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com