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