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
use std::{
    ops::{Deref, DerefMut},
    sync::Arc,
};

use crate::state::ObservableState;

pub trait Lock {
    type RwLock<T>;
    type RwLockReadGuard<'a, T>: Deref<Target = T>
    where
        T: 'a;
    type RwLockWriteGuard<'a, T>: DerefMut<Target = T>
    where
        T: 'a;
    type Shared<T>: Deref<Target = T>;
    type SharedReadGuard<'a, T>: Deref<Target = T>
    where
        T: 'a;
    type SubscriberState<S>;

    fn new_rwlock<T>(value: T) -> Self::RwLock<T>;
    fn read_noblock<T>(lock: &Self::RwLock<T>) -> Self::RwLockReadGuard<'_, T>;

    fn new_shared<T>(value: T) -> Self::Shared<T>;
    fn shared_read_count<T>(shared: &Self::Shared<T>) -> usize;
    fn shared_into_inner<T>(shared: Self::Shared<T>) -> Arc<Self::RwLock<T>>;
}

/// Marker type for using a synchronous lock for the inner value.
#[allow(missing_debug_implementations)]
pub enum SyncLock {}

impl Lock for SyncLock {
    type RwLock<T> = std::sync::RwLock<T>;
    type RwLockReadGuard<'a, T> = std::sync::RwLockReadGuard<'a, T>
    where
        T: 'a;
    type RwLockWriteGuard<'a, T> = std::sync::RwLockWriteGuard<'a, T>
    where
        T: 'a;
    type Shared<T> = readlock::Shared<T>;
    type SharedReadGuard<'a, T> = readlock::SharedReadGuard<'a, T>
    where
        T: 'a;
    type SubscriberState<T> = readlock::SharedReadLock<ObservableState<T>>;

    fn new_rwlock<T>(value: T) -> Self::RwLock<T> {
        Self::RwLock::new(value)
    }
    fn read_noblock<T>(lock: &Self::RwLock<T>) -> Self::RwLockReadGuard<'_, T> {
        lock.try_read().unwrap()
    }

    fn new_shared<T>(value: T) -> Self::Shared<T> {
        Self::Shared::new(value)
    }
    fn shared_read_count<T>(shared: &Self::Shared<T>) -> usize {
        Self::Shared::read_count(shared)
    }
    fn shared_into_inner<T>(shared: Self::Shared<T>) -> Arc<Self::RwLock<T>> {
        Self::Shared::into_inner(shared)
    }
}

/// Marker type for using an asynchronous lock for the inner value.
#[cfg(feature = "async-lock")]
#[allow(missing_debug_implementations)]
pub enum AsyncLock {}

#[cfg(feature = "async-lock")]
impl Lock for AsyncLock {
    type RwLock<T> = tokio::sync::RwLock<T>;
    type RwLockReadGuard<'a, T> = tokio::sync::RwLockReadGuard<'a, T>
    where
        T: 'a;
    type RwLockWriteGuard<'a, T> = tokio::sync::RwLockWriteGuard<'a, T>
    where
        T: 'a;
    type Shared<T> = readlock_tokio::Shared<T>;
    type SharedReadGuard<'a, T> = readlock_tokio::SharedReadGuard<'a, T>
    where
        T: 'a;
    type SubscriberState<T> =
        crate::subscriber::async_lock::AsyncSubscriberState<ObservableState<T>>;

    fn new_rwlock<T>(value: T) -> Self::RwLock<T> {
        Self::RwLock::new(value)
    }
    fn read_noblock<T>(lock: &Self::RwLock<T>) -> Self::RwLockReadGuard<'_, T> {
        lock.try_read().unwrap()
    }

    fn new_shared<T>(value: T) -> Self::Shared<T> {
        Self::Shared::new(value)
    }
    fn shared_read_count<T>(shared: &Self::Shared<T>) -> usize {
        Self::Shared::read_count(shared)
    }
    fn shared_into_inner<T>(shared: Self::Shared<T>) -> Arc<Self::RwLock<T>> {
        Self::Shared::into_inner(shared)
    }
}