iceoryx2_bb_posix/
read_write_mutex.rs

1// Copyright (c) 2023 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! A POSIX inter-process capable [`ReadWriteMutex`] where either multiple readers can acquire
14//! multiple read-locks or one writer can acquire a write-lock.
15//! It is built by the [`ReadWriteMutexBuilder`].
16//!
17//! # Example
18//!
19//! ```ignore
20//! use iceoryx2_bb_posix::read_write_mutex::*;
21//! use std::thread;
22//! use std::time::Duration;
23//! use iceoryx2_bb_posix::clock::ClockType;
24//!
25//! let rw_handle = ReadWriteMutexHandle::new();
26//! let rw_mutex = ReadWriteMutexBuilder::new()
27//!                         .clock_type(ClockType::Monotonic)
28//!                         .is_interprocess_capable(true)
29//!                         .mutex_priority(ReadWriteMutexPriority::PreferReader)
30//!                         .create(123, &rw_handle)
31//!                         .expect("failed to create rw mutex");
32//!
33//! thread::scope(|s| {
34//!     s.spawn(|| {
35//!         match rw_mutex.read_timed_lock(Duration::from_millis(100))
36//!                       .expect("failed to read_lock") {
37//!             None => println!("Timeout while acquiring read lock."),
38//!             Some(guard) => println!("The mutex value is: {}", *guard),
39//!
40//!         }
41//!     });
42//!
43//!     s.spawn(|| {
44//!         match rw_mutex.write_timed_lock(Duration::from_millis(100))
45//!                       .expect("failed to write_lock") {
46//!             None => println!("Timeout while acquiring write lock."),
47//!             Some(mut guard) => {
48//!                 println!("The old value is: {}", *guard);
49//!                 *guard = 456;
50//!                 println!("The new value is: {}", *guard);
51//!             }
52//!         }
53//!     });
54//! });
55//! ```
56pub use crate::ipc_capable::{Handle, IpcCapable};
57
58use crate::ipc_capable::internal::{Capability, HandleStorage, IpcConstructible};
59use crate::{clock::AsTimespec, handle_errno};
60use iceoryx2_bb_elementary::{enum_gen, scope_guard::ScopeGuardBuilder};
61use iceoryx2_bb_log::{fail, fatal_panic, warn};
62use iceoryx2_pal_posix::posix::errno::Errno;
63use iceoryx2_pal_posix::posix::Struct;
64use iceoryx2_pal_posix::*;
65use std::{
66    cell::UnsafeCell,
67    fmt::Debug,
68    ops::{Deref, DerefMut},
69    time::Duration,
70};
71
72use crate::{
73    adaptive_wait::*,
74    clock::{ClockType, Time, TimeError},
75};
76
77#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
78pub enum ReadWriteMutexCreationError {
79    InsufficientMemory,
80    InsufficientResources,
81    InsufficientPermissions,
82    NoInterProcessSupport,
83    NoMutexKindSupport,
84    UnknownError(i32),
85}
86
87#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
88pub enum ReadWriteMutexReadLockError {
89    MaximumAmountOfReadLocksAcquired,
90    DeadlockConditionDetected,
91    UnknownError(i32),
92}
93
94#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
95pub enum ReadWriteMutexUnlockError {
96    OwnedByDifferentEntity,
97    UnknownError(i32),
98}
99
100#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
101pub enum ReadWriteMutexWriteLockError {
102    DeadlockConditionDetected,
103    UnknownError(i32),
104}
105
106#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
107pub enum ReadWriteMutexOpenIpcHandleError {
108    IsNotInterProcessCapable,
109    Uninitialized,
110}
111
112enum_gen! {
113    ReadWriteMutexReadTimedLockError
114  entry:
115    TimeoutExceedsMaximumSupportedDuration
116  mapping:
117    ReadWriteMutexReadLockError,
118    AdaptiveWaitError,
119    TimeError
120}
121
122enum_gen! {
123    ReadWriteMutexWriteTimedLockError
124  entry:
125    TimeoutExceedsMaximumSupportedDuration
126  mapping:
127    ReadWriteMutexWriteLockError,
128    AdaptiveWaitError,
129    TimeError
130}
131
132enum_gen! {
133    /// The ReadWriteMutexError enum is a generalization when one doesn't require the fine-grained error
134    /// handling enums. One can forward ReadWriteMutexError as more generic return value when a method
135    /// returns a ReadWriteMutex***Error.
136    /// On a higher level it is again convertable to [`crate::Error`].
137    ReadWriteMutexError
138  generalization:
139    FailedToLock <= ReadWriteMutexWriteTimedLockError; ReadWriteMutexReadTimedLockError; ReadWriteMutexWriteLockError; ReadWriteMutexReadLockError,
140    FailedToCreate <= ReadWriteMutexCreationError
141}
142
143/// Defines if the reader or the writer should prioritized in the [`ReadWriteMutex`].
144#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
145#[repr(i32)]
146pub enum ReadWriteMutexPriority {
147    PreferReader = posix::PTHREAD_PREFER_READER_NP,
148    PreferWriter = posix::PTHREAD_PREFER_WRITER_NP,
149    PreferWriterNonRecursive = posix::PTHREAD_PREFER_WRITER_NONRECURSIVE_NP,
150}
151
152/// The builder for the [`ReadWriteMutex`].
153#[derive(Debug)]
154pub struct ReadWriteMutexBuilder {
155    clock_type: ClockType,
156    mutex_priority: ReadWriteMutexPriority,
157    is_interprocess_capable: bool,
158}
159
160impl Default for ReadWriteMutexBuilder {
161    fn default() -> Self {
162        ReadWriteMutexBuilder {
163            clock_type: ClockType::default(),
164            mutex_priority: ReadWriteMutexPriority::PreferReader,
165            is_interprocess_capable: true,
166        }
167    }
168}
169
170impl ReadWriteMutexBuilder {
171    pub fn new() -> Self {
172        Self::default()
173    }
174
175    /// Sets the type of clock which will be used in [`ReadWriteMutex::read_timed_lock()`]
176    /// and [`ReadWriteMutex::write_timed_lock()`].
177    pub fn clock_type(mut self, value: ClockType) -> Self {
178        self.clock_type = value;
179        self
180    }
181
182    /// Defines if the [`ReadWriteMutex`] is inter-process capable or not.
183    pub fn is_interprocess_capable(mut self, value: bool) -> Self {
184        self.is_interprocess_capable = value;
185        self
186    }
187
188    /// Defines if the reader or the writer should be prioritized.
189    pub fn mutex_priority(mut self, value: ReadWriteMutexPriority) -> Self {
190        self.mutex_priority = value;
191        self
192    }
193
194    fn initialize_rw_mutex(
195        &self,
196        mtx: *mut posix::pthread_rwlock_t,
197    ) -> Result<Capability, ReadWriteMutexCreationError> {
198        let msg = "Failed to create mutex";
199        let origin = format!("{:?}", self);
200
201        let mut attributes = ScopeGuardBuilder::new(posix::pthread_rwlockattr_t::new()).on_init(|attr| {
202            handle_errno!(ReadWriteMutexCreationError, from self,
203                errno_source unsafe { posix::pthread_rwlockattr_init( attr).into() },
204                success Errno::ESUCCES => (),
205                Errno::ENOMEM => (InsufficientMemory, "{} due to insufficient memory while creating rwlock attributes.", msg),
206                v => (UnknownError(v as i32), "{} since an unknown error occurred while creating rwlock attributes.", msg)
207            );
208        }).on_drop(|attr| {
209            match unsafe {posix::pthread_rwlockattr_destroy(attr) } {
210                0 => (),
211                v => {
212                    fatal_panic!(from origin, "This should never happen! Failed to release rwlock attributes ({}).", v);
213                }
214            }
215        }).create()?;
216
217        match unsafe { posix::pthread_rwlockattr_setpshared(attributes.get_mut(), 0) } {
218            0 => (),
219            v => {
220                fail!(from origin, with ReadWriteMutexCreationError::NoInterProcessSupport,
221                        "{} due to an unknown error while setting interprocess capabilities ({}).", msg,v );
222            }
223        }
224
225        match unsafe {
226            posix::pthread_rwlockattr_setkind_np(attributes.get_mut(), self.mutex_priority as i32)
227        } {
228            0 => (),
229            v => {
230                fail!(from origin, with ReadWriteMutexCreationError::NoMutexKindSupport,
231                    "{} due to an unknown error while setting the mutex kind ({}).", msg, v);
232            }
233        }
234
235        match unsafe { posix::pthread_rwlock_init(mtx, attributes.get()).into() } {
236            Errno::ESUCCES => (),
237            Errno::EAGAIN => {
238                fail!(from origin, with ReadWriteMutexCreationError::InsufficientResources, "{} due to insufficient resources.", msg);
239            }
240            Errno::ENOMEM => {
241                fail!(from origin, with ReadWriteMutexCreationError::InsufficientResources, "{} due to insufficient memory.", msg);
242            }
243            Errno::EPERM => {
244                fail!(from origin, with ReadWriteMutexCreationError::InsufficientPermissions, "{} due to insufficient permissions.", msg);
245            }
246            v => {
247                fail!(from origin, with ReadWriteMutexCreationError::UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v);
248            }
249        };
250
251        match self.is_interprocess_capable {
252            true => Ok(Capability::InterProcess),
253            false => Ok(Capability::ProcessLocal),
254        }
255    }
256
257    /// Creates a new [`ReadWriteMutex`]
258    pub fn create<T: Debug>(
259        self,
260        t: T,
261        handle: &ReadWriteMutexHandle<T>,
262    ) -> Result<ReadWriteMutex<'_, T>, ReadWriteMutexCreationError> {
263        unsafe {
264            handle
265                .handle
266                .initialize(|mtx| self.initialize_rw_mutex(mtx))?
267        };
268
269        unsafe { *handle.clock_type.get() = self.clock_type };
270        unsafe { *handle.value.get() = Some(t) };
271
272        Ok(ReadWriteMutex::new(handle))
273    }
274}
275
276/// A guard which provides read access to the underlying value of a [`ReadWriteMutex`].
277///
278/// Is returned by [`ReadWriteMutex::read_lock()`], [`ReadWriteMutex::read_try_lock()`] and
279/// [`ReadWriteMutex::read_timed_lock()`].
280#[derive(Debug)]
281pub struct MutexReadGuard<'a, 'b, T: Debug> {
282    mutex: &'a ReadWriteMutex<'b, T>,
283}
284
285unsafe impl<T: Send + Debug> Send for MutexReadGuard<'_, '_, T> {}
286unsafe impl<T: Send + Sync + Debug> Sync for MutexReadGuard<'_, '_, T> {}
287
288impl<T: Debug> Deref for MutexReadGuard<'_, '_, T> {
289    type Target = T;
290
291    fn deref(&self) -> &Self::Target {
292        unsafe { (*self.mutex.handle.value.get()).as_ref().unwrap() }
293    }
294}
295
296impl<T: Debug> Drop for MutexReadGuard<'_, '_, T> {
297    fn drop(&mut self) {
298        if self.mutex.release().is_err() {
299            fatal_panic!(from self.mutex, "This should never happen! Failed to release read lock.");
300        }
301    }
302}
303
304/// A guard which provides read and write access to the underlying value of a [`ReadWriteMutex`].
305///
306/// Is returned by [`ReadWriteMutex::write_lock()`], [`ReadWriteMutex::write_try_lock()`] and
307/// [`ReadWriteMutex::write_timed_lock()`].
308#[derive(Debug)]
309pub struct MutexWriteGuard<'a, 'b, T: Debug> {
310    mutex: &'a ReadWriteMutex<'b, T>,
311}
312
313unsafe impl<T: Send + Debug> Send for MutexWriteGuard<'_, '_, T> {}
314unsafe impl<T: Send + Sync + Debug> Sync for MutexWriteGuard<'_, '_, T> {}
315
316impl<T: Debug> Deref for MutexWriteGuard<'_, '_, T> {
317    type Target = T;
318
319    fn deref(&self) -> &Self::Target {
320        unsafe { (*self.mutex.handle.value.get()).as_ref().unwrap() }
321    }
322}
323
324impl<T: Debug> DerefMut for MutexWriteGuard<'_, '_, T> {
325    fn deref_mut(&mut self) -> &mut Self::Target {
326        unsafe { (*self.mutex.handle.value.get()).as_mut().unwrap() }
327    }
328}
329
330impl<T: Debug> Drop for MutexWriteGuard<'_, '_, T> {
331    fn drop(&mut self) {
332        if self.mutex.release().is_err() {
333            fatal_panic!(from self.mutex, "This should never happen! Failed to release write lock.");
334        }
335    }
336}
337
338/// The underlying memory of a [`ReadWriteMutex`] is not allowed to be moved. This issue is solved
339/// by storing the underlying posix handle inside [`ReadWriteMutexHandle`]. When a [`ReadWriteMutex`]
340/// is initialized it stores a const reference to the [`ReadWriteMutexHandle`] and makes it by
341/// that inmovable.
342#[derive(Debug)]
343pub struct ReadWriteMutexHandle<T: Sized + Debug> {
344    handle: HandleStorage<posix::pthread_rwlock_t>,
345    clock_type: UnsafeCell<ClockType>,
346    value: UnsafeCell<Option<T>>,
347}
348
349unsafe impl<T: Sized + Debug> Send for ReadWriteMutexHandle<T> {}
350unsafe impl<T: Sized + Debug> Sync for ReadWriteMutexHandle<T> {}
351
352impl<T: Sized + Debug> Handle for ReadWriteMutexHandle<T> {
353    fn new() -> Self {
354        Self {
355            handle: HandleStorage::new(posix::pthread_rwlock_t::new()),
356            clock_type: UnsafeCell::new(ClockType::default()),
357            value: UnsafeCell::new(None),
358        }
359    }
360
361    fn is_initialized(&self) -> bool {
362        self.handle.is_initialized()
363    }
364
365    fn is_inter_process_capable(&self) -> bool {
366        self.handle.is_inter_process_capable()
367    }
368}
369
370impl<T: Sized + Debug> Drop for ReadWriteMutexHandle<T> {
371    fn drop(&mut self) {
372        if self.handle.is_initialized() {
373            unsafe {
374                self.handle.cleanup(|mtx|{
375                    if posix::pthread_rwlock_destroy(mtx) != 0 {
376                        warn!(from self,
377                            "Unable to destroy read write mutex. Was it already destroyed by another instance in another process?");
378                    }
379                });
380            }
381        }
382    }
383}
384
385/// A POSIX read write mutex where either multiple readers can acquire multiple read-locks or one
386/// writer can acquire a write-lock.
387/// It is built by the [`ReadWriteMutexBuilder`].
388#[derive(Debug)]
389pub struct ReadWriteMutex<'a, T: Sized + Debug> {
390    handle: &'a ReadWriteMutexHandle<T>,
391}
392
393unsafe impl<T: Send + Debug> Send for ReadWriteMutex<'_, T> {}
394unsafe impl<T: Sync + Debug> Sync for ReadWriteMutex<'_, T> {}
395
396impl<'a, T: Sized + Debug> IpcConstructible<'a, ReadWriteMutexHandle<T>> for ReadWriteMutex<'a, T> {
397    fn new(handle: &'a ReadWriteMutexHandle<T>) -> Self {
398        Self { handle }
399    }
400}
401
402impl<'a, T: Sized + Debug> IpcCapable<'a, ReadWriteMutexHandle<T>> for ReadWriteMutex<'a, T> {
403    fn is_interprocess_capable(&self) -> bool {
404        self.handle.is_inter_process_capable()
405    }
406}
407
408impl<'a, T: Sized + Debug> ReadWriteMutex<'a, T> {
409    fn new(handle: &'a ReadWriteMutexHandle<T>) -> Self {
410        Self { handle }
411    }
412
413    /// Returns the used clock type of the mutex
414    pub fn clock_type(&self) -> ClockType {
415        unsafe { *self.handle.clock_type.get() }
416    }
417
418    /// Blocks until a read-lock could be acquired and returns a [`MutexReadGuard`] to provide
419    /// read access to the underlying value.
420    pub fn read_lock(&self) -> Result<MutexReadGuard<'_, '_, T>, ReadWriteMutexReadLockError> {
421        let msg = "Failed to acquire read-lock";
422        handle_errno!(ReadWriteMutexReadLockError, from self,
423            errno_source unsafe { posix::pthread_rwlock_rdlock(self.handle.handle.get()).into() },
424            success Errno::ESUCCES => MutexReadGuard { mutex: self },
425            Errno::EAGAIN => (MaximumAmountOfReadLocksAcquired, "{} since the maximum amount of read-locks is already acquired.", msg),
426            Errno::EDEADLK => (DeadlockConditionDetected, "{} since a deadlock condition was detected.", msg),
427            v => (UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v)
428        );
429    }
430
431    /// Tries to acquire a read-lock. If a write-locks was already acquired it returns [`None`]
432    /// otherwise a [`MutexReadGuard`].
433    pub fn read_try_lock(
434        &self,
435    ) -> Result<Option<MutexReadGuard<'_, '_, T>>, ReadWriteMutexReadLockError> {
436        let msg = "Failed to try to acquire read-lock";
437        handle_errno!(ReadWriteMutexReadLockError, from self,
438            errno_source unsafe { posix::pthread_rwlock_tryrdlock(self.handle.handle.get()).into() },
439            success Errno::ESUCCES => Some(MutexReadGuard { mutex: self });
440            success Errno::EBUSY => None;
441            success Errno::EDEADLK => None,
442            Errno::EAGAIN => (MaximumAmountOfReadLocksAcquired, "{} since the maximum amount of read-locks is already acquired.", msg),
443            v => (UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v)
444        );
445    }
446
447    /// Tries to acquire a read-lock until the timeout has passed. If a read-lock could be
448    /// acquired it returns a [`MutexReadGuard`], if the timeout has passed it returns [`None`].
449    pub fn read_timed_lock(
450        &self,
451        timeout: Duration,
452    ) -> Result<Option<MutexReadGuard<'_, '_, T>>, ReadWriteMutexReadTimedLockError> {
453        let msg = "Failted to timed wait for read lock";
454
455        match self.clock_type() {
456            ClockType::Realtime => {
457                let now = fail!(from self, when Time::now_with_clock(ClockType::Realtime),
458                    "{} due to a failure while acquiring current system time.", msg);
459                let timeout_adjusted = now.as_duration() + timeout;
460                handle_errno!(ReadWriteMutexReadTimedLockError, from self,
461                    errno_source unsafe { posix::pthread_rwlock_timedrdlock(self.handle.handle.get(), &timeout_adjusted.as_timespec()) }.into(),
462                    success Errno::ESUCCES => Some(MutexReadGuard { mutex: self });
463                    success Errno::ETIMEDOUT => None;
464                    success Errno::EDEADLK => None,
465                    Errno::EAGAIN => (ReadWriteMutexReadLockError(ReadWriteMutexReadLockError::MaximumAmountOfReadLocksAcquired), "{} since the maximum number of read locks were already acquired.", msg),
466                    Errno::EINVAL => (TimeoutExceedsMaximumSupportedDuration, "{} since the timeout of {:?} exceeds the maximum supported duration.", msg, timeout),
467                    v => (ReadWriteMutexReadLockError(ReadWriteMutexReadLockError::UnknownError(v as i32)), "{} since unknown error occurred while acquiring the lock ({})", msg, v)
468                )
469            }
470            ClockType::Monotonic => {
471                let time = fail!(from self, when  Time::now_with_clock(self.clock_type()),
472                        "{} due to a failure while acquiring current system time in.", msg);
473                let mut adaptive_wait = fail!(from self, when AdaptiveWaitBuilder::new()
474                    .clock_type(self.clock_type())
475                    .create(), "{} since the adaptive wait could not be created.", msg);
476
477                loop {
478                    match self.read_try_lock() {
479                        Ok(Some(v)) => return Ok(Some(v)),
480                        Ok(None) => match fail!(from self, when time.elapsed(),
481                             "{} due to a failure while acquiring elapsed system time.", msg)
482                            < timeout
483                        {
484                            true => {
485                                fail!(from self, when adaptive_wait.wait(), "{} since AdaptiveWait failed.", msg);
486                            }
487                            false => return Ok(None),
488                        },
489                        Err(v) => {
490                            fail!(from self, with ReadWriteMutexReadTimedLockError::ReadWriteMutexReadLockError(v),
491                        "{} since read_try_lock failed.", msg);
492                        }
493                    }
494                }
495            }
496        }
497    }
498
499    /// Blocks until a write-lock could be acquired and returns a [`MutexWriteGuard`] to provide
500    /// read-write access to the underlying value.
501    pub fn write_lock(&self) -> Result<MutexWriteGuard<'_, '_, T>, ReadWriteMutexWriteLockError> {
502        let msg = "Failed to acquire write-lock";
503        handle_errno!(ReadWriteMutexWriteLockError, from self,
504            errno_source unsafe { posix::pthread_rwlock_wrlock(self.handle.handle.get()).into() },
505            success Errno::ESUCCES => MutexWriteGuard { mutex: self },
506            Errno::EDEADLK => (DeadlockConditionDetected, "{} since a deadlock condition was detected.", msg),
507            v => (UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v)
508        );
509    }
510
511    /// Tries to acquire a read-lock. If a read-locks was already acquired it returns [`None`]
512    /// otherwise a [`MutexWriteGuard`].
513    pub fn write_try_lock(
514        &self,
515    ) -> Result<Option<MutexWriteGuard<'_, '_, T>>, ReadWriteMutexWriteLockError> {
516        let msg = "Failed to try to acquire write-lock";
517        handle_errno!(ReadWriteMutexWriteLockError, from self,
518            errno_source unsafe { posix::pthread_rwlock_trywrlock(self.handle.handle.get()).into() },
519            success Errno::ESUCCES => Some(MutexWriteGuard { mutex: self });
520            success Errno::EBUSY => None;
521            success Errno::EDEADLK => None,
522            v => (UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v)
523        );
524    }
525
526    /// Tries to acquire a write-lock until the timeout has passed. If a write-lock could be
527    /// acquired it returns a [`MutexWriteGuard`], if the timeout has passed it returns [`None`].
528    pub fn write_timed_lock(
529        &self,
530        timeout: Duration,
531    ) -> Result<Option<MutexWriteGuard<'_, '_, T>>, ReadWriteMutexWriteTimedLockError> {
532        let msg = "Failed to timed wait for write lock";
533
534        match self.clock_type() {
535            ClockType::Realtime => {
536                let now = fail!(from self, when Time::now_with_clock(ClockType::Realtime),
537                    "{} due to a failure while acquiring current system time.", msg);
538                let timeout_adjusted = now.as_duration() + timeout;
539                handle_errno!(ReadWriteMutexWriteTimedLockError, from self,
540                    errno_source unsafe { posix::pthread_rwlock_timedwrlock(self.handle.handle.get(), &timeout_adjusted.as_timespec()) }.into(),
541                    success Errno::ESUCCES => Some(MutexWriteGuard { mutex: self });
542                    success Errno::ETIMEDOUT => None;
543                    success Errno::EDEADLK => None,
544                    Errno::EINVAL => (TimeoutExceedsMaximumSupportedDuration, "{} since the timeout of {:?} exceeds the maximum supported duration.", msg, timeout),
545                    v => (ReadWriteMutexWriteLockError(ReadWriteMutexWriteLockError::UnknownError(v as i32)), "{} since unknown error occurred while acquiring the lock ({})", msg, v)
546                )
547            }
548            ClockType::Monotonic => {
549                let time = fail!(from self, when Time::now_with_clock(self.clock_type()),
550                        "{} due to a failure while acquiring current system time.", msg);
551                let mut adaptive_wait = fail!(from self, when AdaptiveWaitBuilder::new()
552            .clock_type(self.clock_type())
553            .create(), "{} since the adaptive wait could not be created.", msg);
554
555                loop {
556                    match self.write_try_lock() {
557                        Ok(Some(v)) => return Ok(Some(v)),
558                        Ok(None) => match fail!(from self, when time.elapsed(),
559                                "{} due to a failure while acquiring elapsed system time.", msg)
560                            < timeout
561                        {
562                            true => {
563                                fail!(from self, when adaptive_wait.wait(), "{} since AdaptiveWait failed.", msg);
564                            }
565                            false => return Ok(None),
566                        },
567                        Err(v) => {
568                            fail!(from self, with ReadWriteMutexWriteTimedLockError::ReadWriteMutexWriteLockError(v),
569                                "{} since write_try_lock failed.", msg);
570                        }
571                    }
572                }
573            }
574        }
575    }
576
577    fn release(&self) -> Result<(), ReadWriteMutexUnlockError> {
578        let msg = "Unable to release lock";
579        match unsafe { posix::pthread_rwlock_unlock(self.handle.handle.get()).into() } {
580            Errno::ESUCCES => Ok(()),
581            Errno::EPERM => {
582                fail!(from self, with ReadWriteMutexUnlockError::OwnedByDifferentEntity,
583                    "{} since it is not owned by the current thread.", msg);
584            }
585            v => {
586                fail!(from self, with ReadWriteMutexUnlockError::UnknownError(v as i32),
587                    "{} since an unknown error occurred ({}).", msg, v);
588            }
589        }
590    }
591}