Error with &self trying to spawn a blocking tokio thread

⚓ Rust    📅 2025-07-14    👤 surdeus    👁️ 4      

surdeus

I have this struct:

struct IoUringWriteBuffer {
    idx: u8,
    ring: Mutex<IoUring>,
    slot_number_queue: ArrayQueue<u32>,
    buf: Vec<u8>,
    capacity: usize,
    offset: AtomicUsize,
    accessible: AtomicBool,
    values: HashMap<u16, SegQueue<(i64, CacheValue)>>,
    max_ttl: AtomicU64
}

This struct implements several methods, and one of them is:

    async fn flush(&self, iouring_config: &IOUringOneConfig, first_dir: u8) -> Result<WriteResult, IOUringError> {
        let iouring_config_clone = iouring_config.clone();
        let handle = task::spawn_blocking(move || { self.execute_flush(&iouring_config_clone, first_dir) });
        handle.await.unwrap_or_else(|err| Err(IOUringError::FailedToSpawnFlushThread(err)))
    }

This method calls the sync io blocking method execute_flush on a tokio blocking thread.

By doing this, I have to clone the IoUringWriteBuffer to be able to use &self.

So, when I create the IoUringWriteBuffer instances, I need to Arc<IoUringWriteBuffer>.

The point is the IO operation in execute_flush takes around 20 microseconds (iouring write), but it (maybe) could take longer is the disk is stressed, and I don't want to block the thread all this time.
So, I was thinking to create a new thread for that, but at the cost to create Arc instances that I did not need until now.

So the new method is now:

    async fn flush(&self, iouring_config: &IOUringOneConfig, first_dir: u8) -> Result<WriteResult, IOUringError> {
        let iouring_config_clone = iouring_config.clone();
        let self_clone = self.clone();
        let handle = task::spawn_blocking(move || { self_clone.execute_flush(&iouring_config_clone, first_dir) });
        handle.await.unwrap_or_else(|err| Err(IOUringError::FailedToSpawnFlushThread(err)))
    }

But now I get this the error:

async fn flush(&self, iouring_config: &IOUringOneConfig, first_dir: u8) -> Result<WriteResult, IOUringError> {
    |                    -----
    |                    |
    |                    `self` is a reference that is only valid in the method body
    |                    let's call the lifetime of this reference `'1`
...
242 |         let handle = task::spawn_blocking(move || { self_clone.execute_flush(&iouring_config_clone, first_dir) });
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                      |
    |                      `self` escapes the method body here
    |
                  argument requires that `'1` must outlive `'static`

I'm calling the flush method in this way:
buffer.flush(iouring_config, first_dir).await

where buffer in an instance of Arc<IoUringWriteBuffer>

And now I'm stuck on this. Any help would be very appreciated.

2 posts - 1 participant

Read full topic

🏷️ rust_feed