pub(crate) mod internal;
use std::ops::{Deref, DerefMut, Drop};
use std::fmt;
use std::os::raw::c_void;
use context::Lock;
use self::internal::Pointer;
pub trait Borrow: Sized {
type Target: Pointer;
fn borrow<'a>(self, lock: &'a Lock<'a>) -> Ref<'a, Self::Target> {
match self.try_borrow(lock) {
Ok(r) => r,
Err(e) => panic!("{}", e)
}
}
fn try_borrow<'a>(self, lock: &'a Lock<'a>) -> Result<Ref<'a, Self::Target>, LoanError>;
}
pub trait BorrowMut: Borrow {
fn borrow_mut<'a>(self, lock: &'a Lock<'a>) -> RefMut<'a, Self::Target> {
match self.try_borrow_mut(lock) {
Ok(r) => r,
Err(e) => panic!("{}", e)
}
}
fn try_borrow_mut<'a>(self, lock: &'a Lock<'a>) -> Result<RefMut<'a, Self::Target>, LoanError>;
}
pub enum LoanError {
Mutating(*const c_void),
Frozen(*const c_void)
}
impl fmt::Display for LoanError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
LoanError::Mutating(p) => {
write!(f, "outstanding mutable loan exists for object at {:?}", p)
}
LoanError::Frozen(p) => {
write!(f, "object at {:?} is frozen", p)
}
}
}
}
pub struct Ref<'a, T: Pointer> {
pointer: T,
lock: &'a Lock<'a>
}
impl<'a, T: Pointer> Ref<'a, T> {
pub(crate) unsafe fn new(lock: &'a Lock<'a>, pointer: T) -> Result<Self, LoanError> {
let mut ledger = lock.ledger.borrow_mut();
ledger.try_borrow(pointer.as_ptr())?;
Ok(Ref { pointer, lock })
}
}
impl<'a, T: Pointer> Drop for Ref<'a, T> {
fn drop(&mut self) {
let mut ledger = self.lock.ledger.borrow_mut();
ledger.settle(unsafe { self.pointer.as_ptr() });
}
}
impl<'a, T: Pointer> Deref for Ref<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.pointer
}
}
pub struct RefMut<'a, T: Pointer> {
pointer: T,
lock: &'a Lock<'a>
}
impl<'a, T: Pointer> RefMut<'a, T> {
pub(crate) unsafe fn new(lock: &'a Lock<'a>, mut pointer: T) -> Result<Self, LoanError> {
let mut ledger = lock.ledger.borrow_mut();
ledger.try_borrow_mut(pointer.as_mut())?;
Ok(RefMut { pointer, lock })
}
}
impl<'a, T: Pointer> Drop for RefMut<'a, T> {
fn drop(&mut self) {
let mut ledger = self.lock.ledger.borrow_mut();
ledger.settle_mut(unsafe { self.pointer.as_mut() });
}
}
impl<'a, T: Pointer> Deref for RefMut<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.pointer
}
}
impl<'a, T: Pointer> DerefMut for RefMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.pointer
}
}