实现每线程全局上下文堆栈

时间:2017-10-19 14:20:47

标签: rust

我希望实现一个线程局部全局堆栈,以便每个堆栈元素代表该线程当前正在做的事情。这就是我所拥有的:

use std::mem;
use std::cell::RefCell;

struct Activity {
    description: String
}

struct StackElement {
    activity: Activity,
    prev: StackNode
}

type StackNode = Option<Box<StackElement>>;

struct Stack {
    top: StackNode
}

thread_local!(static CONTEXT: RefCell<Stack> = RefCell::new( Stack { top: None }));

static AMIT: u32 = 3;

struct StackDisposer<'a> {
    stack: &'a mut Stack
}

impl<'a> Drop for StackDisposer<'a> {
    fn drop(&mut self) {
        let prev = if let Some(ref mut boxed_element) = self.stack.top { (*boxed_element).prev } else { None };
        mem::replace(&mut self.stack.top, prev );
    }
}

impl Stack {
    fn get_instance() -> &'static Stack {
        // The compilation error is coming from here
        CONTEXT.with(|s| {
           &*s.borrow_mut()
        })
    }

    fn push_new_activity(&mut self, description: String) -> StackDisposer {
        let element = Box::new(StackElement {
            activity: Activity { description: description},
            prev: mem::replace(&mut self.top, None),
        });
        self.top = Some(element);
        StackDisposer { stack: self }
    }
}

但是,我收到了编译错误:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:38:16
   |
38 |            &*s.borrow_mut()
   |                ^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 37:22...
  --> src/main.rs:37:22
   |
37 |           CONTEXT.with(|s| {
   |  ______________________^
38 | |            &*s.borrow_mut()
39 | |         })
   | |_________^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:38:14
   |
38 |            &*s.borrow_mut()
   |              ^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:37:9
   |
37 | /         CONTEXT.with(|s| {
38 | |            &*s.borrow_mut()
39 | |         })
   | |__________^

我们的想法是客户端代码可以编写如下内容:

fn foo() {
    let disposer1 = Stack::get_instance().push_new_activity("outer_activity");
    {
        let disposer2 = Stack::get_instance().push_new_activity("inner_activity");
        // ...
        // "inner_activity" should be popped here
    }
    // ...
    // "outer_activity" should be popped here
}

如何修复编译错误?

0 个答案:

没有答案