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