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
//! A statically-allocated, concurrent data structure for storage of Rust objects that are utilized
//! through Mun Runtime C API calls.

use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;

use lazy_static::lazy_static;
use parking_lot::{RwLock, RwLockReadGuard};

use crate::error::ErrorHandle;
use crate::TypedHandle;

fn generate_handle<H: TypedHandle>() -> H {
    loop {
        let token = rand::random();
        if token != 0 {
            return H::new(token);
        }
    }
}

/// A concurrent registry for uniquely indexed values.
pub struct Registry<H, T> {
    data: RwLock<HashMap<H, T>>,
}

impl<H, T> Registry<H, T>
where
    H: Copy + Eq + Hash + TypedHandle,
{
    /// Inserts `value` and returns a unique handle to it.
    pub fn register(&self, value: T) -> H {
        let handle = {
            let data = self.data.read();

            let mut handle = generate_handle();
            while data.contains_key(&handle) {
                handle = generate_handle();
            }
            handle
        };

        self.data.write().insert(handle, value);
        handle
    }

    /// Removes and returns the value corresponding to `handle`, if it is found.
    pub fn unregister(&self, handle: H) -> Option<T> {
        self.data.write().remove(&handle)
    }

    /// Retrieves the inner data
    pub fn get_data(&self) -> RwLockReadGuard<HashMap<H, T>> {
        self.data.read()
    }
}

impl<H, T> Default for Registry<H, T>
where
    H: Eq + Hash + TypedHandle,
{
    fn default() -> Self {
        Registry {
            data: RwLock::new(HashMap::new()),
        }
    }
}

/// Concurrent data structure for storage of Rust objects that are utilized through Mun Runtime
/// C API calls.
#[derive(Default)]
pub struct Hub {
    /// Error registry
    pub errors: Arc<Registry<ErrorHandle, anyhow::Error>>,
}

lazy_static! {
    /// Storage for Rust objects that are utilized through Mun Runtime C API calls.
    pub static ref HUB: Hub = Hub::default();
}