mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Expose VRc to the C++ API
(Not yet in use in the code gen)
This commit is contained in:
parent
503567d84c
commit
3194dd21ca
3 changed files with 138 additions and 8 deletions
|
@ -272,7 +272,7 @@ inline FocusEventResult process_focus_event(ComponentRef component, int64_t &foc
|
||||||
|
|
||||||
void dealloc(const ComponentVTable*, uint8_t *ptr, vtable::Layout layout) {
|
void dealloc(const ComponentVTable*, uint8_t *ptr, vtable::Layout layout) {
|
||||||
#ifdef __cpp_sized_deallocation
|
#ifdef __cpp_sized_deallocation
|
||||||
::operator delete(reinterpret_cast<void*>(ptr), layout.size, layout.align);
|
::operator delete(reinterpret_cast<void*>(ptr), layout.size, static_cast<std::align_val_t>(layout.align));
|
||||||
#else
|
#else
|
||||||
::operator delete(reinterpret_cast<void*>(ptr));
|
::operator delete(reinterpret_cast<void*>(ptr));
|
||||||
#endif
|
#endif
|
||||||
|
@ -281,10 +281,44 @@ void dealloc(const ComponentVTable*, uint8_t *ptr, vtable::Layout layout) {
|
||||||
|
|
||||||
template<typename T> vtable::Layout drop_in_place(ComponentRef component) {
|
template<typename T> vtable::Layout drop_in_place(ComponentRef component) {
|
||||||
reinterpret_cast<T*>(component.instance)->~T();
|
reinterpret_cast<T*>(component.instance)->~T();
|
||||||
return vtable::Layout { sizeof(T), std::align_val_t(alignof(T)) };
|
return vtable::Layout { sizeof(T), alignof(T) };
|
||||||
}
|
}
|
||||||
} // namespace private_api
|
} // namespace private_api
|
||||||
|
|
||||||
|
template<typename T> class ComponentWeakHandle;
|
||||||
|
|
||||||
|
/// The component handle is like a shared pointer to a component in the generated code.
|
||||||
|
/// In order to get a component, use `T::create()` where T is the name of the component
|
||||||
|
/// in the .60 file. This give you a `ComponentHandle<T>`
|
||||||
|
template<typename T>
|
||||||
|
class ComponentHandle {
|
||||||
|
vtable::VRc<private_api::ComponentVTable, T> inner;
|
||||||
|
friend class ComponentWeakHandle<T>;
|
||||||
|
public:
|
||||||
|
/// internal constructor
|
||||||
|
ComponentHandle(const vtable::VRc<private_api::ComponentVTable, T> &inner) : inner(inner) { }
|
||||||
|
|
||||||
|
const T* operator->() const {
|
||||||
|
return inner.operator->();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A weak reference to the component. Can be constructed from a `ComponentHandle<T>`
|
||||||
|
template<typename T>
|
||||||
|
class ComponentWeakHandle {
|
||||||
|
vtable::VWeak<private_api::ComponentVTable, T> inner;
|
||||||
|
public:
|
||||||
|
ComponentWeakHandle() = default;
|
||||||
|
ComponentWeakHandle(const ComponentHandle<T>&other) : inner(other.inner) {}
|
||||||
|
std::optional<ComponentHandle<T>> lock() {
|
||||||
|
if (auto l = inner.lock()) {
|
||||||
|
return { ComponentHandle(*l) };
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// layouts:
|
// layouts:
|
||||||
using cbindgen_private::grid_layout_info;
|
using cbindgen_private::grid_layout_info;
|
||||||
using cbindgen_private::GridLayoutCellData;
|
using cbindgen_private::GridLayoutCellData;
|
||||||
|
|
|
@ -11,6 +11,8 @@ LICENSE END */
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace vtable {
|
namespace vtable {
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ struct VRefMut
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
std::align_val_t align;
|
std::size_t align;
|
||||||
};
|
};
|
||||||
|
|
||||||
// For the C++'s purpose, they are all the same
|
// For the C++'s purpose, they are all the same
|
||||||
|
@ -58,5 +60,93 @@ struct VOffset
|
||||||
std::uintptr_t offset;
|
std::uintptr_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename VTable, typename X>
|
||||||
|
struct VRcInner {
|
||||||
|
template<typename VTable_, typename X_> friend class VRc;
|
||||||
|
template<typename VTable_, typename X_> friend class VWeak;
|
||||||
|
private:
|
||||||
|
const VTable *vtable;
|
||||||
|
int strong_ref;
|
||||||
|
int weak_ref;
|
||||||
|
union {
|
||||||
|
X data;
|
||||||
|
Layout layout;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dyn {};
|
||||||
|
|
||||||
|
template<typename VTable, typename X = Dyn>
|
||||||
|
class VRc {
|
||||||
|
VRcInner<VTable, X> *inner;
|
||||||
|
VRc(VRcInner<VTable, X> inner) : inner(inner) {}
|
||||||
|
template<typename VTable_, typename X_> friend class VWeak;
|
||||||
|
public:
|
||||||
|
~VRc() {
|
||||||
|
if (--inner->strong_ref) {
|
||||||
|
Layout layout = inner->vtable->drop_in_place(&inner->data);
|
||||||
|
layout.size += sizeof(const VTable *) + 2 * sizeof(int);
|
||||||
|
layout.align = std::max<size_t>(layout.align, alignof(VRcInner<VTable, Dyn>));
|
||||||
|
inner->layout = layout;
|
||||||
|
if (--inner->weak_ref) {
|
||||||
|
inner->vtable->dealloc(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VRc(const VRc &other): inner(other.inner) {
|
||||||
|
inner->strong_ref++;
|
||||||
|
}
|
||||||
|
VRc &operator=(const VRc &other) {
|
||||||
|
if (inner == other.inner)
|
||||||
|
return *this;
|
||||||
|
this->~VRc();
|
||||||
|
new(this) VRc(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename ...Args> static VRc make(Args... args) {
|
||||||
|
return VRc(new VRcInner<VTable, X>{
|
||||||
|
X::component_type, 1, 1, X(args...)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const X* operator->() const {
|
||||||
|
return inner->data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename VTable, typename X = Dyn>
|
||||||
|
class VWeak {
|
||||||
|
VRcInner<VTable, X> *inner = nullptr;
|
||||||
|
public:
|
||||||
|
VWeak() = default;
|
||||||
|
~VWeak() {
|
||||||
|
if (inner && --inner->weak_ref) {
|
||||||
|
inner->vtable->dealloc(inner->layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VWeak(const VWeak &other): inner(other.inner) {
|
||||||
|
inner && inner->weak_ref++;
|
||||||
|
}
|
||||||
|
VWeak(const VRc<VTable, X> &other): inner(other.inner) {
|
||||||
|
inner && inner->weak_ref++;
|
||||||
|
}
|
||||||
|
VWeak &operator=(const VWeak &other) {
|
||||||
|
if (inner == other.inner)
|
||||||
|
return *this;
|
||||||
|
this->~VWeak();
|
||||||
|
new(this) VWeak(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<VRc<VTable, X>> lock() const {
|
||||||
|
if (!inner || inner->strong_ref == 0)
|
||||||
|
return {};
|
||||||
|
inner->strong_ref++;
|
||||||
|
return { VRc<VTable, X>(inner) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace vtable
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ LICENSE END */
|
||||||
|
|
||||||
//! implementation of vtable::Vrc
|
//! implementation of vtable::Vrc
|
||||||
|
|
||||||
use core::cell::Cell;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use core::cell::Cell;
|
||||||
|
use core::convert::TryInto;
|
||||||
|
|
||||||
/// This trait is implemented by the `#[vtable]` macro.
|
/// This trait is implemented by the `#[vtable]` macro.
|
||||||
///
|
///
|
||||||
|
@ -85,7 +85,13 @@ impl<VTable: VTableMetaDropInPlace + 'static, X: ?Sized> Drop for VRc<VTable, X>
|
||||||
inner.strong_ref.set(inner.strong_ref.get() - 1);
|
inner.strong_ref.set(inner.strong_ref.get() - 1);
|
||||||
if inner.strong_ref.get() == 0 {
|
if inner.strong_ref.get() == 0 {
|
||||||
let data = &inner.data as *const _ as *const u8 as *mut u8;
|
let data = &inner.data as *const _ as *const u8 as *mut u8;
|
||||||
let layout = VTable::drop_in_place(inner.vtable, data);
|
let mut layout = VTable::drop_in_place(inner.vtable, data);
|
||||||
|
layout = core::alloc::Layout::new::<VRcInner<VTable, ()>>()
|
||||||
|
.extend(layout.try_into().unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.pad_to_align()
|
||||||
|
.into();
|
||||||
inner.weak_ref.set(inner.weak_ref.get() - 1);
|
inner.weak_ref.set(inner.weak_ref.get() - 1);
|
||||||
if inner.weak_ref.get() == 0 {
|
if inner.weak_ref.get() == 0 {
|
||||||
let vtable = inner.vtable;
|
let vtable = inner.vtable;
|
||||||
|
@ -106,7 +112,7 @@ impl<VTable: VTableMetaDropInPlace, X: HasStaticVTable<VTable>> VRc<VTable, X> {
|
||||||
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
||||||
/// the #[vtable] macro)
|
/// the #[vtable] macro)
|
||||||
pub fn new(data: X) -> Self {
|
pub fn new(data: X) -> Self {
|
||||||
let layout = core::alloc::Layout::new::<VRcInner<VTable, X>>();
|
let layout = core::alloc::Layout::new::<VRcInner<VTable, X>>().pad_to_align();
|
||||||
// We must ensure the size is enough to hold a Layout when stonr_count becomes 0
|
// We must ensure the size is enough to hold a Layout when stonr_count becomes 0
|
||||||
let layout_with_layout = core::alloc::Layout::new::<VRcInner<VTable, Layout>>();
|
let layout_with_layout = core::alloc::Layout::new::<VRcInner<VTable, Layout>>();
|
||||||
let layout = core::alloc::Layout::from_size_align(
|
let layout = core::alloc::Layout::from_size_align(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue