]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/RefCount.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / base / RefCount.h
1 /*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section -- Refcount allocator */
10
11 #ifndef SQUID_REFCOUNT_H_
12 #define SQUID_REFCOUNT_H_
13
14 // reference counting requires the Lock API on base classes
15 #include "base/Lock.h"
16
17 #include <iostream>
18
19 /**
20 * Template for Reference Counting pointers.
21 *
22 * Objects of type 'C' must inherit from 'RefCountable' in base/Lock.h
23 * which provides the locking interface used by reference counting.
24 */
25 template <class C>
26 class RefCount
27 {
28
29 public:
30 RefCount () : p_ (NULL) {}
31
32 RefCount (C const *p) : p_(p) { reference (*this); }
33
34 ~RefCount() {
35 dereference();
36 }
37
38 RefCount (const RefCount &p) : p_(p.p_) {
39 reference (p);
40 }
41
42 RefCount (RefCount &&p) : p_(std::move(p.p_)) {
43 p.p_=NULL;
44 }
45
46 /// Base::Pointer = Derived::Pointer
47 template <class Other>
48 RefCount(const RefCount<Other> &p): p_(p.getRaw()) {
49 reference(*this);
50 }
51
52 RefCount& operator = (const RefCount& p) {
53 // DO NOT CHANGE THE ORDER HERE!!!
54 // This preserves semantics on self assignment
55 C const *newP_ = p.p_;
56 reference(p);
57 dereference(newP_);
58 return *this;
59 }
60
61 RefCount& operator = (RefCount&& p) {
62 if (this != &p) {
63 dereference(p.p_);
64 p.p_ = NULL;
65 }
66 return *this;
67 }
68
69 explicit operator bool() const { return p_; }
70
71 bool operator !() const { return !p_; }
72
73 C * operator-> () const {return const_cast<C *>(p_); }
74
75 C & operator * () const {
76 assert(p_);
77 return *const_cast<C *>(p_);
78 }
79
80 C * getRaw() const { return const_cast<C *>(p_); }
81
82 bool operator == (const RefCount& p) const {
83 return p.p_ == p_;
84 }
85
86 bool operator != (const RefCount &p) const {
87 return p.p_ != p_;
88 }
89
90 private:
91 void dereference(C const *newP = NULL) {
92 /* Setting p_ first is important:
93 * we may be freed ourselves as a result of
94 * delete p_;
95 */
96 C const (*tempP_) (p_);
97 p_ = newP;
98
99 if (tempP_ && tempP_->unlock() == 0)
100 delete tempP_;
101 }
102
103 void reference (const RefCount& p) {
104 if (p.p_)
105 p.p_->lock();
106 }
107
108 C const *p_;
109
110 };
111
112 template <class C>
113 inline std::ostream &operator <<(std::ostream &os, const RefCount<C> &p)
114 {
115 if (p != NULL)
116 return os << p.getRaw() << '*' << p->LockCount();
117 else
118 return os << "NULL";
119 }
120
121 #endif /* SQUID_REFCOUNT_H_ */
122