local-spawn-pool 0.1.0

Spawn `!Send` futures in a pool and await for all of them to finish. Standalone alternative to `tokio::task::LocalSet`.
Documentation
use crate::task::Task;
use std::cell::RefCell;
use std::rc::Rc;
use std::thread_local;

pub struct TasksToAdd(Rc<RefCell<Vec<Task>>>);

impl TasksToAdd {
    pub fn new() -> Self {
        Self(Rc::new(RefCell::new(Vec::new())))
    }

    pub fn add(&self, task: Task) {
        self.0.borrow_mut().push(task);
    }

    pub fn access_mut<R>(&self, f: impl FnOnce(&mut Vec<Task>) -> R) -> R {
        f(&mut self.0.borrow_mut())
    }

    fn clone(&self) -> Self {
        Self(Rc::clone(&self.0))
    }
}

thread_local! {
    #[cfg(not(test))]
    static TASKS_TO_ADD_REF: RefCell<Option<TasksToAdd>> = RefCell::new(None);

    #[cfg(test)]
    static TASKS_TO_ADD_REF: RefCell<Option<(TasksToAdd, &'static str)>> = RefCell::new(None);
}

pub fn set_thread_local(tasks_to_add: &TasksToAdd, #[cfg(test)] name: &'static str) {
    TASKS_TO_ADD_REF.with(|tasks_to_add_ref| {
        #[cfg(not(test))]
        tasks_to_add_ref.replace(Some(tasks_to_add.clone()));

        #[cfg(test)]
        tasks_to_add_ref.replace(Some((tasks_to_add.clone(), name)));
    });
}

pub fn unset_thread_local() {
    TASKS_TO_ADD_REF.with(|tasks_to_add_ref| {
        tasks_to_add_ref.replace(None);
    });
}

pub fn access_thread_local<R>(
    #[cfg(not(test))] f: impl FnOnce(Option<&TasksToAdd>) -> R,
    #[cfg(test)] f: impl FnOnce(Option<&(TasksToAdd, &'static str)>) -> R,
) -> R {
    TASKS_TO_ADD_REF.with(|tasks_to_add_ref| f(tasks_to_add_ref.borrow().as_ref()))
}