- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个带有边和节点的图形实现。该图应同时访问,因此我选择将边和节点构建为 Arc<Mutex<dyn Edge>>
和 Arc<RwLock<dyn Node>>
.
不幸的是我得到一个编译错误the parameter type 'T' may not live long enough
( Playground ) 连接节点/边时。
pub trait Node {
fn connect(&mut self, edge: EdgeRef);
}
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub trait Edge {
fn connect(&mut self, node: NodeRef);
}
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
impl<T> Node for Arc<RwLock<T>>
where
T: Node,
{
fn connect(&mut self, edge_ref: EdgeRef) {
let mut node = self.write().unwrap();
let mut edge = edge_ref.lock().unwrap();
let self_clone = self.clone() as NodeRef; // the parameter type `T` may not live long enough
edge.connect(self_clone);
node.connect(edge_ref.clone());
}
}
问题是:一个Arc<RwLock<T>>
应该不是引用,所以不应该有生命周期。将其转换为 Arc<RwLock<dyn Node>>
也不引入生命周期。
有人可以解释这个编译器错误吗?这个问题是与每个参数类型(例如 Type<T>
)相关还是仅与 Arc<RwLock<T>>
相关? ?
最佳答案
编译错误解释了如何解决问题:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:22:22
|
15 | impl<T> Node for Arc<RwLock<T>>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
22 | let self_clone = self.clone() as NodeRef;
| ^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/lib.rs:22:22
|
22 | let self_clone = self.clone() as NodeRef;
| ^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0310`.
添加+ 'static
给你的T
的边界确实修复了错误:
use std::sync::{Arc, Mutex, RwLock};
pub trait Node {
fn connect(&mut self, edge: EdgeRef);
}
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub trait Edge {
fn connect(&mut self, node: NodeRef);
}
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
impl<T> Node for Arc<RwLock<T>>
where
T: Node + 'static, // added "+ 'static" here
{
fn connect(&mut self, edge_ref: EdgeRef) {
let mut node = self.write().unwrap();
let mut edge = edge_ref.lock().unwrap();
let self_clone = self.clone() as NodeRef;
edge.connect(self_clone);
node.connect(edge_ref.clone());
}
}
但是当我的 T 永远不会成为引用时,为什么我需要终生绑定(bind)? 你问。好吧,Rust 编译器还不知道,一个 T
可以是任何类型,包括引用。 T
表示的类型集包括由 &T
表示的类型集和 &mut T
.两者 &T
和 &mut T
是 T
的子集.这就是为什么你必须将生命周期限制在 T
上,这是您与编译器沟通的方式,您的 T
将只拥有类型或静态引用。
更多关于“静态生命周期”
'static
是一生的误导性名称,因为它会让大多数人认为 'static
类型必须在程序的整个持续时间内都存在,并且不能动态分配或删除。这些在现实中都不是真的:'static
类型可以动态分配,也可以删除。什么'static
在实践中真正的意思是“你可以无限期地安全地持有这种类型”。所有“拥有的类型”,如 String
和 Vec
是'static
.这是一个 Rust 程序,我希望它能说明这一点:
use rand::prelude::*; // 0.7.3
// this function takes 'static types and drops them
// no compiler errors because 'static types can be dynamically allocated and dropped
fn is_static<T: 'static>(t: T) {
std::mem::drop(t)
}
fn main() {
let string = String::from("string"); // dynamically allocated string
is_static(string); // compiles just fine
let mut strings: Vec<String> = Vec::new();
let mut loops = 10;
while loops > 0 {
if rand::random() {
strings.push(format!("randomly dynamically allocated string on loop {}", loops));
}
loops -= 1;
}
// all the strings are 'static
for string in strings {
is_static(string); // compiles no problem
}
}
关于生命周期省略和默认特征对象生命周期的更多信息
你定义NodeRef
和 EdgeRef
因此:
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
但是 Rust 编译器会这样解释:
pub type NodeRef = Arc<RwLock<dyn Node + 'static>>;
pub type EdgeRef = Arc<Mutex<dyn Edge + 'static>>;
所以当你想投一些Arc<RwLock<T>>
至 NodeRef
然后 T
必须以 Node + 'static
为界因为NodeRef
也有这些界限,即 Arc<RwLock<dyn Node + 'static>>
. Rust 中的所有特征对象都有生命周期,但您通常不会编写它们,因为 Rust 会为您推断它们。 The Rust Reference has a thorough explanation on lifetime elision and default trait object lifetimes如果您想了解更多信息。
你可以缓解 'static
通过使您的类型别名在 'a
上通用来满足要求:
pub type NodeRef<'a> = Arc<RwLock<dyn Node + 'a>>;
pub type EdgeRef<'a> = Arc<Mutex<dyn Edge + 'a>>;
然而,这会显着增加代码的复杂性,我敢肯定你想坚持使用 'static
因为它已经支持您正在尝试做的事情。
关于generics - 将 Arc<RwLock<T>> 转换为 Arc<RwLock<TraitObject>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61712044/
我正在编写一个带有边和节点的图形实现。该图应同时访问,因此我选择将边和节点构建为 Arc>和 Arc> . 不幸的是我得到一个编译错误the parameter type 'T' may not li
我正在尝试分享 RwLock在不使用作用域线程的几个线程中,但我无法弄清楚如何使生命周期正确。我认为这是可能的(否则 RwLocks 有什么意义?)但我找不到任何例子。 这是我正在努力完成的玩具示例。
我有一个定期调用回调函数的线程。根据状态,回调函数应获取 RwLock。与其他线程共享的资源,并保持资源锁定,甚至超出回调函数的范围。然后它将根据状态在稍后的回调周期中再次释放资源。 我的想法是放一个
我刚刚用C实现了一个读写锁,想限制读者的数量,所以用'num'来统计。我不确定这个实现是否有一些潜在的数据竞争或死锁条件。那么你能帮我弄清楚吗? 另一个问题是我可以通过某种方式删除 struct _r
Posix 提供了一种将互斥锁标记为“稳健”的机制,允许多进程系统从持有互斥锁的进程崩溃中正常恢复。 pthread_mutexattr_setrobust(&mutexattr, PTHREAD_M
假设我们有一个用静态初始化器初始化的全局互斥锁或 rwlock: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 或 pthread_rwlock
我一直在使用 RWLock 读取 mysql 数据库,但似乎以下代码在等待解锁时间歇性地锁定程序? // Returns string value from key in table specifie
我正在玩这个玩具结构: pub struct Community { pub community_contents: RwLock, } pub struct CommunityContent
我有一个程序将可变状态隐藏在 RwLock 后面。我想做的是,当它被可变借用时(RW_LOCK.write()),在删除时它应该做一些事情(即尝试写入文件,清理 rwlock 后面的数据等) 例如:
我正在尝试解决 thread-ring问题。在每个线程中,我读取 token 值 如果不是我的,则检查是否是程序结束 如果是则结束线程 否则,再次阅读并重复 如果它是我的(即有我的 id)然后获取写锁
我注意到有时 Rust 会 panic 以防止死锁。例如,这段代码会发生 panic : let rw_lock = RwLock::new(42); { let data0 = rw_loc
当我阅读 Mutex 的文档时和 RwLock ,我看到的区别如下: Mutex 一次只能有一个读取器或写入器, RwLock 一次可以有一个写入器或多个读取器。 当你这么说时,RwLock 似乎总是
pthread 的 rwlock 在以下情况下的指定行为是什么: 有读者阅读, 有一个写者在等待写锁, 请求读锁 是否授予读锁?如果是,是否有办法阻止在为编写器提供服务之前授予读锁? 最佳答案 这是所
如何在信号处理程序中正确销毁 pthread mutex 或 rwlock?例如 - 在下面的代码中,我有主线程和 3 个其他线程。所有线程都使用互斥体和锁在某个数组上无限循环地执行一些任务。因为主线
所以,我正在写一些代码,显然是 R.A.没有警告我关于所有权如何与 lambda 一起使用的一些错误内容。 所以,一个 friend 帮我重写了一些代码,这只是一个游戏示例,但他们的新代码归结为: l
这个问题在这里已经有了答案: How to return a reference to a sub-value of a value that is under a mutex? (5 个答案) 关
这个问题在这里已经有了答案: Type signature of a Rust HashMap of a function (2 个答案) 关闭 4 年前。 我必须通过 Arc>一个函数: use
安全 Rust要求所有引用资料如下: 对资源的一次或多次引用 ( &T ), 只有一个可变引用 ( &mut T )。 我想要一个Vec可以由多个线程读取并由一个线程写入,但一次只能有一个(根据语言要
我正在尝试在可以通过引用进行变异的特征中获得一个值。问题是 String 值非常大并且可能被许多线程访问,所以我的解决方案看起来像这样: trait MyTrait { fn name(&'a
我有几个线程在同一个 Condvar 上等待,该 Condvar 与包装在 RwLock 中的数据相关联。我想调用 Condvar::wait 并在对数据持有写锁后检查条件,但似乎 Condvar::
我是一名优秀的程序员,十分优秀!