1use std::ops::{Deref, DerefMut};
20use std::sync::atomic::AtomicU64;
21
22use crate::derive::ObjectRef;
23use crate::type_traits::AnyCompatible;
24pub use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
25use tvm_ffi_sys::{
27 TVMFFIAny, TVMFFIGetCustomAllocator, TVMFFIGetTypeInfo, TVMFFIObject,
28 COMBINED_REF_COUNT_BOTH_ONE,
29};
30
31#[repr(C)]
33pub struct Object {
34 header: TVMFFIObject,
36}
37
38#[repr(C)]
42pub struct ObjectArc<T: ObjectCore> {
43 ptr: std::ptr::NonNull<T>,
44 _phantom: std::marker::PhantomData<T>,
45}
46
47unsafe impl<T: Send + Sync + ObjectCore> Send for ObjectArc<T> {}
48unsafe impl<T: Send + Sync + ObjectCore> Sync for ObjectArc<T> {}
49
50pub unsafe trait ObjectCore: Sized + 'static {
55 const TYPE_KEY: &'static str;
57 const TYPE_DEPTH: i32;
63 #[doc(hidden)]
67 const TYPE_FINAL: bool = false;
68 fn type_index() -> i32;
70 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject;
80}
81
82pub unsafe trait ObjectCoreWithExtraItems: ObjectCore {
86 type ExtraItem;
88 fn extra_items_count(this: &Self) -> usize;
90 unsafe fn extra_items(this: &Self) -> &[Self::ExtraItem] {
92 let extra_items_ptr = (this as *const Self as *const u8).add(std::mem::size_of::<Self>());
93 std::slice::from_raw_parts(
94 extra_items_ptr as *const Self::ExtraItem,
95 Self::extra_items_count(this),
96 )
97 }
98 unsafe fn extra_items_mut(this: &mut Self) -> &mut [Self::ExtraItem] {
100 let extra_items_ptr = (this as *mut Self as *mut u8).add(std::mem::size_of::<Self>());
101 std::slice::from_raw_parts_mut(
102 extra_items_ptr as *mut Self::ExtraItem,
103 Self::extra_items_count(this),
104 )
105 }
106}
107
108pub unsafe trait ObjectRefCore: Sized + Clone {
128 type ContainerType: ObjectCore;
129 fn data(this: &Self) -> &ObjectArc<Self::ContainerType>;
130 fn into_data(this: Self) -> ObjectArc<Self::ContainerType>;
131 fn from_data(data: ObjectArc<Self::ContainerType>) -> Self;
132}
133
134#[doc(hidden)]
147#[inline(always)]
148pub fn is_instance_of<Target: ObjectCore>(object_type_index: i32) -> bool {
149 let target_type_index = Target::type_index();
150 if object_type_index == target_type_index {
151 return true;
152 }
153 let object_begin = TypeIndex::kTVMFFIStaticObjectBegin as i32;
154 if object_type_index < object_begin || target_type_index < object_begin {
156 return false;
157 }
158 if object_type_index < target_type_index {
160 return false;
161 }
162 unsafe {
163 let object_info = TVMFFIGetTypeInfo(object_type_index);
164 if object_info.is_null() {
165 return false;
166 }
167 let target_depth = Target::TYPE_DEPTH;
168 if (*object_info).type_depth <= target_depth {
169 return false;
170 }
171 let ancestor = *(*object_info).type_acenstors.add(target_depth as usize);
172 !ancestor.is_null() && (*ancestor).type_index == target_type_index
173 }
174}
175
176pub trait ObjectRefCast: ObjectRefCore + AnyCompatible {
185 #[inline(always)]
187 fn try_cast<B>(self) -> crate::error::Result<B>
188 where
189 B: ObjectRefCore + AnyCompatible,
190 {
191 let mut any_data = TVMFFIAny::new();
192 unsafe {
193 Self::copy_to_any_view(&self, &mut any_data);
197 debug_assert!(any_data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32);
198 std::hint::assert_unchecked(
201 any_data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32,
202 );
203
204 if B::check_any_strict(&any_data) {
205 Self::move_to_any(self, &mut any_data);
208 Ok(B::move_from_any_after_check(&mut any_data))
209 } else {
210 let msg = format!(
211 "Cannot convert from type `{}` to `{}`",
212 B::get_mismatch_type_info(&any_data),
213 B::type_str()
214 );
215 Err(crate::error::Error::new(crate::error::TYPE_ERROR, &msg, ""))
216 }
217 }
218 }
219}
220
221impl<T: ObjectRefCore + AnyCompatible> ObjectRefCast for T {}
222
223#[repr(C)]
227#[derive(ObjectRef, Clone)]
228pub struct ObjectRef {
229 data: ObjectArc<Object>,
230}
231
232#[doc(hidden)]
234pub mod unsafe_ {
235 use tvm_ffi_sys::{
236 COMBINED_REF_COUNT_BOTH_ONE, COMBINED_REF_COUNT_MASK_U32, COMBINED_REF_COUNT_STRONG_ONE,
237 COMBINED_REF_COUNT_WEAK_ONE,
238 };
239
240 use std::ffi::c_void;
241 use std::sync::atomic::{fence, Ordering};
242 use tvm_ffi_sys::{TVMFFIObject, TVMFFIObjectAllocHeader};
243 use tvm_ffi_sys::TVMFFIObjectDeleterFlagBitMask::{
244 kTVMFFIObjectDeleterFlagBitMaskBoth, kTVMFFIObjectDeleterFlagBitMaskStrong,
245 kTVMFFIObjectDeleterFlagBitMaskWeak,
246 };
247
248 #[inline]
255 pub unsafe fn inc_ref(handle: *mut TVMFFIObject) {
256 let obj = &mut *handle;
257 obj.combined_ref_count.fetch_add(1, Ordering::Relaxed);
258 }
259
260 #[inline]
267 pub(crate) unsafe fn dec_ref(handle: *mut TVMFFIObject) {
268 let obj = &mut *handle;
269 let old_combined_count = obj
270 .combined_ref_count
271 .fetch_sub(COMBINED_REF_COUNT_STRONG_ONE, Ordering::Relaxed);
272 if old_combined_count == COMBINED_REF_COUNT_BOTH_ONE {
273 if let Some(deleter) = obj.deleter {
274 fence(Ordering::Acquire);
275 deleter(
276 obj as *mut TVMFFIObject as *mut c_void,
277 kTVMFFIObjectDeleterFlagBitMaskBoth as i32,
278 );
279 }
280 } else if (old_combined_count & COMBINED_REF_COUNT_MASK_U32)
281 == COMBINED_REF_COUNT_STRONG_ONE
282 {
283 fence(Ordering::Acquire);
286 if let Some(deleter) = obj.deleter {
287 deleter(
288 obj as *mut TVMFFIObject as *mut c_void,
289 kTVMFFIObjectDeleterFlagBitMaskStrong as i32,
290 );
291 }
292 let old_weak_count = obj
293 .combined_ref_count
294 .fetch_sub(COMBINED_REF_COUNT_WEAK_ONE, Ordering::Release);
295 if old_weak_count == COMBINED_REF_COUNT_WEAK_ONE {
296 fence(Ordering::Acquire);
297 if let Some(deleter) = obj.deleter {
298 deleter(
299 obj as *mut TVMFFIObject as *mut c_void,
300 kTVMFFIObjectDeleterFlagBitMaskWeak as i32,
301 );
302 }
303 }
304 }
305 }
306
307 #[inline]
308 pub(crate) unsafe fn strong_count(handle: *mut TVMFFIObject) -> usize {
309 let obj = &mut *handle;
310 (obj.combined_ref_count.load(Ordering::Relaxed) & COMBINED_REF_COUNT_MASK_U32) as usize
311 }
312
313 #[inline]
314 pub(crate) unsafe fn weak_count(handle: *mut TVMFFIObject) -> usize {
315 let obj = &mut *handle;
316 (obj.combined_ref_count.load(Ordering::Relaxed) >> 32) as usize
317 }
318
319 pub(crate) unsafe extern "C" fn object_deleter_for_new<T>(ptr: *mut c_void, flags: i32)
322 where
323 T: super::ObjectCore,
324 {
325 let obj = ptr as *mut T;
326 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
327 std::ptr::drop_in_place(obj);
328 }
329 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
330 let header_ptr = (ptr as *mut u8)
331 .sub(std::mem::size_of::<TVMFFIObjectAllocHeader>())
332 as *mut TVMFFIObjectAllocHeader;
333 let delete_space = (*header_ptr)
334 .delete_space
335 .expect("TVMFFIObjectAllocHeader::delete_space must be set by the allocator");
336 delete_space(ptr);
337 }
338 }
339}
340
341impl Object {
346 pub fn new() -> Self {
347 Self {
348 header: TVMFFIObject::new(),
349 }
350 }
351}
352
353unsafe impl ObjectCore for Object {
354 const TYPE_KEY: &'static str = "ffi.Object";
355 const TYPE_DEPTH: i32 = 0;
356 #[inline]
357 fn type_index() -> i32 {
358 TypeIndex::kTVMFFIStaticObjectBegin as i32
359 }
360 #[inline]
361 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
362 &mut this.header
363 }
364}
365
366unsafe fn allocate_via_registry(size: usize, alignment: usize, type_index: i32) -> *mut u8 {
372 let alloc = TVMFFIGetCustomAllocator();
373 let allocate_fn = (*alloc)
374 .allocate
375 .expect("TVMFFICustomAllocator::allocate must be set");
376 allocate_fn(size, alignment, type_index, (*alloc).context) as *mut u8
377}
378
379impl<T: ObjectCore> ObjectArc<T> {
380 pub fn new(data: T) -> Self {
381 unsafe {
382 let raw_data_ptr = allocate_via_registry(
383 std::mem::size_of::<T>(),
384 std::mem::align_of::<T>(),
385 T::type_index(),
386 );
387 let ptr = raw_data_ptr as *mut T;
388 std::ptr::write(ptr, data);
389 std::ptr::write(
391 ptr as *mut TVMFFIObject,
392 TVMFFIObject {
393 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
394 type_index: T::type_index(),
395 __padding: 0,
396 deleter: Some(unsafe_::object_deleter_for_new::<T>),
397 },
398 );
399 Self {
401 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
402 _phantom: std::marker::PhantomData,
403 }
404 }
405 }
406 pub fn new_with_extra_items<U>(data: T) -> Self
407 where
408 T: ObjectCoreWithExtraItems<ExtraItem = U>,
409 {
410 unsafe {
411 assert_eq!(std::mem::align_of::<T>() % std::mem::align_of::<U>(), 0);
414 assert_eq!(std::mem::size_of::<T>() % std::mem::align_of::<U>(), 0);
415 let extra_items_count = T::extra_items_count(&data);
416 let total_size = std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>();
417 let raw_data_ptr =
418 allocate_via_registry(total_size, std::mem::align_of::<T>(), T::type_index());
419 let ptr = raw_data_ptr as *mut T;
420 std::ptr::write(ptr, data);
421 std::ptr::write(
423 ptr as *mut TVMFFIObject,
424 TVMFFIObject {
425 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
426 type_index: T::type_index(),
427 __padding: 0,
428 deleter: Some(unsafe_::object_deleter_for_new::<T>),
429 },
430 );
431 Self {
433 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
434 _phantom: std::marker::PhantomData,
435 }
436 }
437 }
438
439 #[inline]
448 pub unsafe fn from_raw(ptr: *const T) -> Self {
449 Self {
450 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
451 _phantom: std::marker::PhantomData,
452 }
453 }
454
455 #[inline]
463 pub unsafe fn into_raw(this: Self) -> *const T {
464 let droped_this = std::mem::ManuallyDrop::new(this);
465 droped_this.ptr.as_ptr() as *const T
466 }
467
468 #[inline]
479 pub unsafe fn as_raw(this: &Self) -> *const T {
480 this.ptr.as_ptr() as *const T
481 }
482
483 #[inline]
493 pub unsafe fn as_raw_mut(this: &mut Self) -> *mut T {
494 this.ptr.as_mut()
495 }
496
497 #[inline]
505 pub fn strong_count(this: &Self) -> usize {
506 unsafe {
507 unsafe_::strong_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject)
508 }
509 }
510
511 #[inline]
519 pub fn weak_count(this: &Self) -> usize {
520 unsafe { unsafe_::weak_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
521 }
522}
523
524impl<T: ObjectCore> Deref for ObjectArc<T> {
526 type Target = T;
527 #[inline]
528 fn deref(&self) -> &Self::Target {
529 unsafe { self.ptr.as_ref() }
530 }
531}
532
533impl<T: ObjectCore> DerefMut for ObjectArc<T> {
535 #[inline]
536 fn deref_mut(&mut self) -> &mut Self::Target {
537 unsafe { self.ptr.as_mut() }
538 }
539}
540
541impl<T: ObjectCore> Drop for ObjectArc<T> {
543 fn drop(&mut self) {
544 unsafe { unsafe_::dec_ref(self.ptr.as_mut() as *mut T as *mut TVMFFIObject) }
545 }
546}
547
548impl<T: ObjectCore> Clone for ObjectArc<T> {
550 #[inline]
551 fn clone(&self) -> Self {
552 unsafe { unsafe_::inc_ref(self.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
553 Self {
554 ptr: self.ptr,
555 _phantom: std::marker::PhantomData,
556 }
557 }
558}