Change the implementation of SharedArray so that it can destruct its contents

This commit is contained in:
Olivier Goffart 2020-09-04 14:04:06 +02:00
parent e19ad3006a
commit c8fa3354be
3 changed files with 221 additions and 113 deletions

View file

@ -9,6 +9,7 @@
LICENSE END */
#pragma once
#include "sixtyfps_sharedarray_internal.h"
#include <atomic>
namespace sixtyfps {
@ -16,26 +17,29 @@ template<typename T>
struct SharedArray
{
SharedArray()
{
cbindgen_private::sixtyfps_shared_array_new_null(reinterpret_cast<SharedArray<uint8_t> *>(this));
}
: inner(const_cast<SharedArrayHeader*>(reinterpret_cast<const SharedArrayHeader*>(
cbindgen_private::sixtyfps_shared_array_empty())))
{ }
SharedArray(const SharedArray &other)
: inner(other.inner)
{
cbindgen_private::sixtyfps_shared_array_clone(
reinterpret_cast<SharedArray<uint8_t> *>(this),
reinterpret_cast<const SharedArray<uint8_t> *>(&other));
if (inner->refcount > 0) {
++inner->refcount;
}
}
~SharedArray()
{
cbindgen_private::sixtyfps_shared_array_drop(reinterpret_cast<SharedArray<uint8_t> *>(this));
drop();
}
SharedArray &operator=(const SharedArray &other)
{
cbindgen_private::sixtyfps_shared_array_drop(reinterpret_cast<SharedArray<uint8_t> *>(this));
cbindgen_private::sixtyfps_shared_array_clone(
reinterpret_cast<SharedArray<uint8_t> *>(this),
reinterpret_cast<const SharedArray<uint8_t> *>(&other));
if (other.inner == inner) { return *this; }
drop();
inner = other.inner;
if (inner->refcount > 0) {
++inner->refcount;
}
return *this;
}
SharedArray &operator=(SharedArray &&other)
@ -44,7 +48,36 @@ struct SharedArray
return *this;
}
const T *begin() const {
return reinterpret_cast<const T *>(inner + 1);
}
const T *end() const {
return begin() + inner->size;
}
private:
void *inner; // opaque
void drop() {
if (inner->refcount > 0 && (--inner->refcount) == 0) {
auto b = begin(), e = end();
for (auto it = b; it < e; ++it) {
it->~T();
}
}
cbindgen_private::sixtyfps_shared_array_free(
reinterpret_cast<uint8_t *>(inner),
sizeof(SharedArrayHeader) + inner->capacity * sizeof(T),
alignof(SharedArrayHeader));
}
// Unfortunately, this cannot be generated by cbindgen because std::atomic is not understood
struct SharedArrayHeader {
std::atomic<std::intptr_t> refcount;
std::size_t size;
std::size_t capacity;
};
static_assert(alignof(T) <= alignof(SharedArrayHeader), "Not yet supported because we would need to add padding");
SharedArrayHeader *inner;
};
}