Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
Loading...
Searching...
No Matches
ref_counted.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Roc Streaming authors
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8
9//! @file roc_core/ref_counted.h
10//! @brief Base class for reference counted object.
11
12#ifndef ROC_CORE_REF_COUNTED_H_
13#define ROC_CORE_REF_COUNTED_H_
14
16#include "roc_core/atomic.h"
18#include "roc_core/panic.h"
19
20namespace roc {
21namespace core {
22
23//! Base class for reference counted object.
24//!
25//! Allows to increment and decrement reference counter. When the counter
26//! reaches zero, the object is automatically destroyed.
27//!
28//! @tparam T defines the derived class.
29//! @tparam AllocationPolicy defies destroy policy.
30//!
31//! When reference counter becomes zero, AllocationPolicy::destroy() is invoked
32//! by RefCounted to destroy itself.
33//!
34//! Inherits AllocationPolicy to make its methods available in the derived class.
35//!
36//! Thread-safe.
37template <class T, class AllocationPolicy>
38class RefCounted : public NonCopyable<RefCounted<T, AllocationPolicy> >,
39 protected AllocationPolicy {
40public:
41 //! Initialization with default allocation policy.
43 : AllocationPolicy()
44 , counter_(0) {
45 }
46
47 //! Initialization with arbitrary allocation policy.
48 explicit RefCounted(const AllocationPolicy& policy)
49 : AllocationPolicy(policy)
50 , counter_(0) {
51 }
52
53 ~RefCounted() {
54 if (!counter_.compare_exchange(0, -1)) {
55 roc_panic("ref counter: attempt to destroy object that is still in use: "
56 "counter=%d",
57 (int)counter_);
58 }
59 }
60
61 //! Get reference counter.
62 long getref() const {
63 return counter_;
64 }
65
66 //! Increment reference counter.
67 void incref() const {
68 const int previous_counter = counter_++;
69
70 if (previous_counter < 0) {
71 roc_panic("ref counter: attempt to call acquire on destroyed object");
72 }
73 }
74
75 //! Decrement reference counter.
76 //! @remarks
77 //! Destroys itself if reference counter becomes zero.
78 void decref() const {
79 const int previous_counter = counter_--;
80
81 if (previous_counter < 0) {
82 roc_panic("ref counter: attempt to call release on destroyed object");
83 }
84
85 if (previous_counter == 0) {
86 roc_panic("ref counter: attempt to call release without acquire");
87 }
88
89 if (previous_counter == 1) {
90 const_cast<RefCounted&>(*this).destroy(
91 static_cast<T&>(const_cast<RefCounted&>(*this)));
92 }
93 }
94
95private:
96 mutable Atomic<int> counter_;
97};
98
99} // namespace core
100} // namespace roc
101
102#endif // ROC_CORE_REF_COUNTED_H_
Allocation policies.
Atomic.
Atomic integer. Provides sequential consistency. For a fine-grained memory order control,...
Definition atomic.h:26
bool compare_exchange(T exp, T des)
Atomic compare-and-swap.
Definition atomic.h:44
Base class for non-copyable objects.
Definition noncopyable.h:23
Base class for reference counted object.
Definition ref_counted.h:39
void incref() const
Increment reference counter.
Definition ref_counted.h:67
RefCounted(const AllocationPolicy &policy)
Initialization with arbitrary allocation policy.
Definition ref_counted.h:48
long getref() const
Get reference counter.
Definition ref_counted.h:62
RefCounted()
Initialization with default allocation policy.
Definition ref_counted.h:42
void decref() const
Decrement reference counter.
Definition ref_counted.h:78
Root namespace.
Non-copyable object.
Panic.
#define roc_panic(...)
Print error message and terminate program gracefully.
Definition panic.h:50