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) {
|
||||
#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
|
||||
::operator delete(reinterpret_cast<void*>(ptr));
|
||||
#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) {
|
||||
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
|
||||
|
||||
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:
|
||||
using cbindgen_private::grid_layout_info;
|
||||
using cbindgen_private::GridLayoutCellData;
|
||||
|
|
|
@ -11,6 +11,8 @@ LICENSE END */
|
|||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace vtable {
|
||||
|
||||
|
@ -23,7 +25,7 @@ struct VRefMut
|
|||
|
||||
struct Layout {
|
||||
std::size_t size;
|
||||
std::align_val_t align;
|
||||
std::size_t align;
|
||||
};
|
||||
|
||||
// For the C++'s purpose, they are all the same
|
||||
|
@ -58,5 +60,93 @@ struct VOffset
|
|||
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
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue