rmux-server 0.10.0

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
use std::sync::{Arc, Condvar, Mutex as StdMutex};

use super::super::super::RequestHandler;

#[derive(Debug, Default)]
pub(in crate::handler) struct AttachedKeyTableTimerMutationPause {
    pub(in crate::handler) reached: tokio::sync::Notify,
    released: StdMutex<bool>,
    release: Condvar,
}

impl AttachedKeyTableTimerMutationPause {
    pub(in crate::handler) fn release(&self) {
        *self
            .released
            .lock()
            .expect("key table timer mutation pause lock") = true;
        self.release.notify_one();
    }

    fn wait(&self) {
        self.reached.notify_one();
        let mut released = self
            .released
            .lock()
            .expect("key table timer mutation pause lock");
        while !*released {
            released = self
                .release
                .wait(released)
                .expect("key table timer mutation pause lock");
        }
    }
}

#[derive(Debug, Default)]
pub(in crate::handler) struct AttachedKeyTableTimerAsyncPause {
    pub(in crate::handler) reached: tokio::sync::Notify,
    pub(in crate::handler) release: tokio::sync::Notify,
}

static TIMER_MUTATION_PAUSES: StdMutex<Vec<(usize, Arc<AttachedKeyTableTimerMutationPause>)>> =
    StdMutex::new(Vec::new());
static TIMER_EXPIRY_PAUSES: StdMutex<Vec<(usize, Arc<AttachedKeyTableTimerAsyncPause>)>> =
    StdMutex::new(Vec::new());
static TRANSITION_PAUSES: StdMutex<Vec<(usize, Arc<AttachedKeyTableTimerMutationPause>)>> =
    StdMutex::new(Vec::new());
static TIMER_REFRESH_PAUSES: StdMutex<Vec<(usize, Arc<AttachedKeyTableTimerAsyncPause>)>> =
    StdMutex::new(Vec::new());
static SWITCH_APPLY_PAUSES: StdMutex<Vec<(usize, u32, Arc<AttachedKeyTableTimerAsyncPause>)>> =
    StdMutex::new(Vec::new());

impl RequestHandler {
    pub(in crate::handler) fn install_attached_key_table_timer_mutation_pause(
        &self,
    ) -> Arc<AttachedKeyTableTimerMutationPause> {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = Arc::new(AttachedKeyTableTimerMutationPause::default());
        TIMER_MUTATION_PAUSES
            .lock()
            .expect("key table timer mutation pause registry lock")
            .push((handler_key, Arc::clone(&pause)));
        pause
    }

    pub(in crate::handler) fn install_attached_key_table_timer_refresh_pause(
        &self,
    ) -> Arc<AttachedKeyTableTimerAsyncPause> {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = Arc::new(AttachedKeyTableTimerAsyncPause::default());
        TIMER_REFRESH_PAUSES
            .lock()
            .expect("key table timer refresh pause registry lock")
            .push((handler_key, Arc::clone(&pause)));
        pause
    }

    pub(in crate::handler) fn install_attached_key_table_timer_expiry_pause(
        &self,
    ) -> Arc<AttachedKeyTableTimerAsyncPause> {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = Arc::new(AttachedKeyTableTimerAsyncPause::default());
        TIMER_EXPIRY_PAUSES
            .lock()
            .expect("key table timer expiry pause registry lock")
            .push((handler_key, Arc::clone(&pause)));
        pause
    }

    pub(in crate::handler) fn install_attached_key_table_switch_apply_pause(
        &self,
        attach_pid: u32,
    ) -> Arc<AttachedKeyTableTimerAsyncPause> {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = Arc::new(AttachedKeyTableTimerAsyncPause::default());
        SWITCH_APPLY_PAUSES
            .lock()
            .expect("key table switch apply pause registry lock")
            .push((handler_key, attach_pid, Arc::clone(&pause)));
        pause
    }

    pub(in crate::handler) fn install_attached_key_table_transition_pause(
        &self,
    ) -> Arc<AttachedKeyTableTimerMutationPause> {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = Arc::new(AttachedKeyTableTimerMutationPause::default());
        TRANSITION_PAUSES
            .lock()
            .expect("key table transition pause registry lock")
            .push((handler_key, Arc::clone(&pause)));
        pause
    }

    pub(super) fn pause_attached_key_table_timer_mutation(&self) {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        if let Some(pause) = take_timer_pause(&TIMER_MUTATION_PAUSES, handler_key) {
            pause.wait();
        }
    }

    pub(super) async fn pause_attached_key_table_timer_expiry(&self) {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        if let Some(pause) = take_timer_pause(&TIMER_EXPIRY_PAUSES, handler_key) {
            pause.reached.notify_one();
            pause.release.notified().await;
        }
    }

    pub(in crate::handler) async fn pause_before_attached_key_table_switch_apply(
        &self,
        attach_pid: u32,
    ) {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        let pause = {
            let mut pauses = SWITCH_APPLY_PAUSES
                .lock()
                .expect("key table switch apply pause registry lock");
            pauses
                .iter()
                .position(|(key, pid, _)| *key == handler_key && *pid == attach_pid)
                .map(|position| pauses.swap_remove(position).2)
        };
        if let Some(pause) = pause {
            pause.reached.notify_one();
            pause.release.notified().await;
        }
    }

    pub(super) fn pause_attached_key_table_transition_commit(&self) {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        if let Some(pause) = take_timer_pause(&TRANSITION_PAUSES, handler_key) {
            pause.wait();
        }
    }

    pub(super) async fn pause_attached_key_table_timer_refresh(&self) {
        let handler_key = Arc::as_ptr(&self.lifecycle_producers) as usize;
        if let Some(pause) = take_timer_pause(&TIMER_REFRESH_PAUSES, handler_key) {
            pause.reached.notify_one();
            pause.release.notified().await;
        }
    }
}

fn take_timer_pause<T>(
    pauses: &StdMutex<Vec<(usize, Arc<T>)>>,
    handler_key: usize,
) -> Option<Arc<T>> {
    let mut pauses = pauses.lock().expect("key table timer pause registry lock");
    pauses
        .iter()
        .position(|(key, _)| *key == handler_key)
        .map(|position| pauses.swap_remove(position).1)
}