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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// Copyright 2018–2021 yvt, all rights reserved.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
use core::marker::PhantomData;

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
mod stdimp;
#[cfg(feature = "std")]
pub use self::stdimp::*;

#[cfg(feature = "atomic")]
#[cfg_attr(docsrs, doc(cfg(feature = "atomic")))]
mod panicking;
#[cfg(feature = "atomic")]
pub use self::panicking::*;

mod local;
pub use self::local::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SendMarker(());

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NoSendMarker(PhantomData<*mut ()>);

/// A trait for readers-writer locks.
pub unsafe trait Lock {
    fn new() -> Self;

    /// The `Send`-ness of this type indicates whether a lock can only be
    /// acquired by the same thread as `self`'s creator.
    type LockMarker;
    /// The `Send`-ness of this type indicates whether a lock can only be
    /// released by the same thread as the one that acquired it.
    type UnlockMarker;

    /// Acquire a shared lock, blocking the current thread until the lock
    /// is acquired.
    ///
    /// # Safety
    ///
    /// If [`Self::LockMarker`] is `!`[`Send`], the current thread must be the
    /// same one as `self`'s creator.
    unsafe fn lock_shared(&self);

    /// Acquire a shared lock.
    ///
    /// # Safety
    ///
    /// If [`Self::LockMarker`] is `!`[`Send`], the current thread must be the
    /// same one as `self`'s creator.
    unsafe fn try_lock_shared(&self) -> bool;

    /// Release a shared lock.
    ///
    /// # Safety
    ///
    /// There must be a shared lock to release.
    ///
    /// If [`Self::UnlockMarker`] is `!`[`Send`], the current thread must own a
    /// shared lock on `self`.
    unsafe fn unlock_shared(&self);

    /// Acquire an exclusive lock, blocking the current thread until the lock
    /// is acquired.
    ///
    /// # Safety
    ///
    /// If [`Self::LockMarker`] is `!`[`Send`], the current thread must be the
    /// same one as `self`'s creator.
    unsafe fn lock_exclusive(&self);

    /// Acquire an exclusive lock.
    ///
    /// # Safety
    ///
    /// If [`Self::LockMarker`] is `!`[`Send`], the current thread must be the
    /// same one as `self`'s creator.
    unsafe fn try_lock_exclusive(&self) -> bool;

    /// Release an exclusive lock.
    ///
    /// # Safety
    ///
    /// There must be an exclusive lock to release.
    ///
    /// If [`Self::UnlockMarker`] is `!`[`Send`], the current thread must own an
    /// exclusive lock on `self`.
    unsafe fn unlock_exclusive(&self);
}

#[cfg(feature = "lock_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "lock_api")))]
/// This crate's `LockTrait` is automatically implemented for types implementing
/// [`lock_api::RawRwLock`]
unsafe impl<T: lock_api::RawRwLock> Lock for T {
    type LockMarker = PhantomData<Self>;
    type UnlockMarker = T::GuardMarker;

    #[inline]
    fn new() -> Self {
        <Self as lock_api::RawRwLock>::INIT
    }

    #[inline]
    unsafe fn lock_shared(&self) {
        lock_api::RawRwLock::lock_shared(self)
    }

    #[inline]
    unsafe fn try_lock_shared(&self) -> bool {
        lock_api::RawRwLock::try_lock_shared(self)
    }

    #[inline]
    unsafe fn unlock_shared(&self) {
        lock_api::RawRwLock::unlock_shared(self)
    }

    #[inline]
    unsafe fn lock_exclusive(&self) {
        lock_api::RawRwLock::lock_exclusive(self)
    }

    #[inline]
    unsafe fn try_lock_exclusive(&self) -> bool {
        lock_api::RawRwLock::try_lock_exclusive(self)
    }

    #[inline]
    unsafe fn unlock_exclusive(&self) {
        lock_api::RawRwLock::unlock_exclusive(self)
    }
}