我正在尝试将非静态闭包传递给tokio。显然,这是行不通的。有没有办法确保生存期在运行时合适?这是我尝试过的:
尝试Arc
为了不将闭包直接传递给tokio,我将其放入管理计时器的结构中:
type Delays<'l,K: Eq + Hash + Debug + Copy + Send> = HashMap<K,Box<dyn FnOnce() + 'l + Send>>;
pub struct Timers<'l,K: Eq + Hash + Debug + Clone + Send> {
delays: Arc<Mutex<Delays<'l,K>>>,}
该结构的impl
使我们可以轻松添加和删除计时器。我的计划是通过仅移动Weak
引用,以某种方式将静态闭包传递给tokio
到互斥的哈希图:
// remember handler function
delays.insert(key.clone(),Box::new(func));
// create a weak reference to the delay map to pass into the closure
let weak_handlers = Arc::downgrade(&self.delays);
// task that runs after a delay
let task = Delay::new(Instant::now() + delay)
.map_err(|e| warn!("Tokio timer error: {}",e)) // Map the error type to ()
.and_then(move |_| {
// get the handler from the table,of which we have only a weak ref.
let handler = Weak::upgrade(&weak_handlers)
.ok_or(())? // If the Arc dropped,return an error and thus aborting the future
.lock()
.remove(&key)
.ok_or(())?; // If the handler isn't there anymore,we can abort aswell.
// call the handler
handler();
Ok(())
});
因此,如果丢弃了哈希表,则使用Weak
我们确保我们放弃。
重要的是要知道生命周期'l
与Timers
结构的生命周期是相同的,但是我该如何告诉编译器呢?另外,我认为真正的问题是Weak<T>: 'static
不满意。
使用unsafe
自己写
我尝试构建类似于Sc的东西来实现这一目标。首先,Sc将在这里工作吗?我阅读并理解了代码。我看不到任何明显的问题-尽管很难得出map
方法实际上是安全的结论,因为肯定会在map
的末尾删除引用,并且没有存储在某个地方。
因此,我尝试使Sc适应我的需求。这只是一个粗略的概述,我知道与此有关的一些问题,但是我相信这样的事情应该是可能的:
- 有一个
struct Doa<T>
拥有T
-
Doa::ref(&self) -> DoaRef<T>
将产生一个不透明的对象,该对象内部包含一个对拥有的对象的*const u8
。 -
-
DoaRef
不包含具有非静态生存期的引用,因此可以传递给tokio。
-
- 具有
impl<T> Drop for Doa<T>
将该*const u8
设置为null
- 因此
DoaRef
现在可以检查该值是否仍然存在并获取对其的引用。
我还尝试确保&self
中ref
的生存期必须长于T
中引用的生存期,以确保仅在Doa
时有效确实比指针指向的对象寿命更长。
struct Doa<'t,T: 'l> { ... }
pub fn ref(&'s self) -> DoaRef<T> where 't: 'a
但是随后T
受到了生命周期的限制,并且由于DoaRef
对其进行了参数化,因此DoaRef: 'static
不再适用。
或者是否有一些板条箱,甚至std
中的某些东西可以做到这一点?