22 ensure(count > 0,
"DOUBLE RELEASE DETECTED!");
27 u64 val() {
return count; }
30 enum class StrongReleaseAction {
37 struct ThreadLocalRefCount {
39 u64 strongCounter = 1;
42 bool acquireStrong() {
43 if (strongCounter == 0 || value ==
nullptr) {
51 if (strongCounter == 0 && weakCounter == 0) {
58 StrongReleaseAction releaseStrong() {
59 ensure(strongCounter > 0,
"Double release detected");
61 if (strongCounter > 0) {
62 return StrongReleaseAction::NONE;
64 else if (weakCounter == 0) {
65 return StrongReleaseAction::CLEANUP_RC;
68 return StrongReleaseAction::CLEANUP_VAR_ONLY;
73 ensure(weakCounter > 0,
"Double release detected");
75 return weakCounter == 0 && strongCounter == 0;
107 impl::ThreadLocalRefCount<T> *
rc =
nullptr;
127 if (
rc->releaseWeak()) {
135 [[nodiscard]]
bool valid()
const {
return rc !=
nullptr; }
140 [[nodiscard]]
operator bool()
const {
return valid(); }
147 if (!
rc->acquireWeak()) {
156 impl::ThreadLocalRefCount<T> *
rc =
nullptr;
184 return rc == other.
rc;
189 if (other ==
nullptr &&
rc ==
nullptr) {
193 return rc->value == other;
198 if (other ==
nullptr &&
rc ==
nullptr) {
202 return rc->value == other;
206 [[nodiscard]]
bool valid()
const {
return rc !=
nullptr &&
rc->value !=
nullptr; }
209 [[nodiscard]]
operator bool()
const {
return valid(); }
218 template<
typename... Args>
225 return valRes.
error();
227 T* val = valRes.
value();
229 auto rcRes = alloc.
create<impl::ThreadLocalRefCount<T>>();
230 if (rcRes.is_error()) {
245 if (!
rc->acquireStrong()) {
262 switch (impl::StrongReleaseAction action =
rc->releaseStrong()) {
263 case impl::StrongReleaseAction::NONE:
265 case impl::StrongReleaseAction::CLEANUP_RC:
270 case impl::StrongReleaseAction::CLEANUP_VAR_ONLY:
288 if (!
rc->acquireWeak()) {
298 if (!
rc->acquireStrong()) {
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Success< void > success()
Creates a successful void Result object.
Error< Underlying > error(Underlying err)
Creates an error.
uint64_t u64
Alias for 64-bit unsigned ints.
Core library for C++ with Zig-related functionality.
RcError
Error for thread-local reference counting.
Represents a memory allocator Exact behavior depends on the underlying VTable used Should use the a_*...
Result< T *, AllocationError > create(Args... args)
Allocates some block of memory with an allocator with a known type Will pass arguments to the constru...
void destroy(T *&ptr)
Destroys an object allocated by this allocator by calling the destructor and freeing memory.
Thread-local reference counted pointer Not thread safe, don't share Reference counting for cleaning u...
void deinit(Allocator &alloc)
Same as release.
T * operator->()
Dereferences pointer.
bool operator==(const T *other) const
Compares to a pointer.
Result< WeakRc< T >, RcError > weak()
Attempts to get a weak reference.
bool operator==(T *other) const
Compares to a pointer.
T & operator*()
Dereferences pointer.
Result< void, AllocationError > init(Allocator &alloc, Args... args)
Initializes a reference counter to point to a new entity.
const T & operator*() const
Dereferences pointer.
const T * operator->() const
Dereferences pointer.
bool operator==(const Rc &other) const
Compares to a pointer.
void release(Allocator &alloc)
Releases a reference.
bool valid() const
Checks if is valid.
impl::ThreadLocalRefCount< T > * rc
Result< Rc, RcError > acquire()
Tries to acquire another strong reference Will return either another strong reference or an error.
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
T value() const noexcept
Checks if is a successful Result (aka.
bool is_error() const noexcept
Checks if is an error Result.
ErrVal error() const noexcept
Returns the associated error Fails if there is no error;.
Thread-local weak reference counted pointer Not thread safe, don't share Does not hold lifetime.
Result< WeakRc, RcError > copy()
Tries to copy a weak reference.
Result< Rc< T >, RcError > obtain(Allocator &alloc)
Tries to obtain a strong reference May error if could not obtain (e.g.
void deinit(Allocator &alloc)
Deinitializes a weak pointer Will decrement weak count and may clean up counter.
impl::ThreadLocalRefCount< T > * rc
bool valid() const
Checks if weak reference is valid.