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
//! Wrapper for thread-safe Abscissa `Application` state access.

mod reader;
mod writer;

pub use self::{reader::Reader, writer::Writer};
use super::Application;
use std::sync::{PoisonError, RwLock};

/// `RwLock` for accessing `Application` state.
///
/// Supports multiple concurrent readers (immutable-only) with an exclusive
/// mutable writer.
pub struct Lock<A: Application>(RwLock<A>);

impl<A: Application> Lock<A> {
    /// Create a new lock around the given application
    pub fn new(app: A) -> Self {
        Self(RwLock::new(app))
    }

    /// Get the application state, acquiring a shared, read-only lock around
    /// it which permits concurrent access by multiple readers.
    ///
    /// If the application has not yet been initialized, calls `not_loaded()`.
    pub fn read(&'static self) -> Reader<A> {
        Reader::new(self.0.read().unwrap_or_else(|e| poisoned(e)))
    }

    /// Obtain an exclusive lock on the application state, allowing it to be
    /// accessed mutably.
    pub fn write(&'static self) -> Writer<A> {
        Writer::new(self.0.write().unwrap_or_else(|e| poisoned(e)))
    }
}

/// Error handler called if the `RwLock` protecting the application state
/// has been poisoned.
///
/// This indicates a bug in the program accessing this type.
fn poisoned<Guard>(e: PoisonError<Guard>) -> ! {
    panic!(
        "Abscissa application state corrupted by unhandled crash: {}",
        e
    )
}