Rust中状态+回调的唯一指针

时间:2013-05-25 21:39:36

标签: rust

我试图将一个结构中的状态与变异状态的回调捆绑在一起。当我使用托管指针时,它工作正常:

struct StateAndCallbacks01 {
  state: @mut int,
  inc: @fn(),
  dec: @fn()
}

let state01: @mut int = @mut 0;
let inc01: @fn() = || {
  *state01 += 1;
};
let dec01: @fn() = || {
  *state01 -= 1;
};
let state_cbs_01 = @StateAndCallbacks01 {
  state: state01,
  inc: inc01,
  dec: dec01
};
(state_cbs_01.inc)();
println(fmt!("state: %d", *state_cbs_01.state));
(state_cbs_01.dec)();
println(fmt!("state: %d", *state_cbs_01.state));

接下来,我想将此结构发送到另一个任务,因此必须在任何地方切换到唯一指针。我无法做到这一点:“错误:过时的语法:const或mutable拥有指针”

struct StateAndCallbacks02 {
  state: ~mut int,
  inc: ~fn(),
  dec: ~fn()
}

let state02: ~mut int = ~mut 0;
let inc02: ~fn() = || {
  *state02 += 1;
};
let dec02: ~fn() = || {
  *state02 -= 1;
};
let state_cbs_02 = ~StateAndCallbacks02 {
  state: state02,
  inc: inc02,
  dec: dec02
};

let (port, chan): (Port<bool>, Chan<bool>) = stream();
do spawn {
  (state_cbs_02.inc)();
  println(fmt!("state: %d", *state_cbs_02.state));
  (state_cbs_02.dec)();
  println(fmt!("state: %d", *state_cbs_02.state));
  chan.send(true);
};
let result = port.recv();
println(fmt!("result: %s", result));

有什么建议吗?有没有更好的方法来跨任务发送回调?

1 个答案:

答案 0 :(得分:3)

不是将函数保存为结构中的字段,而是可以在结构中添加方法。

struct Foo {
    data: int
}

impl Foo {
    fn inc(&mut self) {
        self.data += 1;
    }
}

impl语法允许您在结构上定义方法。您可以稍后致电:

let mut my_foo = Foo { data: 0 };
my_foo.inc();

您必须将my_foo声明为可变,因为inc方法需要对其进行可变引用。

语法错误的原因是因为不推荐使用~mut 0,因为可变性取决于谁拥有该对象。你需要做的是let mut foo = ~0。变量foo是“所有者”,因此是您声明可变性的地方。 @-指针的特殊之处在于它们不会继承可变性并由任务本地GC管理。 (Rust tutorial的第8节和第9节更好地解释了这一点)

所以把所有这些放在一起,你可以像这样编写原始代码:

struct State {
    data: int 
}

impl State {
    fn inc(&mut self) {
        self.data += 1;
    }   

    fn dec(&mut self) {
        self.data -= 1;
    }   
}

fn main() {

    let state = State {
        data: 0
    };  

    let (port, chan) = stream();

    do spawn {

        let mut state = state;

        state.inc();
        println(fmt!("State: %d", state.data));
        state.dec();
        println(fmt!("State: %d", state.data));

        chan.send(true);
    };  

    let result = port.recv();
    println(fmt!("Result: %?", result));

}