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
use crate::values::{Values, ValuesIter};
use std::mem;
use std::sync;
use std::sync::atomic;

/// A guard wrapping a live reference into an evmap.
///
/// As long as this guard lives, the map being read cannot change, and if a writer attempts to
/// call [`WriteHandle::refresh`], that call will block until this guard is dropped.
#[derive(Debug)]
pub struct ReadGuard<'rh, T: ?Sized> {
    // NOTE: _technically_ this is more like &'self.
    // the reference is valid until the guard is dropped.
    pub(super) t: &'rh T,
    pub(super) epoch: usize,
    pub(super) handle: &'rh sync::atomic::AtomicUsize,
}

impl<'rh, T: ?Sized> ReadGuard<'rh, T> {
    pub(super) fn map_ref<F, U: ?Sized>(self, f: F) -> ReadGuard<'rh, U>
    where
        F: for<'a> FnOnce(&'a T) -> &'a U,
    {
        let rg = ReadGuard {
            t: f(self.t),
            epoch: self.epoch,
            handle: self.handle,
        };
        mem::forget(self);
        rg
    }

    pub(super) fn map_opt<F, U: ?Sized>(self, f: F) -> Option<ReadGuard<'rh, U>>
    where
        F: for<'a> FnOnce(&'a T) -> Option<&'a U>,
    {
        let rg = Some(ReadGuard {
            t: f(self.t)?,
            epoch: self.epoch,
            handle: self.handle,
        });
        mem::forget(self);
        rg
    }
}

impl<'rh, T: ?Sized> AsRef<T> for ReadGuard<'rh, T> {
    fn as_ref(&self) -> &T {
        self.t
    }
}

impl<'rh, T: ?Sized> std::ops::Deref for ReadGuard<'rh, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        self.t
    }
}

impl<'rh, T: ?Sized> Drop for ReadGuard<'rh, T> {
    fn drop(&mut self) {
        self.handle.store(
            (self.epoch + 1) | 1usize << (mem::size_of::<usize>() * 8 - 1),
            atomic::Ordering::Release,
        );
    }
}

impl<'rh, T, S> IntoIterator for &'rh ReadGuard<'rh, Values<T, S>> {
    type Item = &'rh T;
    type IntoIter = ValuesIter<'rh, T, S>;

    fn into_iter(self) -> Self::IntoIter {
        self.t.into_iter()
    }
}