use std::collections::BinaryHeap;
use std::sync::{Mutex, MutexGuard};
use std::usize;
use crate::Storage;
struct ThreadIdManager {
limit: usize,
free_list: BinaryHeap<usize>,
}
impl ThreadIdManager {
fn new() -> ThreadIdManager {
ThreadIdManager {
limit: usize::MAX,
free_list: BinaryHeap::new(),
}
}
fn alloc(&mut self) -> usize {
if let Some(id) = self.free_list.pop() {
id
} else {
let id = self.limit;
self.limit = self.limit.checked_sub(1).expect("Ran out of thread IDs");
id
}
}
fn free(&mut self, id: usize) {
self.free_list.push(id);
}
}
fn thread_id_manager() -> MutexGuard<'static, ThreadIdManager> {
static THREAD_ID_MANAGER: Storage<Mutex<ThreadIdManager>> = Storage::new();
THREAD_ID_MANAGER.get_or_set(|| Mutex::new(ThreadIdManager::new())).lock().unwrap()
}
struct ThreadId(usize);
impl ThreadId {
fn new() -> ThreadId {
ThreadId(thread_id_manager().alloc())
}
}
impl Drop for ThreadId {
fn drop(&mut self) {
thread_id_manager().free(self.0)
}
}
thread_local!(static THREAD_ID: ThreadId = ThreadId::new());
pub fn get() -> usize {
THREAD_ID.with(|x| x.0)
}