将Arc传递给异步处理程序

时间:2020-02-11 21:33:21

标签: rust rust-tokio hyper

我有一个全局状态,可以在代码中使用它。对于我的超级请求处理,我生成了一个本地状态来将数据分组以便于访问。我决定对全局静态变量使用Arc<Mutex<_>>进行线程安全访问。现在,我在传递Arc时遇到了问题。我创建的示例代码以相同的方式失败。如何解决和了解这一点?

use hyper::{
    service::{make_service_fn, service_fn},
    Body, Response, Server,
}; // 0.13.2

use std::{
    process::exit,
    sync::{Arc, Mutex},
};

struct GlobalState {
    id: u64,
    name: String,
}

impl GlobalState {
    pub fn unregister(&self) {
        println!("Unregister {}", self.id);
    }
}

struct LocalState {
    global_state: Arc<Mutex<GlobalState>>,
}

impl LocalState {
    pub fn new(global_state: Arc<Mutex<GlobalState>>) -> Self {
        LocalState { global_state }
    }

    pub fn name(&self) -> &str {
        self.global_state.lock().unwrap().name.as_str()
    }
}

async fn handle_request(local_state: LocalState) -> Result<Response<Body>, String> {
    println!("Name {}", &local_state.name());

    Ok(Response::new(Body::from("test".to_string())))
}

async fn start(port: u16, global_state: Arc<Mutex<GlobalState>>) -> Result<(), String> {
    let service = make_service_fn(move |_| async {
        Ok::<_, String>(service_fn(move |request| async {
            let local_state = LocalState::new(global_state);

            handle_request(local_state).await
        }))
    });

    let addr = format!("0.0.0.0:{}", port).parse().unwrap();
    let server = Server::bind(&addr).serve(service);

    println!("Listening on {}", addr);

    server.await.map_err(|error| format!("Error: {}", error))
}

#[tokio::main]
async fn main() {
    let global_state = Arc::new(Mutex::new(GlobalState {
        id: 1,
        name: "name".to_string(),
    }));

    let gs_clone1 = global_state.clone();
    let gs_clone2 = global_state.clone();

    let server_handle = tokio::spawn(async {
        if let Err(error) = start(8088, gs_clone1).await {
            println!("Server failed: {}", error);
        }
    });

    let abort_handle = tokio::spawn(async move {
        if let Err(error) = tokio::signal::ctrl_c().await {
            println!("Signal handling failed: {}", error);
        }
        println!("User terminated the process");
        // Remove download server from list
        gs_clone2.lock().unwrap().unregister();
        exit(1);
    });

    tokio::try_join!(server_handle, abort_handle).unwrap();
}

它抱怨移动,因为每个请求都会调用闭包,因此不能多次移动它。当我尝试将其作为参考传递时,借阅检查器抱怨.serve(service)返回了'static的生存期。

warning: unused variable: `request`
  --> src/main.rs:44:42
   |
44 |         Ok::<_, String>(service_fn(move |request| async {
   |                                          ^^^^^^^ help: consider prefixing with an underscore: `_request`
   |
   = note: `#[warn(unused_variables)]` on by default

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:32:9
   |
32 |         self.global_state.lock().unwrap().name.as_str()
   |         ---------------------------------^^^^^^^^^^^^^^
   |         |
   |         returns a value referencing data owned by the current function
   |         temporary value created here

error[E0507]: cannot move out of `global_state`, a captured variable in an `FnMut` closure
  --> src/main.rs:44:57
   |
42 |   async fn start(port: u16, global_state: Arc<Mutex<GlobalState>>) -> Result<(), String> {
   |                             ------------ captured outer variable
43 |       let service = make_service_fn(move |_| async {
44 |           Ok::<_, String>(service_fn(move |request| async {
   |  _________________________________________________________^
45 | |             let local_state = LocalState::new(global_state);
   | |                                               ------------
   | |                                               |
   | |                                               move occurs because `global_state` has type `std::sync::Arc<std::sync::Mutex<GlobalState>>`, which does not implement the `Copy` trait
   | |                                               move occurs due to use in generator
46 | |
47 | |             handle_request(local_state).await
48 | |         }))
   | |_________^ move out of `global_state` occurs here

error[E0507]: cannot move out of `global_state`, a captured variable in an `FnMut` closure
  --> src/main.rs:43:50
   |
42 |   async fn start(port: u16, global_state: Arc<Mutex<GlobalState>>) -> Result<(), String> {
   |                             ------------ captured outer variable
43 |       let service = make_service_fn(move |_| async {
   |  __________________________________________________^
44 | |         Ok::<_, String>(service_fn(move |request| async {
45 | |             let local_state = LocalState::new(global_state);
   | |                                               ------------
   | |                                               |
   | |                                               move occurs because `global_state` has type `std::sync::Arc<std::sync::Mutex<GlobalState>>`, which does not implement the `Copy` trait
   | |                                               move occurs due to use in generator
46 | |
47 | |             handle_request(local_state).await
48 | |         }))
49 | |     });
   | |_____^ move out of `global_state` occurs here

0 个答案:

没有答案
相关问题