Repository: tokio-rs/tokio
File: tokio/src/runtime/io/driver/uring.rs (Rust)

Code before:
                Err(e) if e.raw_os_error() == Some(libc::ENOSYS) => {
                    self.set_uring_state(State::Unsupported);
                    Ok(false)
                }
                // For other system errors, we just return it.
                Err(e) => Err(e),
            },
            State::Unsupported => Ok(false),
            State::Initialized => Ok(true),
        }
    }

    /// Initialize the io_uring context if it hasn't been initialized yet.
    fn try_init(&self) -> io::Result<()> {
        let mut guard = self.get_uring().lock();
        if guard.try_init()? {
            self.add_uring_source(guard.ring().as_raw_fd())?;
        }

        Ok(())
    }

    /// Register an operation with the io_uring.
    ///
    /// If this is the first io_uring operation, it will also initialize the io_uring context.
    /// If io_uring isn't supported, this function returns an ENOSYS error, so the caller can
    /// perform custom handling, such as falling back to an alternative mechanism.
    ///
    /// # Safety
    ///
    /// Callers must ensure that parameters of the entry (such as buffer) are valid and will
    /// be valid for the entire duration of the operation, otherwise it may cause memory problems.
    pub(crate) unsafe fn register_op(&self, entry: Entry, waker: Waker) -> io::Result<usize> {
        // Fist, check if the uring is initialized. Callers can use
        // Note: Maybe this check can be removed if upstream callers consistently use `check_and_init`.
        if !self.check_and_init()? {
            return Err(io::Error::from_raw_os_error(libc::ENOSYS));
        }

        // Uring is initialized.

        let mut guard = self.get_uring().lock();
        let ctx = &mut *guard;
        let index = ctx.ops.insert(Lifecycle::Waiting(waker));
        let entry = entry.user_data(index as u64);

        let submit_or_remove = |ctx: &mut UringContext| -> io::Result<()> {
            if let Err(e) = ctx.submit() {
                // Submission failed, remove the entry from the slab and return the error
                ctx.remove_op(index);
                return Err(e);

Review comment (suggestion):
With this, you no longer need it in the dictionary.
```suggestion
    /// If io_uring isn't supported, this function returns an `ENOSYS` error, so the caller can
```

Code after:
                Err(e) if e.raw_os_error() == Some(libc::ENOSYS) => {
                    self.set_uring_state(State::Unsupported);
                    Ok(false)
                }
                // For other system errors, we just return it.
                Err(e) => Err(e),
            },
            State::Unsupported => Ok(false),
            State::Initialized => Ok(true),
        }
    }

    /// Initialize the io_uring context if it hasn't been initialized yet.
    fn try_init(&self) -> io::Result<()> {
        let mut guard = self.get_uring().lock();
        if guard.try_init()? {
            self.add_uring_source(guard.ring().as_raw_fd())?;
        }

        Ok(())
    }

    /// Register an operation with the io_uring.
    ///
    /// If this is the first io_uring operation, it will also initialize the io_uring context.
    /// If io_uring isn't supported, this function returns an `ENOSYS` error, so the caller can
    /// perform custom handling, such as falling back to an alternative mechanism.
    ///
    /// # Safety
    ///
    /// Callers must ensure that parameters of the entry (such as buffer) are valid and will
    /// be valid for the entire duration of the operation, otherwise it may cause memory problems.
    pub(crate) unsafe fn register_op(&self, entry: Entry, waker: Waker) -> io::Result<usize> {
        // Note: Maybe this check can be removed if upstream callers consistently use `check_and_init`.
        if !self.check_and_init()? {
            return Err(io::Error::from_raw_os_error(libc::ENOSYS));
        }

        // Uring is initialized.

        let mut guard = self.get_uring().lock();
        let ctx = &mut *guard;
        let index = ctx.ops.insert(Lifecycle::Waiting(waker));
        let entry = entry.user_data(index as u64);

        let submit_or_remove = |ctx: &mut UringContext| -> io::Result<()> {
            if let Err(e) = ctx.submit() {
                // Submission failed, remove the entry from the slab and return the error
                ctx.remove_op(index);
                return Err(e);
            }