/* LICENSE BEGIN This file is part of the SixtyFPS Project -- https://sixtyfps.io Copyright (c) 2020 Olivier Goffart Copyright (c) 2020 Simon Hausmann SPDX-License-Identifier: GPL-3.0-only This file is also available under commercial licensing terms. Please contact info@sixtyfps.io for more information. LICENSE END */ #pragma once #include "sixtyfps_sharedarray_internal.h" #include namespace sixtyfps { template struct SharedArray { SharedArray() : inner(const_cast(reinterpret_cast( cbindgen_private::sixtyfps_shared_array_empty()))) { } SharedArray(const SharedArray &other) : inner(other.inner) { if (inner->refcount > 0) { ++inner->refcount; } } ~SharedArray() { drop(); } SharedArray &operator=(const SharedArray &other) { if (other.inner == inner) { return *this; } drop(); inner = other.inner; if (inner->refcount > 0) { ++inner->refcount; } return *this; } SharedArray &operator=(SharedArray &&other) { std::swap(inner, other.inner); return *this; } const T *begin() const { return reinterpret_cast(inner + 1); } const T *end() const { return begin() + inner->size; } private: 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(inner), sizeof(SharedArrayHeader) + inner->capacity * sizeof(T), alignof(SharedArrayHeader)); } } #if !defined(DOXYGEN) // Unfortunately, this cannot be generated by cbindgen because std::atomic is not understood struct SharedArrayHeader { std::atomic 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; #endif }; }