use std::{cell::Cell, num::NonZeroU16};
use index_type::IndexType;
use crate::{
atomic_type::Atomic,
thread_state::{EncodedThreadState, ThreadState},
};
mod thread_storage_slots;
pub use thread_storage_slots::{ThreadStorageSlots, ThreadStorageSlotsReadGuard};
#[derive(IndexType, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct ThreadStorageSlotId(
pub NonZeroU16,
);
#[derive(Debug)]
pub struct ThreadStorageSlotValue {
pub state: Atomic<EncodedThreadState>,
}
static THREAD_STORAGE_SLOTS: ThreadStorageSlots = ThreadStorageSlots::new();
pub fn thread_storage_slot_get_all() -> ThreadStorageSlotsReadGuard<'static> {
THREAD_STORAGE_SLOTS.read()
}
pub struct OwnedThreadStorageSlot {
id: Cell<Option<ThreadStorageSlotId>>,
}
impl OwnedThreadStorageSlot {
pub const fn unallocated() -> Self {
Self {
id: Cell::new(None),
}
}
pub fn alloc(&self, initial_thread_state: ThreadState) {
if self.id.get().is_some() {
return;
}
let id = THREAD_STORAGE_SLOTS.alloc(initial_thread_state);
self.id.set(Some(id));
}
pub fn dealloc(&self) {
let Some(id) = self.id.get() else { return };
unsafe { THREAD_STORAGE_SLOTS.dealloc(id) };
self.id.set(None);
}
pub fn id(&self) -> Option<ThreadStorageSlotId> {
self.id.get()
}
}
impl Drop for OwnedThreadStorageSlot {
fn drop(&mut self) {
self.dealloc();
}
}
thread_local! {
static THREAD_STORAGE_SLOT: OwnedThreadStorageSlot = const { OwnedThreadStorageSlot::unallocated() };
}
pub fn this_thread_get_storage_slot_id() -> ThreadStorageSlotId {
THREAD_STORAGE_SLOT.with(|storage_slot| storage_slot.id().unwrap())
}
pub fn this_thread_does_have_allocated_storage_slot() -> bool {
THREAD_STORAGE_SLOT.with(|storage_slot| storage_slot.id.get().is_some())
}
pub fn this_thread_alloc_storage_slot(initial_thread_state: ThreadState) {
THREAD_STORAGE_SLOT.with(|storage_slot| storage_slot.alloc(initial_thread_state))
}
pub fn this_thread_dealloc_storage_slot() {
THREAD_STORAGE_SLOT.with(|storage_slot| storage_slot.dealloc())
}