Skip to content

Commit

Permalink
gh-581 Extracted non-templated code out of RefCounted
Browse files Browse the repository at this point in the history
  • Loading branch information
nolan-veed committed Oct 3, 2023
1 parent 8af74c6 commit b1a6180
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 51 deletions.
60 changes: 9 additions & 51 deletions src/internal_modules/roc_core/ref_counted.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
#define ROC_CORE_REF_COUNTED_H_

#include "roc_core/allocation_policy.h"
#include "roc_core/atomic.h"
#include "roc_core/noncopyable.h"
#include "roc_core/panic.h"
#include "roc_core/ref_counted_impl.h"

namespace roc {
namespace core {
Expand All @@ -26,7 +25,7 @@ namespace core {
//! reaches zero, the object is automatically destroyed.
//!
//! @tparam T defines the derived class.
//! @tparam AllocationPolicy defies destroy policy.
//! @tparam AllocationPolicy defines destroy policy.
//!
//! When reference counter becomes zero, AllocationPolicy::destroy() is invoked
//! by RefCounted to destroy itself.
Expand All @@ -42,79 +41,38 @@ class RefCounted : public NonCopyable<RefCounted<T, AllocationPolicy> >,
public:
//! Initialize.
RefCounted()
: AllocationPolicy()
, counter_(0) {
: AllocationPolicy() {
}

//! Initialize.
explicit RefCounted(const AllocationPolicy& policy)
: AllocationPolicy(policy)
, counter_(0) {
}

~RefCounted() {
if (!counter_.compare_exchange(0, -1)) {
roc_panic(
"ref counter:"
" attempt to destroy object that is in use, destroyed, or corrupted:"
" counter=%d",
(int)counter_);
}
: AllocationPolicy(policy) {
}

//! Get reference counter.
int getref() const {
const int current_counter = counter_;

if (current_counter < 0 || current_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or currupted object:"
" counter=%d",
(int)current_counter);
}

return current_counter;
return impl_.getref();
}

//! Increment reference counter.
void incref() const {
const int previous_counter = counter_++;

if (previous_counter < 0 || previous_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or currupted object"
" counter=%d",
(int)previous_counter);
}
impl_.incref();
}

//! Decrement reference counter.
//! @remarks
//! Destroys itself if reference counter becomes zero.
void decref() const {
const int previous_counter = counter_--;

if (previous_counter < 0 || previous_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or currupted object"
" counter=%d",
(int)previous_counter);
}
const int current_counter = impl_.decref();

if (previous_counter == 0) {
roc_panic("ref counter: unpaired incref/decref");
}

if (previous_counter == 1) {
if (current_counter == 0) {
const_cast<RefCounted&>(*this).destroy(
static_cast<T&>(const_cast<RefCounted&>(*this)));
}
}

private:
enum { MaxCounter = 100000 };

mutable Atomic<int> counter_;
RefCountedImpl impl_;
};

} // namespace core
Expand Down
67 changes: 67 additions & 0 deletions src/internal_modules/roc_core/ref_counted_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023 Roc Streaming authors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include "roc_core/ref_counted_impl.h"
#include "roc_core/panic.h"

namespace roc {
namespace core {

RefCountedImpl::RefCountedImpl()
: counter_(0) {
}

RefCountedImpl::~RefCountedImpl() {
if (!counter_.compare_exchange(0, -1)) {
roc_panic("ref counter:"
" attempt to destroy object that is in use, destroyed, or corrupted:"
" counter=%d",
(int)counter_);
}
}

int RefCountedImpl::getref() const {
const int current_counter = counter_;

if (current_counter < 0 || current_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or corrupted object:"
" counter=%d",
(int)current_counter);
}

return current_counter;
}

int RefCountedImpl::incref() const {
const int current_counter = ++counter_;

if (current_counter < 0 || current_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or corrupted object"
" counter=%d",
(int)current_counter);
}

return current_counter;
}

int RefCountedImpl::decref() const {
const int current_counter = --counter_;

if (current_counter < 0 || current_counter > MaxCounter) {
roc_panic("ref counter:"
" attempt to access destroyed or corrupted object"
" counter=%d",
(int)current_counter);
}
return current_counter;
}

} // namespace core
} // namespace roc
50 changes: 50 additions & 0 deletions src/internal_modules/roc_core/ref_counted_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Roc Streaming authors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

//! @file roc_core/ref_counted_impl.h
//! @brief Implementation class for reference counter.

#ifndef ROC_CORE_REF_COUNTED_IMPL_H_
#define ROC_CORE_REF_COUNTED_IMPL_H_

#include "roc_core/atomic.h"

namespace roc {
namespace core {

//! Implementation class for reference counter.
//!
//! Allows to increment and decrement reference counter.
class RefCountedImpl {
public:
//! Initialize.
RefCountedImpl();

~RefCountedImpl();

//! Get reference counter.
int getref() const;

//! Increment reference counter.
//! @returns reference counter value after incrementing.
int incref() const;

//! Decrement reference counter.
//! @returns reference counter value after decrementing.
int decref() const;

private:
enum { MaxCounter = 100000 };

mutable Atomic<int> counter_;
};

} // namespace core
} // namespace roc

#endif // ROC_CORE_REF_COUNTED_IMPL_H_

0 comments on commit b1a6180

Please sign in to comment.