pub struct ReadWriteLock<'a, T: Persistable + 'a>
{
objectPool: *mut PMEMobjpool,
readWriteLock: *mut PMEMrwlock,
object: &'a mut T
}
impl<'a, T: Persistable> ReadWriteLock<'a, T>
{
#[inline(always)]
fn new(objectPool: *mut PMEMobjpool, readWriteLock: *mut PMEMrwlock, object: &'a mut T) -> Self
{
debug_assert!(!objectPool.is_null(), "objectPool is null");
debug_assert!(!readWriteLock.is_null(), "readWriteLock is null");
Self
{
objectPool: objectPool,
readWriteLock: readWriteLock,
object: object,
}
}
#[inline(always)]
pub fn readLock(self) -> ReadLockUnlock<'a, T>
{
let result = unsafe { pmemobj_rwlock_rdlock(self.objectPool, self.readWriteLock) };
if likely(result == 0)
{
return ReadLockUnlock(self);
}
match result
{
E::EDEADLK => panic!("Deadlock"),
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[inline(always)]
pub fn tryReadLock(self) -> Option<ReadLockUnlock<'a, T>>
{
let result = unsafe { pmemobj_rwlock_tryrdlock(self.objectPool, self.readWriteLock) };
if likely(result == 0)
{
return Some(ReadLockUnlock(self));
}
match result
{
E::EBUSY => None,
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[inline(always)]
pub fn timedReadLock(self, absoluteTimeOut: ×pec) -> Option<ReadLockUnlock<'a, T>>
{
let result = unsafe { pmemobj_rwlock_timedwrlock(self.objectPool, self.readWriteLock, absoluteTimeOut) };
if likely(result == 0)
{
return Some(ReadLockUnlock(self));
}
match result
{
E::ETIMEDOUT => None,
E::EDEADLK => panic!("Deadlock"),
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid or absoluteTimeOut is out-of-range (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[allow(unused_variables)]
#[inline(always)]
pub fn writeLockInTransaction(self, transaction: Transaction)
{
let result = unsafe { pmemobj_tx_lock(pobj_tx_param::TX_PARAM_RWLOCK, self.readWriteLock as *mut c_void) };
if likely(result == 0)
{
return;
}
Self::writeLockErrorHandling(result);
}
#[inline(always)]
pub fn writeLock(self) -> WriteLockUnlock<'a, T>
{
let result = unsafe { pmemobj_rwlock_wrlock(self.objectPool, self.readWriteLock) };
if likely(result == 0)
{
return WriteLockUnlock(self);
}
Self::writeLockErrorHandling(result)
}
#[inline(always)]
fn writeLockErrorHandling(result: c_int) -> WriteLockUnlock<'a, T>
{
match result
{
E::EDEADLK => panic!("Deadlock"),
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[inline(always)]
pub fn tryWriteLock(self) -> Option<WriteLockUnlock<'a, T>>
{
let result = unsafe { pmemobj_rwlock_trywrlock(self.objectPool, self.readWriteLock) };
if likely(result == 0)
{
return Some(WriteLockUnlock(self));
}
match result
{
E::EBUSY => None,
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[inline(always)]
pub fn timedWriteLock(self, absoluteTimeOut: ×pec) -> Option<WriteLockUnlock<'a, T>>
{
let result = unsafe { pmemobj_rwlock_timedwrlock(self.objectPool, self.readWriteLock, absoluteTimeOut) };
if likely(result == 0)
{
return Some(WriteLockUnlock(self));
}
match result
{
E::ETIMEDOUT => None,
E::EDEADLK => panic!("Deadlock"),
E::EAGAIN => panic!("EAGAIN; too many locks of the same lock in this thread"),
E::EINVAL => panic!("objectPool or readWriteLock was null or readWriteLock was invalid or absoluteTimeOut is out-of-range (none of these things should occur)"),
_ => panic!("Unexpected error '{}'", result),
}
}
#[inline(always)]
fn unlock(&self)
{
let result = unsafe { pmemobj_rwlock_unlock(self.objectPool, self.readWriteLock) };
if likely(result == 0)
{
return;
}
match result
{
E::EINVAL => panic!("objectPool or mutex was null or mutex was invalid (none of these things should occur)"),
E::EPERM => panic!("Current thread does not hold this mutex lock"),
E::EAGAIN => panic!("EAGAIN is no longer part of POSIX for pthread_mutex_unlock"),
_ => panic!("Unexpected error '{}'", result),
}
}
}