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
//! The thread-unsafe (but faster) implementation.
use core::{ops::Range, pin::Pin};
use pin_cell::PinCell;

use crate::{
    core::{rbtree, IntervalRwLockCore},
    raw::{RawBlockingIntervalRwLock, RawIntervalRwLock},
};

/// Wraps `IntervalRwLockCore` (an internal trait) to provide a non-thread-safe
/// readers-writer lock optimized for interval locks with a raw interface.
#[pin_project::pin_project]
#[derive(Debug)]
pub struct LocalRawIntervalRwLock<Core> {
    #[pin]
    core: PinCell<Core>,
}

#[cold]
fn core_is_not_reentrant() -> ! {
    panic!("attempted to recursively call a method of `LocalRawIntervalRwLock`");
}

#[cold]
fn deadlocked() -> ! {
    panic!("deadlocked");
}

macro_rules! borrow_core {
    (let $p:pat = $self:ident.core) => {
        let Ok(mut core) = $self.project_ref().core.try_borrow_mut()
                			else { core_is_not_reentrant(); };
        let $p = pin_cell::PinMut::as_mut(&mut core);
    };
}

unsafe impl<Core: IntervalRwLockCore<InProgress = !>> RawIntervalRwLock
    for LocalRawIntervalRwLock<Core>
{
    type Index = Core::Index;

    type TryReadLockState = Core::TryReadLockState;

    type TryWriteLockState = Core::TryWriteLockState;

    const INIT: Self = Self {
        core: PinCell::new(Core::INIT),
    };

    fn try_lock_read(
        self: Pin<&Self>,
        range: Range<Self::Index>,
        state: Pin<&mut Self::TryReadLockState>,
    ) -> bool {
        borrow_core!(let core = self.core);
        core.try_lock_read(range, state)
    }

    fn try_lock_write(
        self: Pin<&Self>,
        range: Range<Self::Index>,
        state: Pin<&mut Self::TryWriteLockState>,
    ) -> bool {
        borrow_core!(let core = self.core);
        core.try_lock_write(range, state)
    }

    fn unlock_try_read(self: Pin<&Self>, state: Pin<&mut Self::TryReadLockState>) {
        borrow_core!(let core = self.core);
        core.unlock_try_read(state, ())
    }

    fn unlock_try_write(self: Pin<&Self>, state: Pin<&mut Self::TryWriteLockState>) {
        borrow_core!(let core = self.core);
        core.unlock_try_write(state, ())
    }
}

unsafe impl<Core: IntervalRwLockCore<InProgress = !>> RawBlockingIntervalRwLock
    for LocalRawIntervalRwLock<Core>
{
    type ReadLockState = Core::TryReadLockState;

    type WriteLockState = Core::TryWriteLockState;

    type Priority = ();

    fn lock_read(
        self: Pin<&Self>,
        range: Range<Self::Index>,
        _priority: Self::Priority,
        state: Pin<&mut Self::ReadLockState>,
    ) {
        if !self.try_lock_read(range, state) {
            deadlocked();
        }
    }

    fn lock_write(
        self: Pin<&Self>,
        range: Range<Self::Index>,
        _priority: Self::Priority,
        state: Pin<&mut Self::WriteLockState>,
    ) {
        if !self.try_lock_write(range, state) {
            deadlocked();
        }
    }

    fn unlock_read(self: Pin<&Self>, state: Pin<&mut Self::ReadLockState>) {
        self.unlock_try_read(state);
    }

    fn unlock_write(self: Pin<&Self>, state: Pin<&mut Self::WriteLockState>) {
        self.unlock_try_write(state);
    }
}

/// A raw interface to a non-thread-safe readers-writer lock optimized for
/// interval locks, implemented by a [red-black tree][1].
///
/// [1]: https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
pub type LocalRawRbTreeIntervalRwLock<Index> =
    LocalRawIntervalRwLock<rbtree::RbTreeIntervalRwLockCore<Index, !, !>>;