Hyper中的共享可变状态 [英] Shared mutable state in Hyper

查看:104
本文介绍了Hyper中的共享可变状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Hyper Web服务器中创建一个计数器,该计数器对已收到的请求数进行计数.我正在使用Arc<Mutex<u64>>保持计数.但是,我无法找出move.clone()的正确组合来满足闭包的类型.以下是一些可编译的代码,但会在每个请求时重置计数器:

I'm trying to create a counter in a Hyper web server that counts the number of requests it has received. I'm using a Arc<Mutex<u64>> to hold onto count. However, I haven't been able to figure out the right combination of move and .clone() to satisfy the types of the closures. Here's some code that compiles, but resets the counter on each request:

extern crate hyper;

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    // FIXME want to create the counter here, not below
    let server = Server::bind(&addr)
        .serve(|| {
            service_fn_ok(|_req| {
                let counter = Arc::new(Mutex::new(0));
                use_counter(counter)
            })
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}

推荐答案

事实证明我已经很接近了,看看其他一些例子可以帮助我认识到这个问题.由于这里有两个封闭层,我需要将counter移到外部封闭中,对其进行克隆,然后将其复制到内部封闭中,然后再次克隆到内部.发挥作用:

It turns out I was pretty close, and looking at a few other examples helped me realize the problem. Since there are two layers of closures at play here, I need to move the counter into the outer closure, clone it, and then move that clone into the inner closure and clone there again. To wit:

extern crate hyper; // 0.12.10

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    let counter = Arc::new(Mutex::new(0));
    let server = Server::bind(&addr)
        .serve(move || {
            let counter = counter.clone();
            service_fn_ok(move |_req| use_counter(counter.clone()))
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}


2020年2月更新,以下是使用超级0.13的版本:


Update February 2020 Here's a version using hyper 0.13:

use hyper::{Body, Response, Server, Request};
use std::sync::{Arc, Mutex};
use hyper::service::{make_service_fn, service_fn};
use std::convert::Infallible;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "0.0.0.0:3000".parse()?;
    let counter = Arc::new(Mutex::new(0));

    let make_service = make_service_fn(move |_conn| {
        let counter = counter.clone();
        async move {
            Ok::<_, Infallible>(service_fn(move |_req: Request<Body>| {
                let counter = counter.clone();
                async move {
                    Ok::<_, Infallible>(use_counter(counter))
                }
            }))
        }
    });

    Server::bind(&addr).serve(make_service).await?;
    Ok(())
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}

这篇关于Hyper中的共享可变状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆