Hello Rustaceans!
I can't see to find the correct design for my system.
I've got a gRPC server responding to requests. I want the structural type implementing the server to accept a request, then process it in an async function.
use tokio::runtime::Runtime;
struct ConcreteServer {
pool: Arc<Runtime>,
cache: Mutex<Vec<i32>>,
}
impl Server for ConcreteServer {
async fn ping(&self, request: Request<PingRequest>) -> Result<Response<PingResponse> {
// Spawn a new thread to do work on.
self.pool.spawn(async {
// Perform work using fields and methods on the ConcreteServer type.
// All such fields are Send and Sync.
let mut data = self.cache.lock().unwrap();
data.push(5);
});
// Reply immediately.
let reply = PingReply {};
Ok(Response::new(reply))
}
}
The error I'm getting is cannot infer an appropriate lifetime for autoref due to conflicting requirements
.
I think I understand the error: the lifetime of &self
is not guaranteed to outlive the lifetime of the spawned thread. ping
could up the stack and eventually deallocate the stack frame containing the ConcreteServer
, creating a use-after-free in my spawned thread.
So I'm obviously designing my programs incorrectly. I can't figure out a way to do what I'd like, which is to offload work to a thread, using the TCP connections I'm caching on the ConcreteServer
struct. How can I lend a field from a struct to another thread, promising that the lifetime of the ConcreteServer
is static?