Я не слишком знаком с внутренностями jsonrpc, но библиотека jsonrpc реализована в Tokio совершенно асинхронно.Несмотря на то, что вы вызываете синхронную обработку запросов, внутренне он все равно выполняет запрос асинхронно и просто блокирует ваш поток, пока он не будет выполнен.Недостатком этого является то, что Tokio не может гарантировать что-либо о планировании ваших замыканий в исполнителе задач.Таким образом, время жизни любого такого замыкания связано с исполнителем больше, чем любое self
.
. В приведенном выше коде вы фиксируете ссылку на self
, но нет гарантии, что self
все еще живет, когда замыканиевыполнен.Следовательно, вы должны move
любые данные, используемые закрытием.Кроме того, закрытие должно быть Send
для использования с Tokio, поэтому вы не можете просто использовать Rc
и переместить копию в закрытие.
В вашем случае самый простой способ, который я знаю, этозамените test
на тип Arc<Test>
.Затем измените определение замыкания, чтобы переместить копию переменной в замыкание.У вас также были некоторые проблемы с изменчивостью, вот полный пример, который компилируется:
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate jsonrpc_core as rpc;
use std::borrow::Borrow;
use std::sync::Arc;
#[derive(Serialize, Deserialize)]
struct Test {
var: u32,
}
struct TestRpc {
test: Arc<Test>,
rpc_io_handler: rpc::IoHandler,
}
impl TestRpc {
fn new() -> Self {
let mut ret = Self {
test: Arc::new(Test { var: 1 }),
rpc_io_handler: rpc::IoHandler::new(),
};
ret.register_rpc_methods();
ret
}
fn register_rpc_methods(&mut self) {
let test_clone = self.test.clone();
let get_var = move |_params: rpc::Params| match rpc::to_value(test_clone.borrow() as &Test)
{
Ok(x) => Ok(x),
Err(_) => Err(rpc::Error::internal_error()),
};
self.rpc_io_handler.add_method("get_var", get_var);
}
fn get_var_test(&self, msg: &str) -> Option<String> {
self.rpc_io_handler.handle_request_sync(msg)
}
}
fn main() {
let test = TestRpc::new();
let request = r#"{"jsonrpc": "2.0", "method": "get_var", "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"var":1},"id":1}"#;
assert_eq!(test.get_var_test(request), Some(response.to_owned()));
}