1#![allow(dead_code)]
2
3use std::cell::Cell;
4use std::fmt;
5use std::mem::MaybeUninit;
6use std::ptr::NonNull;
7
8use super::{Allocator, ShmHeader, ShmToken};
9
10pub struct ShmBox<T: ?Sized>(NonNull<T>);
11
12impl<T: ?Sized> ShmBox<T> {
13 pub fn as_shm(this: &Self) -> ShmToken<T> {
14 ShmHandle::get().get_shm(this.0)
15 }
16
17 pub fn into_raw(self) -> NonNull<T> {
18 let ptr = self.0;
19 std::mem::forget(self);
20 ptr
21 }
22
23 pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
27 ShmBox(ptr)
28 }
29}
30
31impl<T> ShmBox<T> {
32 pub fn new(val: T) -> Self {
33 unsafe { Self::from_raw(AloHandle::get().alloc(val)) }
34 }
35
36 pub fn into_uninit(self) -> ShmBox<MaybeUninit<T>> {
37 unsafe { ShmBox::from_raw(self.into_raw().cast()) }
38 }
39}
40
41impl<T> ShmBox<MaybeUninit<T>> {
42 pub fn new_uninit() -> Self {
43 unsafe { Self::from_raw(AloHandle::get().alloc_uninit()) }
44 }
45
46 pub unsafe fn assume_init(self) -> ShmBox<T> {
51 unsafe { ShmBox::from_raw(self.into_raw().cast()) }
52 }
53}
54
55impl<T> ShmBox<[T]> {
56 pub fn new_slice_copied(src: &[T]) -> Self
57 where
58 T: Copy,
59 {
60 unsafe { Self::from_raw(AloHandle::get().alloc_slice_copied(src)) }
61 }
62
63 pub fn new_slice_filled(val: T, n: usize) -> Self
64 where
65 T: Copy,
66 {
67 unsafe { Self::from_raw(AloHandle::get().alloc_slice_filled(val, n)) }
68 }
69
70 pub fn into_uninit(self) -> ShmBox<[MaybeUninit<T>]> {
71 unsafe {
72 let ptr = self.into_raw().as_ptr();
73 ShmBox::from_raw(NonNull::new_unchecked(ptr as *mut [MaybeUninit<T>]))
74 }
75 }
76}
77
78impl<T> ShmBox<[MaybeUninit<T>]> {
79 pub fn new_slice_uninit(n: usize) -> Self {
80 unsafe { Self::from_raw(AloHandle::get().alloc_slice_uninit(n)) }
81 }
82
83 pub unsafe fn assume_init(self) -> ShmBox<[T]> {
88 unsafe {
89 let ptr = self.into_raw().as_ptr();
90 ShmBox::from_raw(NonNull::new_unchecked(ptr as *mut [T]))
91 }
92 }
93}
94
95impl<T: ?Sized> Drop for ShmBox<T> {
96 fn drop(&mut self) {
97 unsafe {
98 let ptr = self.0;
99 ptr.drop_in_place();
100 AloHandle::get().dealloc(ptr);
101 }
102 }
103}
104
105impl<T: ?Sized + fmt::Debug> fmt::Debug for ShmBox<T> {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 T::fmt(self, f)
108 }
109}
110
111impl<T: ?Sized> std::ops::Deref for ShmBox<T> {
112 type Target = T;
113 fn deref(&self) -> &Self::Target {
114 unsafe { self.0.as_ref() }
115 }
116}
117
118impl<T: ?Sized> std::ops::DerefMut for ShmBox<T> {
119 fn deref_mut(&mut self) -> &mut Self::Target {
120 unsafe { self.0.as_mut() }
121 }
122}
123
124thread_local! {
125 static SHM: Cell<Option<&'static ShmHeader>> = const { Cell::new(None) };
126 static ALO: Cell<Option<&'static Allocator>> = const { Cell::new(None) };
127}
128
129pub struct ShmHandle;
130
131impl ShmHandle {
132 pub fn init(shm: &'static ShmHeader) {
133 if SHM.get().is_some() {
134 panic!("shm has been initialized");
135 }
136 SHM.set(Some(shm))
137 }
138
139 pub fn get() -> &'static ShmHeader {
140 SHM.get().expect("shm is not initialized")
141 }
142}
143
144pub struct AloHandle;
145
146impl AloHandle {
147 pub fn init(shm: &'static ShmHeader) {
148 if ALO.get().is_some() {
149 panic!("allocator has been initialized");
150 }
151 ALO.set(Some(shm.get_allocator()))
152 }
153
154 pub fn get() -> &'static Allocator {
155 ALO.get().expect("allocator is not initialized")
156 }
157}
158
159pub fn init_client(shm: &'static ShmHeader) {
160 ShmHandle::init(shm);
161 AloHandle::init(shm);
162}
163
164pub fn init_server(shm: &'static ShmHeader) {
165 ShmHandle::init(shm);
166}