duskphantom_utils/
mem.rs

1// Copyright 2024 Duskphantom Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17use std::{
18    fmt::Debug,
19    hash::{Hash, Hasher},
20    ops::{Deref, DerefMut},
21    ptr::NonNull,
22};
23
24/// 裸指针,基于unsafe实现
25pub struct ObjPtr<T>(NonNull<T>);
26
27impl<T> ObjPtr<T> {
28    pub fn new(ptr: &T) -> ObjPtr<T> {
29        ObjPtr(NonNull::new(ptr as *const _ as *mut _).unwrap())
30    }
31}
32impl<T> AsRef<T> for ObjPtr<T> {
33    fn as_ref(&self) -> &T {
34        unsafe { self.0.as_ref() }
35    }
36}
37impl<T> AsMut<T> for ObjPtr<T> {
38    fn as_mut(&mut self) -> &mut T {
39        unsafe { self.0.as_mut() }
40    }
41}
42
43impl<T> Deref for ObjPtr<T> {
44    type Target = T;
45    fn deref(&self) -> &Self::Target {
46        unsafe { self.0.as_ref() }
47    }
48}
49
50impl<T> DerefMut for ObjPtr<T> {
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        unsafe { self.0.as_mut() }
53    }
54}
55
56impl<T> Clone for ObjPtr<T> {
57    fn clone(&self) -> Self {
58        *self
59    }
60}
61
62impl<T> Copy for ObjPtr<T> {}
63
64impl<T> PartialEq for ObjPtr<T> {
65    fn eq(&self, other: &Self) -> bool {
66        std::ptr::eq(self.as_ref(), other.as_ref())
67    }
68}
69
70impl<T> Eq for ObjPtr<T> {}
71
72/// Deterministic ordering for ObjPtr.
73/// Comparing by pointer address is non-deterministic, so we compare by the object itself.
74impl<T> PartialOrd for ObjPtr<T>
75where
76    T: PartialOrd,
77{
78    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
79        self.as_ref().partial_cmp(other.as_ref())
80    }
81}
82
83impl<T> Ord for ObjPtr<T>
84where
85    T: Ord,
86{
87    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
88        self.as_ref().cmp(other.as_ref())
89    }
90}
91
92impl<T> Hash for ObjPtr<T> {
93    fn hash<H: Hasher>(&self, state: &mut H) {
94        std::ptr::hash(self.as_ref(), state)
95    }
96}
97
98impl<T> From<&T> for ObjPtr<T> {
99    fn from(ptr: &T) -> Self {
100        Self::new(ptr)
101    }
102}
103
104impl<T> From<&mut T> for ObjPtr<T> {
105    fn from(ptr: &mut T) -> Self {
106        Self::new(ptr)
107    }
108}
109
110impl<T> Debug for ObjPtr<T> {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(f, "{:p}", self.as_ref())
113    }
114}
115
116pub struct ObjPool<T>
117where
118    T: Sized,
119{
120    arena: typed_arena::Arena<std::pin::Pin<Box<T>>>,
121}
122
123impl<T> Default for ObjPool<T>
124where
125    T: Sized,
126{
127    fn default() -> Self {
128        Self {
129            arena: typed_arena::Arena::new(),
130        }
131    }
132}
133impl<T> ObjPool<T> {
134    /// 构造一个新的内存分配器
135    pub fn new() -> Self {
136        Default::default()
137    }
138
139    /// 分配一块内存存放obj
140    pub fn alloc(&mut self, obj: T) -> ObjPtr<T> {
141        ObjPtr::new(self.arena.alloc(Box::pin(obj)))
142    }
143
144    /// 清空内存池
145    pub fn clear(&mut self) {
146        self.arena = typed_arena::Arena::new();
147    }
148}