3

我正在使用 Iron 框架来创建一个简单的端点。我有端点需要访问的有状态的、可变的数据。

这是一些显示我意图的代码:

extern crate iron;
extern crate mount;

use iron::{Iron, Request, Response, IronResult};
use iron::status;
use mount::Mount;

static mut s_counter: Option<Counter> = None;

struct Counter {
    pub count: u8
}

impl Counter {
    pub fn new() -> Counter {
        Counter {
            count: 0
        }
    }

    pub fn inc(&mut self) {
        self.count += 1;
    }
}

fn main() {
    unsafe { s_counter = Some(Counter::new()); }
    let mut mount = Mount::new();
    mount.mount("/api/inc", inc);
    println!("Server running on http://localhost:3000");
    Iron::new(mount).http("127.0.0.1:3000").unwrap();
}

fn inc(req: &mut Request) -> IronResult<Response> {
    let mut counter: Counter;
    unsafe {
        counter = match s_counter {
            Some(counter) => counter,
            None => { panic!("counter not initialized"); }
        };
    }
    counter.inc();
    let resp = format!("{}", counter.count);
    Ok(Response::with((status::Ok, resp)))
}

此代码无法编译:

error: cannot move out of static item

我希望有更好的方法来做到这一点,不涉及任何不安全的代码或static mut. 我的问题是,实现这一目标的惯用方法是什么?

4

1 回答 1

5

我强烈推荐阅读The Rust Programming Language的全部内容,尤其是关于并发的章节。Rust 社区投入了大量精力来制作高质量的文档来帮助人们。

在这种情况下,我可能只是将Counter结构设为 Iron Handler。然后,我将在结构内使用原子变量来保存计数而不需要可变性:

extern crate iron;
extern crate mount;

use std::sync::atomic::{AtomicUsize, Ordering};

use iron::{Iron, Request, Response, IronResult};
use iron::status;
use mount::Mount;

struct Counter {
    count: AtomicUsize,
}

impl Counter {
    pub fn new() -> Counter {
        Counter {
            count: AtomicUsize::new(0),
        }
    }
}

fn main() {
    let mut mount = Mount::new();
    mount.mount("/api/inc", Counter::new());
    println!("Server running on http://localhost:3000");
    Iron::new(mount).http("127.0.0.1:3000").unwrap();
}

impl iron::Handler for Counter {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        let old_count = self.count.fetch_add(1, Ordering::SeqCst);

        let resp = format!("{}", old_count);

        Ok(Response::with((status::Ok, resp)))
    }
}
于 2015-09-21T02:33:25.437 回答