问题
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