Здравствуйте!
Натолкнулся на первую серьезную проблему с заимствованием. Задача - нужно, чтобы веб-сервер обработал один запрос и завершился. Код такой
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
let (sender, receiver) = futures::sync::oneshot::channel::<()>();
let proc = || {
let res = service_fn_ok(got_google_response);
sender.send(());
res
};
let server = Server::bind(&addr)
.serve(proc)
.with_graceful_shutdown(receiver)
.map_err(|e| eprintln!("server error: {}", e));
Rust компилировать отказывается т.к. serve требует Fn, но proc имеет тип FnOnce из-за того, что метод send принимает объект sender во владение.
Сделать канал не oneshot тоже не выходит, т.к. with_graceful_shutdown требует именно его.
Как обойти данную проблему? Есть какой-то подход?
Спасибо.
В принципе можно так сделать:
let (sender, receiver) = futures::sync::oneshot::channel::<()>();
let sender = RefCell::new(Some(sender));
let proc = || {
let res = service_fn_ok(got_google_response);
sender.borrow_mut().take().map(|s| s.send(()));
res
};
А take() - это чей метод? Что-то не могу его найти ни в Sender ни в Arc.
Компилятор тоже на это ругается
no method named `take` found for type `&mut auth::futures::Sender<()>` in the current scope
И c map - та же история. Получилось вот так
sender.borrow_mut().send(());
Но теперь компилятор ругается
this closure implements `FnMut`, not `Fn`
А просто с borrow
|
59 | sender.borrow().send(());
| ^^^^^^^^^^^^^^^ cannot move out of borrowed content
let sender = RefCell::new(Some(sender));
^^^^
Внутри RefCell должен быть Option<Sender>.
Получилось! Откомпилировалось, по крайней мере. Вот окончательный вариант.
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
let (sender, receiver) = futures::sync::oneshot::channel::<()>();
let sender = RefCell::new(Some(sender));
let proc = move || {
let res = service_fn_ok(got_google_response);
sender.borrow_mut().take().unwrap().send(());
res
};
Сейчас попытаюсь это осознать 
Тут лучше вместо unwrap() сделать как я выше писал. Можно панику словить если следующий пакет придет до того как сервер остановится.
Не пойму, зачем тут Option. Т.е. да, без него не компилируется и понятно почему.
|
61 | sender.borrow_mut().send(());
| ^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
Но как Option решает эту проблему?
Нельзя переместить заимствованные данные. Option остается заимствованным, но при этом позволяет переместить то, что лежит у него внутри с помощью take().
Т.е., мой вариант кода упадёт при повторном вызове proc, т.к. в Option уже будет не Some, а None? Другими словами, здесь Option используется как контейнер для транспортировки значения?