使用thread_local在struct中生锈

时间:2014-12-29 04:32:15

标签: rust lifetime

我正在尝试使用Windows API编写Windows GUI程序,使用thread_local保存所有创建的窗口或按钮。

use std::thread::Thread;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

// button window checkbox need impl this trait.
trait Wnd{
    fn CreateWindow(&self)->int
    {
        // do some thing
        0
    }
}

pub struct Dust{
  window_counter:int,
  hInstance:int,
  hookId: int,
  widgets:HashMap<int, Rc<RefCell<Wnd>>>,
}

fn dust()->RefCell<Dust>{
  unsafe{
    let mut d = Dust{
      window_counter:0,
      hInstance:0,
      hookId:0,
      widgets: HashMap::new(),
    };

    return RefCell::new(d)
  }
}

pub thread_local!(static TLS_DUST: RefCell<Dust> = dust());


fn main()
{

    TLS_DUST.with( | d | {
        let mut dust = d.borrow_mut();
        dust.window_counter-=1;
    });

}

当我构建时出现错误:

$ cargo build --verbose
   Compiling dust v0.0.1 (file:///D:/msys64/home/BYWAYBOY/dust/examples)
     Running `rustc D:\msys64\home\BYWAYBOY\dust\src\lib.rs --crate-name dust --crate-type lib -g -C metadata=3fbf7f518595f4d2 -C extra-filename=-3fbf7f518595f4d2 --out-dir D:\msys64\home\BYWAYBOY\dust\examples\target\deps --emit=dep-info,link -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps`
D:\msys64\home\BYWAYBOY\dust\src\lib.rs:52:36: 52:39 error: explicit lifetime bound required
D:\msys64\home\BYWAYBOY\dust\src\lib.rs:52   widgets:HashMap<HWND, Rc<RefCell<Wnd>>>,
                                                                              ^~~
error: aborting due to previous error
Could not compile `dust`.

Caused by:
  Process didn't exit successfully: `rustc D:\msys64\home\BYWAYBOY\dust\src\lib.rs --crate-name dust --crate-type lib -g -C metadata=3fbf7f518595f4d2 -C extra-filename=-3fbf7f518595f4d2 --out-dir D:\msys64\home\BYWAYBOY\dust\examples\target\deps --emit=dep-info,link -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps -L D:\msys64\home\BYWAYBOY\dust\examples\target\deps` (status=101)

我只想使用HashMap将所有窗口和小部件存储在thread_local中。

1 个答案:

答案 0 :(得分:1)

这是一个带有您的代码版本的防火围栏:http://is.gd/1vAihA

以下是从围栏中复制的代码,让我解释一下我的更改。

您在上面提到的错误来自您的Dust结构声明,特别是widgets字段。 Wnd是一个特征,widget字段的类型使用特征对象类型。特征对象类型允许在运行时进行动态分派,但是,正如编译器所说,您需要在特征对象上指定生命周期绑定。

我指定了特殊的生命周期限制static,因为您将此与thread_local!宏一起使用并将TLS_DUST声明为静态。 'static基本上表示此变量将在程序的整个生命周期中存在。

修正错误后,rustc点击了另一个与Wnd无关的错误SizedSized是一种指定类型在编译时具有已知大小的类型。由于Wnd是一个特征对象,因此可能是任意数量的不同大小,我们必须将其包装在Box<T>中(将Box<T>视为唯一的指针类型)。

我也借此机会为impl写了Dust。这是创建某种类型Dust::new()的新变量的更惯用的方法。我保留了dust()函数,将新的Dust结构包装在RefCell中。

最后,我修复了一些与驼峰案例代码相关的rustc警告,生锈通常使用下划线来分隔单词。

代码:

use std::thread::Thread;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

// button window checkbox need impl this trait.
trait Wnd {
    fn create_window(&self) -> int
    {
        // do some thing
        0
    }
}

struct Dust {
  window_counter: int,
  h_instance: int,
  hook_id: int,
  widgets: HashMap<int, Rc<RefCell<Box<Wnd + 'static>>>>, //'
}

impl Dust {
    fn new() -> Dust {
        Dust {
            window_counter:0,
            h_instance:0,
            hook_id:0,
            widgets: HashMap::new(),
        }
    }

    fn dust() -> RefCell<Dust> {
        RefCell::new(Dust::new())
    }
}

pub thread_local!(static TLS_DUST: RefCell<Dust> = Dust::dust());

fn main()
{
    TLS_DUST.with( | d | {
        let mut dust = d.borrow_mut();
        dust.window_counter-=1;
    });
}