Trouble with lifetimes in Queue Implementation

I am trying to create a simple queue for rate limiting by wrapping a tokio::sync::Semaphore

Essentially I need a queue to rate limit access with a certain number of slots and to know the length but I am struggling a bit with the life times required

My code is below

use tokio::sync::{Semaphore,OwnedSemaphorePermit};
use std::sync::{Arc,atomic::{AtomicU32, Ordering}};

pub struct QueuePermit<'a> {
    permit:OwnedSemaphorePermit,
    queue: & 'a Queue,
}

impl <'a> Drop for QueuePermit<'a> {
    fn drop(&mut self) {
        self.queue.size.fetch_sub(1, Ordering::Relaxed);
    }
}

/// A basic queue implamentation that wraps a Tokio::Semaphore and keeps track of the searches and size
pub struct Queue {
    lock: Arc<Semaphore>,
    size: AtomicU32,
}

impl Queue {

    pub fn new (search_slots:usize) -> Self {
        Self{
            lock: Arc::new(Semaphore::new(search_slots)),
            size: AtomicU32::new(0u32),
        }
    }

    pub async fn enqueue<'a>(&'a self) -> QueuePermit<'a> {
    
        // Increment size and try to acquire a permit
        self.size.fetch_add(1, Ordering::Relaxed);

        // Acquire a permit from the underlying semaphore
        let permit = self.lock.acquire_owned().await;

        QueuePermit {
            permit:permit,
            queue:&self
        }

    }

}

Now obviously the permit must live as long as the queue but I can quite figure out how to communicate that.
A link to the code in the playground is here https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=44bb3b920786fae97dd7f13859e3568e Also if there is a better way to go about this any input is greatly appreciated

How about this?

pub async fn enqueue<'a>(&'a self) -> QueuePermit<'a> {

    // Increment size and try to acquire a permit
    self.size.fetch_add(1, Ordering::Relaxed);

    // Acquire a permit from the underlying semaphore
    let permit = self.lock.clone().acquire_owned().await;

    QueuePermit {
        permit:permit,
        queue:&self
    }
}
1 Like

Thanks Alice!

Check the sequence implementation https://crates.io/crates/seq

Thanks for the tip, I will check it out