I have a WriterJob
struct. Its functionality is not important; what it does is that it spawns a long-running task and provides callers an api to check the status of the job.
pub(crate) struct WriterJob {
...,
status: Status,
}
impl WriterJob {
async fn writer_job_impl(&mut self, rx: Receiver<WriteCommand>) {
// Job implementation details. It's important that `self` is mutuable
// since I update the job status
// eg.
// self.status = Status::Ready;
}
pub(crate) fn status(&self) -> Status {
self.status
}
pub(crate) fn spawn_writer_job(&mut self) -> Sender<WriteCommand> {
let (tx, rx) = mpsc::channel(10);
let handle = tokio::spawn(async move {
self.writer_job_impl(rx).await;
});
self.status = Status::Spawned;
tx
}
I get this error:
error[E0521]: borrowed data escapes outside of associated function
--> src/io/buffered_write.rs:92:22
|
89 | pub(crate) fn spawn_writer_job(&mut self) -> Sender<WriteCommand> {
| ---------
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
...
92 | let handle = tokio::spawn(async move {
| ______________________^
93 | | self.writer_job_impl(rx).await;
94 | | });
| | ^
| | |
| |__________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
I think I understand that the compiler is complaining that it doesn't know whether self
will live as long as the spawned task hence a lifetime error. But I'm not sure what a good approach to this is. One possibility is to use Arc<Mutex<Status>>
or Arc<RwLock<Status>>
but I don't like this approach because I will probably need to add more mutuable fields in self
. Are there cleaner ways to do this?