Files @ f450ae18ef58
Branch filter:

Location: CSY/reowolf/src/runtime2/global_store.rs - annotation

f450ae18ef58 3.8 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
merge with rewrite of connector/scheduler
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
1aef293674a6
use crate::collections::{MpmcQueue, RawVec};

use super::connector::Connector;

use std::ptr;
use std::sync::RwLock;

/// A kind of token that, once obtained, allows access to a container.
struct ConnectorKey {
    index: u32, // of connector
}

struct ConnectorStore {
    connectors: RawVec<*mut Connector>,
    free: Vec<usize>,
}

impl ConnectorStore {
    fn with_capacity(capacity: usize) -> Self {
        Self{
            connectors: RawVec::with_capacity(capacity),
            free: Vec::with_capacity(capacity),
        }
    }

    fn get_mut(&self, key: &ConnectorKey) -> &'static mut Connector {
        unsafe {
            let connector = self.connectors.get_mut(key.index as usize);
            debug_assert!(!connector.is_null());
            return *connector as &mut _;
        }
    }

    fn create(&mut self, connector: Connector) -> ConnectorKey {
        let index;
        if self.free.is_empty() {
            let connector = Box::into_raw(Box::new(connector));

            unsafe {
                // Cheating a bit here. Anyway, move to heap, store in list
                index = self.connectors.len();
                self.connectors.push(connector);
            }
        } else {
            index = self.free.pop().unwrap();

            unsafe {
                let target = self.connectors.get_mut(index);
                debug_assert!(!target.is_null());
                ptr::write(*target, connector);
            }
        }

        return ConnectorKey{ index: index as u32 };
    }

    fn destroy(&mut self, key: ConnectorKey) {
        unsafe {
            let connector = self.connectors.get_mut(key.index as usize);
            ptr::drop_in_place(*connector);
            // Note: but not deallocating!
        }

        self.free.push(key.index as usize);
    }
}

impl Drop for ConnectorStore {
    fn drop(&mut self) {
        for idx in 0..self.connectors.len() {
            unsafe {
                let memory = *self.connectors.get_mut(idx);
                let boxed = Box::from_raw(memory); // takes care of deallocation
            }
        }
    }
}

/// Global store of connectors, ports and queues that are used by the sceduler
/// threads. The global store has the appearance of a thread-safe datatype, but
/// one needs to be careful using it.
///
/// The intention of this data structure is to enforce the rules:
/// TODO: @docs
pub struct GlobalStore {
    connector_queue: MpmcQueue<ConnectorKey>,
    connectors: RwLock<ConnectorStore>,
}

impl GlobalStore {
    pub fn new() -> Self {
        Self{
            connector_queue: MpmcQueue::with_capacity(256),
            connectors: RwLock::new(ConnectorStore::with_capacity(256)),
        }
    }

    // Taking connectors out of global queue

    pub fn pop_key(&self) -> Option<ConnectorKey> {
        return self.connector_queue.pop_front();
    }

    pub fn push_key(&self, key: ConnectorKey) {
        self.connector_queue.push_back(key);
    }

    // Creating, retrieving and destroying connectors

    /// Retrieves a connector using the provided key. Note that the returned
    /// reference is not truly static, the `GlobalStore` needs to stay alive.
    pub fn get_connector(&self, key: &ConnectorKey) -> &'static mut Connector {
        let connectors = self.connectors.read().unwrap();
        return connectors.get_mut(key);
    }

    /// Adds a connector to the global system. Will also queue it to run
    pub fn add_connector(&self, connector: Connector) {
        let key = {
            let mut connectors = self.connectors.write().unwrap();
            connectors.create(connector)
        };

        self.connector_queue.push_back(key);
    }

    /// Destroys a connector
    pub fn destroy_connector(&self, key: ConnectorKey) {
        let mut connectors = self.connectors.write().unwrap();
        connectors.destroy(key);
    }
}