Общее изменяемое состояние в Hyper - PullRequest
0 голосов
/ 24 октября 2018

Я пытаюсь создать счетчик на веб-сервере Hyper, который подсчитывает количество полученных запросов.Я использую Arc<Mutex<u64>>, чтобы удержать счет.Однако я не смог найти правильную комбинацию move и .clone() для соответствия типам замыканий.Вот некоторый код, который компилируется, но сбрасывает счетчик при каждом запросе:

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)))
}

1 Ответ

0 голосов
/ 24 октября 2018

Оказывается, я был довольно близок, и просмотр нескольких других примеров помог мне понять проблему.Поскольку здесь находятся два слоя замыканий, мне нужно переместить counter во внешнее закрытие, клонировать его, а затем переместить этот клон во внутреннее закрытие и снова клонировать туда.Для остроумия:

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)))
}
...