1use std::ops::{Deref, DerefMut};
20use std::sync::atomic::AtomicU64;
21
22use crate::derive::ObjectRef;
23pub use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
24use tvm_ffi_sys::{TVMFFIObject, COMBINED_REF_COUNT_BOTH_ONE};
26
27#[repr(C)]
29pub struct Object {
30 header: TVMFFIObject,
32}
33
34#[repr(C)]
38pub struct ObjectArc<T: ObjectCore> {
39 ptr: std::ptr::NonNull<T>,
40 _phantom: std::marker::PhantomData<T>,
41}
42
43unsafe impl<T: Send + Sync + ObjectCore> Send for ObjectArc<T> {}
44unsafe impl<T: Send + Sync + ObjectCore> Sync for ObjectArc<T> {}
45
46pub unsafe trait ObjectCore: Sized + 'static {
51 const TYPE_KEY: &'static str;
53 fn type_index() -> i32;
55 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject;
65}
66
67pub unsafe trait ObjectCoreWithExtraItems: ObjectCore {
71 type ExtraItem;
73 fn extra_items_count(this: &Self) -> usize;
75 unsafe fn extra_items(this: &Self) -> &[Self::ExtraItem] {
77 let extra_items_ptr = (this as *const Self as *const u8).add(std::mem::size_of::<Self>());
78 std::slice::from_raw_parts(
79 extra_items_ptr as *const Self::ExtraItem,
80 Self::extra_items_count(this),
81 )
82 }
83 unsafe fn extra_items_mut(this: &mut Self) -> &mut [Self::ExtraItem] {
85 let extra_items_ptr = (this as *mut Self as *mut u8).add(std::mem::size_of::<Self>());
86 std::slice::from_raw_parts_mut(
87 extra_items_ptr as *mut Self::ExtraItem,
88 Self::extra_items_count(this),
89 )
90 }
91}
92
93pub unsafe trait ObjectRefCore: Sized + Clone {
99 type ContainerType: ObjectCore;
100 fn data(this: &Self) -> &ObjectArc<Self::ContainerType>;
101 fn into_data(this: Self) -> ObjectArc<Self::ContainerType>;
102 fn from_data(data: ObjectArc<Self::ContainerType>) -> Self;
103}
104
105#[repr(C)]
109#[derive(ObjectRef, Clone)]
110pub struct ObjectRef {
111 data: ObjectArc<Object>,
112}
113
114pub(crate) mod unsafe_ {
116 use tvm_ffi_sys::{
117 COMBINED_REF_COUNT_BOTH_ONE, COMBINED_REF_COUNT_MASK_U32, COMBINED_REF_COUNT_STRONG_ONE,
118 COMBINED_REF_COUNT_WEAK_ONE,
119 };
120
121 use std::ffi::c_void;
122 use std::sync::atomic::{fence, Ordering};
123 use tvm_ffi_sys::TVMFFIObject;
124 use tvm_ffi_sys::TVMFFIObjectDeleterFlagBitMask::{
125 kTVMFFIObjectDeleterFlagBitMaskBoth, kTVMFFIObjectDeleterFlagBitMaskStrong,
126 kTVMFFIObjectDeleterFlagBitMaskWeak,
127 };
128
129 #[inline]
136 pub unsafe fn inc_ref(handle: *mut TVMFFIObject) {
137 let obj = &mut *handle;
138 obj.combined_ref_count.fetch_add(1, Ordering::Relaxed);
139 }
140
141 #[inline]
148 pub unsafe fn dec_ref(handle: *mut TVMFFIObject) {
149 let obj = &mut *handle;
150 let old_combined_count = obj
151 .combined_ref_count
152 .fetch_sub(COMBINED_REF_COUNT_STRONG_ONE, Ordering::Relaxed);
153 if old_combined_count == COMBINED_REF_COUNT_BOTH_ONE {
154 if let Some(deleter) = obj.deleter {
155 fence(Ordering::Acquire);
156 deleter(
157 obj as *mut TVMFFIObject as *mut c_void,
158 kTVMFFIObjectDeleterFlagBitMaskBoth as i32,
159 );
160 }
161 } else if (old_combined_count & COMBINED_REF_COUNT_MASK_U32)
162 == COMBINED_REF_COUNT_STRONG_ONE
163 {
164 fence(Ordering::Acquire);
167 if let Some(deleter) = obj.deleter {
168 deleter(
169 obj as *mut TVMFFIObject as *mut c_void,
170 kTVMFFIObjectDeleterFlagBitMaskStrong as i32,
171 );
172 }
173 let old_weak_count = obj
174 .combined_ref_count
175 .fetch_sub(COMBINED_REF_COUNT_WEAK_ONE, Ordering::Release);
176 if old_weak_count == COMBINED_REF_COUNT_WEAK_ONE {
177 fence(Ordering::Acquire);
178 if let Some(deleter) = obj.deleter {
179 deleter(
180 obj as *mut TVMFFIObject as *mut c_void,
181 kTVMFFIObjectDeleterFlagBitMaskWeak as i32,
182 );
183 }
184 }
185 }
186 }
187
188 #[inline]
189 pub unsafe fn strong_count(handle: *mut TVMFFIObject) -> usize {
190 let obj = &mut *handle;
191 (obj.combined_ref_count.load(Ordering::Relaxed) & COMBINED_REF_COUNT_MASK_U32) as usize
192 }
193
194 #[inline]
195 pub unsafe fn weak_count(handle: *mut TVMFFIObject) -> usize {
196 let obj = &mut *handle;
197 (obj.combined_ref_count.load(Ordering::Relaxed) >> 32) as usize
198 }
199
200 pub unsafe extern "C" fn object_deleter_for_new<T>(ptr: *mut c_void, flags: i32)
202 where
203 T: super::ObjectCore,
204 {
205 let obj = ptr as *mut T;
206 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
207 std::ptr::drop_in_place(obj);
209 }
210 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
211 std::alloc::dealloc(ptr as *mut u8, std::alloc::Layout::new::<T>());
213 }
214 }
215
216 pub unsafe extern "C" fn object_deleter_for_new_with_extra_items<T, U>(
217 ptr: *mut c_void,
218 flags: i32,
219 ) where
220 T: super::ObjectCoreWithExtraItems<ExtraItem = U>,
221 {
222 let obj = ptr as *mut T;
223 if flags == kTVMFFIObjectDeleterFlagBitMaskBoth as i32 {
224 let extra_items_count = T::extra_items_count(&(*obj));
226 std::ptr::drop_in_place(obj);
227 let layout = std::alloc::Layout::from_size_align(
228 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
229 std::mem::align_of::<T>(),
230 )
231 .unwrap();
232 std::alloc::dealloc(ptr as *mut u8, layout);
234 } else {
235 assert_eq!(std::mem::size_of::<T>() % std::mem::size_of::<u64>(), 0);
236 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
237 let extra_items_count = T::extra_items_count(&(*obj));
239 std::ptr::drop_in_place(obj);
241 std::ptr::write(obj as *mut u64, extra_items_count as u64);
243 }
244 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
245 let extra_items_count = std::ptr::read(obj as *mut u64) as usize;
249 let layout = std::alloc::Layout::from_size_align(
250 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
251 std::mem::align_of::<T>(),
252 )
253 .unwrap();
254 std::alloc::dealloc(ptr as *mut u8, layout);
256 }
257 }
258 }
259}
260
261impl Object {
266 pub fn new() -> Self {
267 Self {
268 header: TVMFFIObject::new(),
269 }
270 }
271}
272
273unsafe impl ObjectCore for Object {
274 const TYPE_KEY: &'static str = "ffi.Object";
275 #[inline]
276 fn type_index() -> i32 {
277 TypeIndex::kTVMFFIStaticObjectBegin as i32
278 }
279 #[inline]
280 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
281 &mut this.header
282 }
283}
284
285impl<T: ObjectCore> ObjectArc<T> {
289 pub fn new(data: T) -> Self {
290 unsafe {
291 let layout = std::alloc::Layout::new::<T>();
292 let raw_data_ptr = std::alloc::alloc(layout);
293 if raw_data_ptr.is_null() {
294 std::alloc::handle_alloc_error(layout);
295 }
296 let ptr = raw_data_ptr as *mut T;
297 std::ptr::write(ptr, data);
298 std::ptr::write(
300 ptr as *mut TVMFFIObject,
301 TVMFFIObject {
302 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
303 type_index: T::type_index(),
304 __padding: 0,
305 deleter: Some(unsafe_::object_deleter_for_new::<T>),
306 },
307 );
308 Self {
310 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
311 _phantom: std::marker::PhantomData,
312 }
313 }
314 }
315 pub fn new_with_extra_items<U>(data: T) -> Self
316 where
317 T: ObjectCoreWithExtraItems<ExtraItem = U>,
318 {
319 unsafe {
320 assert_eq!(std::mem::align_of::<T>() % std::mem::align_of::<U>(), 0);
323 assert_eq!(std::mem::size_of::<T>() % std::mem::align_of::<U>(), 0);
324 let extra_items_count = T::extra_items_count(&data);
325 let layout = std::alloc::Layout::from_size_align(
326 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
327 std::mem::align_of::<T>(),
328 )
329 .unwrap();
330 let raw_data_ptr = std::alloc::alloc(layout);
331 if raw_data_ptr.is_null() {
332 std::alloc::handle_alloc_error(layout);
333 }
334 let ptr = raw_data_ptr as *mut T;
335 std::ptr::write(ptr, data);
336 std::ptr::write(
338 ptr as *mut TVMFFIObject,
339 TVMFFIObject {
340 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
341 type_index: T::type_index(),
342 __padding: 0,
343 deleter: Some(unsafe_::object_deleter_for_new_with_extra_items::<T, U>),
344 },
345 );
346 Self {
348 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
349 _phantom: std::marker::PhantomData,
350 }
351 }
352 }
353
354 #[inline]
363 pub unsafe fn from_raw(ptr: *const T) -> Self {
364 Self {
365 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
366 _phantom: std::marker::PhantomData,
367 }
368 }
369
370 #[inline]
378 pub unsafe fn into_raw(this: Self) -> *const T {
379 let droped_this = std::mem::ManuallyDrop::new(this);
380 droped_this.ptr.as_ptr() as *const T
381 }
382
383 #[inline]
394 pub unsafe fn as_raw(this: &Self) -> *const T {
395 this.ptr.as_ptr() as *const T
396 }
397
398 #[inline]
408 pub unsafe fn as_raw_mut(this: &mut Self) -> *mut T {
409 this.ptr.as_mut()
410 }
411
412 #[inline]
420 pub fn strong_count(this: &Self) -> usize {
421 unsafe {
422 unsafe_::strong_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject)
423 }
424 }
425
426 #[inline]
434 pub fn weak_count(this: &Self) -> usize {
435 unsafe { unsafe_::weak_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
436 }
437}
438
439impl<T: ObjectCore> Deref for ObjectArc<T> {
441 type Target = T;
442 #[inline]
443 fn deref(&self) -> &Self::Target {
444 unsafe { self.ptr.as_ref() }
445 }
446}
447
448impl<T: ObjectCore> DerefMut for ObjectArc<T> {
450 #[inline]
451 fn deref_mut(&mut self) -> &mut Self::Target {
452 unsafe { self.ptr.as_mut() }
453 }
454}
455
456impl<T: ObjectCore> Drop for ObjectArc<T> {
458 fn drop(&mut self) {
459 unsafe { unsafe_::dec_ref(self.ptr.as_mut() as *mut T as *mut TVMFFIObject) }
460 }
461}
462
463impl<T: ObjectCore> Clone for ObjectArc<T> {
465 #[inline]
466 fn clone(&self) -> Self {
467 unsafe { unsafe_::inc_ref(self.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
468 Self {
469 ptr: self.ptr,
470 _phantom: std::marker::PhantomData,
471 }
472 }
473}