mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-27 20:42:25 +00:00
C++: Make a model based on a SharedArray like in C++
And make the SharedArray editable
This commit is contained in:
parent
2ae4f1757b
commit
4da5f5eee6
3 changed files with 95 additions and 11 deletions
|
@ -48,15 +48,67 @@ struct SharedArray
|
|||
return *this;
|
||||
}
|
||||
|
||||
const T *begin() const {
|
||||
const T *cbegin() const {
|
||||
return reinterpret_cast<const T *>(inner + 1);
|
||||
}
|
||||
|
||||
const T *end() const {
|
||||
const T *cend() const {
|
||||
return cbegin() + inner->size;
|
||||
}
|
||||
|
||||
const T *begin() const { return cbegin(); }
|
||||
const T *end() const { return cend(); }
|
||||
|
||||
T *begin() {
|
||||
detach(inner->size);
|
||||
return reinterpret_cast<T *>(inner + 1);
|
||||
}
|
||||
|
||||
T *end() {
|
||||
detach(inner->size);
|
||||
return begin() + inner->size;
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return inner->size;
|
||||
}
|
||||
|
||||
T &operator[](std::size_t index) {
|
||||
return begin()[index];
|
||||
}
|
||||
const T &operator[](std::size_t index) const {
|
||||
return begin()[index];
|
||||
}
|
||||
|
||||
const T &at(std::size_t index) const {
|
||||
return begin()[index];
|
||||
}
|
||||
|
||||
void push_back(const T &value) {
|
||||
detach(inner->size + 1);
|
||||
new (end()) T(value);
|
||||
inner->size++;
|
||||
}
|
||||
void push_back(T &&value) {
|
||||
detach(inner->size + 1);
|
||||
new (end()) T(std::move(value));
|
||||
inner->size++;
|
||||
}
|
||||
|
||||
private:
|
||||
void detach(std::size_t expected_capacity) {
|
||||
if (inner->refcount == 1 && expected_capacity <= inner->capacity) {
|
||||
return;
|
||||
}
|
||||
auto new_array = SharedArray::with_capacity(expected_capacity);
|
||||
auto old_data = reinterpret_cast<const T *>(inner + 1);
|
||||
auto new_data = reinterpret_cast<T *>(new_array.inner + 1);
|
||||
for (std::size_t i = 0; i < inner->size; ++i) {
|
||||
new (new_data+i) T(old_data[i]);
|
||||
new_array.inner->size++;
|
||||
}
|
||||
*this = std::move(new_array);
|
||||
}
|
||||
|
||||
void drop() {
|
||||
if (inner->refcount > 0 && (--inner->refcount) == 0) {
|
||||
|
@ -71,6 +123,13 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
static SharedArray with_capacity(std::size_t capacity) {
|
||||
auto mem = cbindgen_private::sixtyfps_shared_array_allocate(
|
||||
sizeof(SharedArrayHeader) + capacity * sizeof(T),
|
||||
alignof(SharedArrayHeader));
|
||||
return SharedArray(new (mem) SharedArrayHeader{ {1}, 0, capacity });
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN)
|
||||
// Unfortunately, this cannot be generated by cbindgen because std::atomic is not understood
|
||||
struct SharedArrayHeader {
|
||||
|
@ -80,6 +139,7 @@ private:
|
|||
};
|
||||
static_assert(alignof(T) <= alignof(SharedArrayHeader), "Not yet supported because we would need to add padding");
|
||||
SharedArrayHeader *inner;
|
||||
explicit SharedArray(SharedArrayHeader *inner) : inner(inner) {}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue