1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//!Semaphore primitive

#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
mod posix;
#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
pub use posix::Sem;

#[cfg(windows)]
mod win32;
#[cfg(windows)]
pub use win32::Sem;

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod mac;
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub use mac::Sem;

///Describes Semaphore interface
///
///This primitive provides access to single integer that can be decremented using signal
///and incremented using wait
pub trait Semaphore: Sized {
    ///Creates new instance, returning None on inability to do so.
    ///
    ///`init` is initial value for the semaphore
    fn new(init: u32) -> Option<Self>;

    ///Decrements self, returning immediately if it was signaled.
    ///
    ///Otherwise awaits for `signal`
    fn wait(&self);

    ///Attempts to decrement self, returning whether self was signaled or not.
    ///
    ///Returns `true` if self was signaled
    ///
    ///Returns `false` otherwise
    fn try_wait(&self) -> bool;

    ///Attempts to decrement self within provided time, returning whether self was signaled or not.
    ///
    ///Returns `true` if self was signaled within specified `timeout`
    ///
    ///Returns `false` otherwise
    fn wait_timeout(&self, timeout: core::time::Duration) -> bool;

    ///Increments self, returning whether another thread has been woken as result.
    fn post(&self) -> bool;

    ///Increments self, waking any awaiting thread as result
    fn signal(&self);

    ///Gets semaphore's guard, which signal on drop.
    ///
    ///Before guard is created, function will await for semaphore to get decremented.
    fn lock(&self) -> SemaphoreGuard<'_, Self> {
        self.wait();
        SemaphoreGuard {
            sem: self
        }
    }

    ///Attempts to acquire semaphore's guard, which signal on drop.
    ///
    ///If semaphore cannot be decremented at the current moment, returns `None`
    fn try_lock(&self) -> Option<SemaphoreGuard<'_, Self>> {
        match self.try_wait() {
            true => Some(SemaphoreGuard {
                sem: self,
            }),
            false => None,
        }
    }
}

///[Semaphore](trait.Semaphore.html) guard
///
///Increments(signal) semaphore on drop.
pub struct SemaphoreGuard<'a, T: Semaphore> {
    sem: &'a T,
}

impl<T: Semaphore> Drop for SemaphoreGuard<'_, T> {
    fn drop(&mut self) {
        self.sem.signal();
    }
}