Issue passing mutable Arc reference to hyper service_fn handler

蹲街弑〆低调 提交于 2021-01-24 07:09:21

问题


I've been trying the following

Relevant imports and code shown

use std::sync::{Arc, Mutex};
use std::thread;
use hyper::rt::{self, Future, Stream};
use hyper::service::service_fn;
use hyper::{Body, Request, Response, Server, StatusCode};

pub struct ChallengeState;
pub struct ChallengeResponse;

type BoxFut<'a> = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send + 'a>;

fn handle_challengeproof<'a>(
    req: Request<Body>,
    challenge: &Arc<Mutex<ChallengeState>>,
) -> BoxFut<'a> {
    let resp = req.into_body().concat2().map(move |body| {
        let challenge_lock = challenge.lock().unwrap();
        Response::builder()
        .status(StatusCode::OK)
        .body(Body::from("test"))
        .unwrap()
    });
    Box::new(resp)
}

fn handle<'a>(
    req: Request<Body>,
    challenge: &Arc<Mutex<ChallengeState>>,
) -> BoxFut<'a> {
    handle_challengeproof(req, challenge)
}

pub fn run_listener(
    challenge: Arc<Mutex<ChallengeState>>,
) -> thread::JoinHandle<()> {
    let addr = ([127, 0, 0, 1], 9999).into();

    let listener_service = move || {
        let challenge = Arc::clone(&challenge);
        service_fn(move |req: Request<Body>| {
            handle(req, &challenge)
        })
    };

    let server = Server::bind(&addr)
        .serve(listener_service)
        .map_err(|_| () );

    thread::spawn(move || {
        rt::run(server);
    })
}

I've been trying to avoid an extra clone of Arc by passing a reference to the handle method but can't seem to get around this. Avoiding the lifetime on handle() got a different error regarding futures asking for static lifetime.

Code updated with only relevant stuff @ https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=10ea31450e88a122455006760d7fcdd1


回答1:


The whole point of an Arc is that it counts how many references there are, which happens when it is cloned. Passing around references to an Arc defeats the point.

Instead of passing references, pass the Arc itself. So handle's signature becomes:

fn handle<'a>(
    req: Request<Body>,
    challenge: Arc<Mutex<ChallengeState>>,
) -> BoxFut<'a>

Passing the Arc by references from the closure isn't possible because you would be referencing something that immediately goes out of scope. Instead, move the Arc into handle:

let listener_service = move || {
    service_fn(move |req: Request<Body>| handle(req, challenge))
}; 


来源:https://stackoverflow.com/questions/55164529/issue-passing-mutable-arc-reference-to-hyper-service-fn-handler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!