use std::cell::{Cell, RefCell};
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll};
pub mod container;
pub use container::{Container, ContainerGetRequest, ContainerPutRequest};
mod preemptive;
pub use preemptive::{PreemptiveGuard, PreemptiveRequest, PreemptiveResource};
pub mod priority;
pub use priority::{PriorityResource, PriorityResourceGuard, PriorityResourceRequest};
pub(crate) mod wait_queue;
use wait_queue::WaitQueue;
#[derive(Clone)]
pub struct Resource {
state: Rc<RefCell<WaitQueue<()>>>,
}
impl std::fmt::Debug for Resource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut d = f.debug_struct("Resource");
if let Ok(q) = self.state.try_borrow() {
d.field("in_use", &q.in_use())
.field("capacity", &q.capacity())
.field("queue_len", &q.live_waiters());
}
d.finish_non_exhaustive()
}
}
impl Resource {
#[must_use]
pub fn new(capacity: usize) -> Self {
assert!(capacity > 0, "Resource capacity must be at least 1");
Resource {
state: Rc::new(RefCell::new(WaitQueue::new(capacity))),
}
}
#[must_use = "futures do nothing unless awaited"]
pub fn request(&self) -> ResourceRequest {
ResourceRequest {
state: Rc::clone(&self.state),
registered: false,
consumed: false,
canceled: Rc::new(Cell::new(false)),
granted: Rc::new(Cell::new(false)),
}
}
#[must_use]
pub fn in_use(&self) -> usize {
self.state.borrow().in_use()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.state.borrow().capacity()
}
#[must_use]
pub fn queue_len(&self) -> usize {
self.state.borrow().live_waiters()
}
}
pub struct ResourceRequest {
state: Rc<RefCell<WaitQueue<()>>>,
registered: bool,
consumed: bool,
canceled: Rc<Cell<bool>>,
granted: Rc<Cell<bool>>,
}
impl std::fmt::Debug for ResourceRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResourceRequest")
.field("registered", &self.registered)
.field("granted", &self.granted.get())
.finish_non_exhaustive()
}
}
impl Future for ResourceRequest {
type Output = ResourceGuard;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<ResourceGuard> {
if self.granted.get() {
self.consumed = true;
return Poll::Ready(ResourceGuard {
state: Rc::clone(&self.state),
});
}
let acquired = {
let mut state = self.state.borrow_mut();
if state.try_acquire() {
true
} else {
if !self.registered {
state.register(
(),
cx.waker().clone(),
Rc::clone(&self.canceled),
Rc::clone(&self.granted),
);
}
false
}
};
if acquired {
self.consumed = true;
return Poll::Ready(ResourceGuard {
state: Rc::clone(&self.state),
});
}
self.registered = true;
Poll::Pending
}
}
impl Drop for ResourceRequest {
fn drop(&mut self) {
if self.consumed {
return; }
if self.granted.get() {
self.state.borrow_mut().release();
} else if self.registered {
self.canceled.set(true);
}
}
}
pub struct ResourceGuard {
state: Rc<RefCell<WaitQueue<()>>>,
}
impl std::fmt::Debug for ResourceGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResourceGuard").finish_non_exhaustive()
}
}
impl Drop for ResourceGuard {
fn drop(&mut self) {
self.state.borrow_mut().release();
}
}