]>
Commit | Line | Data |
---|---|---|
4299f876 AR |
1 | #ifndef SQUID_CBC_POINTER_H |
2 | #define SQUID_CBC_POINTER_H | |
3 | ||
4 | #include "base/TextException.h" | |
5 | #include "cbdata.h" | |
6 | ||
7 | /** | |
8 | \ingroup CBDATAAPI | |
9 | * | |
4cb2536f | 10 | * Safely points to a cbdata-protected class (cbc), such as an AsyncJob. |
4299f876 AR |
11 | * When a cbc we communicate with disappears without |
12 | * notice or a notice has not reached us yet, this class prevents | |
13 | * dereferencing the pointer to the gone cbc object. | |
14 | */ | |
15 | template<class Cbc> | |
16 | class CbcPointer | |
17 | { | |
18 | public: | |
19 | CbcPointer(); // a nil pointer | |
20 | CbcPointer(Cbc *aCbc); | |
21 | CbcPointer(const CbcPointer &p); | |
22 | ~CbcPointer(); | |
23 | ||
24 | Cbc *raw() const; ///< a temporary raw Cbc pointer; may be invalid | |
25 | Cbc *get() const; ///< a temporary valid raw Cbc pointer or NULL | |
26 | Cbc &operator *() const; ///< a valid Cbc reference or exception | |
27 | Cbc *operator ->() const; ///< a valid Cbc pointer or exception | |
28 | ||
29 | // no bool operator because set() != valid() | |
30 | bool set() const { return cbc != NULL; } ///< was set but may be invalid | |
31 | Cbc *valid() const { return get(); } ///< was set and is valid | |
32 | bool operator !() const { return !valid(); } ///< invalid or was not set | |
33 | bool operator ==(const CbcPointer<Cbc> &o) const { return lock == o.lock; } | |
34 | ||
35 | CbcPointer &operator =(const CbcPointer &p); | |
36 | ||
37 | /// support converting a child cbc pointer into a parent cbc pointer | |
38 | template <typename Other> | |
39 | CbcPointer(const CbcPointer<Other> &o): cbc(o.raw()), lock(NULL) { | |
40 | if (o.valid()) | |
41 | lock = cbdataReference(o->toCbdata()); | |
42 | } | |
43 | ||
44 | /// support assigning a child cbc pointer to a parent cbc pointer | |
45 | template <typename Other> | |
46 | CbcPointer &operator =(const CbcPointer<Other> &o) { | |
596e3d5f | 47 | if (this != &o) { // assignment to self |
6cb816e5 A |
48 | clear(); |
49 | cbc = o.raw(); // so that set() is accurate | |
50 | if (o.valid()) | |
51 | lock = cbdataReference(o->toCbdata()); | |
596e3d5f | 52 | } |
4299f876 AR |
53 | return *this; |
54 | } | |
55 | ||
56 | void clear(); ///< make pointer not set; does not invalidate cbdata | |
57 | ||
58 | std::ostream &print(std::ostream &os) const; | |
59 | ||
60 | private: | |
61 | Cbc *cbc; // a possibly invalid pointer to a cbdata class | |
62 | void *lock; // a valid pointer to cbc's cbdata or nil | |
63 | }; | |
64 | ||
65 | template <class Cbc> | |
66 | inline | |
4cb2536f A |
67 | std::ostream &operator <<(std::ostream &os, const CbcPointer<Cbc> &p) |
68 | { | |
4299f876 AR |
69 | return p.print(os); |
70 | } | |
71 | ||
72 | // inlined methods | |
73 | ||
74 | template<class Cbc> | |
75 | CbcPointer<Cbc>::CbcPointer(): cbc(NULL), lock(NULL) | |
76 | { | |
77 | } | |
78 | ||
79 | template<class Cbc> | |
80 | CbcPointer<Cbc>::CbcPointer(Cbc *aCbc): cbc(aCbc), lock(NULL) | |
81 | { | |
82 | if (cbc) | |
83 | lock = cbdataReference(cbc->toCbdata()); | |
84 | } | |
85 | ||
86 | template<class Cbc> | |
87 | CbcPointer<Cbc>::CbcPointer(const CbcPointer &d): cbc(d.cbc), lock(NULL) | |
88 | { | |
89 | if (d.lock && cbdataReferenceValid(d.lock)) | |
90 | lock = cbdataReference(d.lock); | |
91 | } | |
92 | ||
93 | template<class Cbc> | |
94 | CbcPointer<Cbc>::~CbcPointer() | |
95 | { | |
96 | clear(); | |
97 | } | |
98 | ||
99 | template<class Cbc> | |
100 | CbcPointer<Cbc> &CbcPointer<Cbc>::operator =(const CbcPointer &d) | |
101 | { | |
596e3d5f | 102 | if (this != &d) { // assignment to self |
6cb816e5 A |
103 | clear(); |
104 | cbc = d.cbc; | |
105 | if (d.lock && cbdataReferenceValid(d.lock)) | |
106 | lock = cbdataReference(d.lock); | |
596e3d5f | 107 | } |
4299f876 AR |
108 | return *this; |
109 | } | |
110 | ||
111 | template<class Cbc> | |
112 | void | |
113 | CbcPointer<Cbc>::clear() | |
114 | { | |
115 | cbdataReferenceDone(lock); // lock may be nil before and will be nil after | |
116 | cbc = NULL; | |
117 | } | |
118 | ||
119 | template<class Cbc> | |
120 | Cbc * | |
121 | CbcPointer<Cbc>::raw() const | |
122 | { | |
123 | return cbc; | |
124 | } | |
125 | ||
126 | template<class Cbc> | |
127 | Cbc * | |
128 | CbcPointer<Cbc>::get() const | |
129 | { | |
130 | return (lock && cbdataReferenceValid(lock)) ? cbc : NULL; | |
131 | } | |
132 | ||
133 | template<class Cbc> | |
134 | Cbc & | |
135 | CbcPointer<Cbc>::operator *() const | |
136 | { | |
137 | Cbc *c = get(); | |
ca603620 | 138 | assert(c); |
4299f876 AR |
139 | return *c; |
140 | } | |
141 | ||
142 | template<class Cbc> | |
143 | Cbc * | |
144 | CbcPointer<Cbc>::operator ->() const | |
145 | { | |
146 | Cbc *c = get(); | |
ca603620 | 147 | assert(c); |
4299f876 AR |
148 | return c; |
149 | } | |
150 | ||
151 | template <class Cbc> | |
4cb2536f A |
152 | std::ostream &CbcPointer<Cbc>::print(std::ostream &os) const |
153 | { | |
4299f876 AR |
154 | return os << cbc << '/' << lock; |
155 | } | |
156 | ||
4299f876 | 157 | #endif /* SQUID_CBC_POINTER_H */ |