mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-01 12:24:16 +00:00
[reorg]: Move api/sixtyfps-rs/sixtyfps-* into api/rs
This commit is contained in:
parent
2813441cd9
commit
842f75e653
95 changed files with 65 additions and 72 deletions
186
api/cpp/include/vtable.h
Normal file
186
api/cpp/include/vtable.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
// Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
||||
// SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <atomic>
|
||||
|
||||
namespace vtable {
|
||||
|
||||
template<typename T>
|
||||
struct VRefMut
|
||||
{
|
||||
const T *vtable;
|
||||
void *instance;
|
||||
};
|
||||
|
||||
struct Layout {
|
||||
std::size_t size;
|
||||
std::size_t align;
|
||||
};
|
||||
|
||||
// For the C++'s purpose, they are all the same
|
||||
template<typename T>
|
||||
using VRef = VRefMut<T>;
|
||||
template<typename T>
|
||||
using VBox = VRefMut<T>;
|
||||
|
||||
template<typename T>
|
||||
using Pin = T;
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
struct VBox {
|
||||
const T *vtable;
|
||||
void *instance;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct VRef {
|
||||
const T *vtable;
|
||||
const void *instance;
|
||||
};
|
||||
*/
|
||||
|
||||
struct AllowPin;
|
||||
|
||||
template<typename Base, typename T, typename Flag = void>
|
||||
struct VOffset
|
||||
{
|
||||
const T *vtable;
|
||||
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:
|
||||
VRcInner() : layout {} {}
|
||||
const VTable *vtable = &X::static_vtable;
|
||||
std::atomic<int> strong_ref = 1;
|
||||
std::atomic<int> weak_ref = 1;
|
||||
std::uint16_t data_offset = offsetof(VRcInner, data);
|
||||
union {
|
||||
X data;
|
||||
Layout layout;
|
||||
};
|
||||
|
||||
void *data_ptr() { return reinterpret_cast<char *>(this) + data_offset; }
|
||||
~VRcInner() = delete;
|
||||
};
|
||||
|
||||
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->vtable, &inner->data});
|
||||
layout.size += inner->data_offset;
|
||||
layout.align = std::max<size_t>(layout.align, alignof(VRcInner<VTable, Dyn>));
|
||||
inner->layout = layout;
|
||||
if (!--inner->weak_ref) {
|
||||
inner->vtable->dealloc(inner->vtable, reinterpret_cast<uint8_t*>(inner), 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;
|
||||
}
|
||||
/// Construct a new VRc holding an X.
|
||||
///
|
||||
/// The type X must have a static member `static_vtable` of type VTable
|
||||
template<typename ...Args> static VRc make(Args... args) {
|
||||
auto mem = ::operator new(sizeof(VRcInner<VTable, X>), static_cast<std::align_val_t>(alignof(VRcInner<VTable, X>)));
|
||||
auto inner = new (mem) VRcInner<VTable, X>;
|
||||
new (&inner->data) X(args...);
|
||||
return VRc(inner);
|
||||
}
|
||||
|
||||
const X* operator->() const {
|
||||
return &inner->data;
|
||||
}
|
||||
const X& operator*() const {
|
||||
return inner->data;
|
||||
}
|
||||
X* operator->() {
|
||||
return &inner->data;
|
||||
}
|
||||
X& operator*() {
|
||||
return inner->data;
|
||||
}
|
||||
|
||||
VRc<VTable, Dyn> into_dyn() const { return *reinterpret_cast<const VRc<VTable, Dyn> *>(this); }
|
||||
|
||||
VRef<VTable> borrow() const { return { inner->vtable, inner->data_ptr() }; }
|
||||
|
||||
friend bool operator==(const VRc &a, const VRc &b) {
|
||||
return a.inner == b.inner;
|
||||
}
|
||||
friend bool operator!=(const VRc &a, const VRc &b) {
|
||||
return a.inner != b.inner;
|
||||
}
|
||||
const VTable *vtable() const { return inner->vtable; }
|
||||
};
|
||||
|
||||
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->vtable, reinterpret_cast<uint8_t*>(inner), 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) };
|
||||
}
|
||||
|
||||
VWeak<VTable, Dyn> into_dyn() const { return *reinterpret_cast<const VWeak<VTable, Dyn> *>(this); }
|
||||
|
||||
friend bool operator==(const VWeak &a, const VWeak &b) {
|
||||
return a.inner == b.inner;
|
||||
}
|
||||
friend bool operator!=(const VWeak &a, const VWeak &b) {
|
||||
return a.inner != b.inner;
|
||||
}
|
||||
const VTable *vtable() const { return inner ? inner->vtable : nullptr; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
} //namespace vtable
|
||||
Loading…
Add table
Add a link
Reference in a new issue