PVData C++
8.0.9
Toggle main menu visibility
Loading...
Searching...
No Matches
misc
pv
debugPtr.h
1
/*
2
* Copyright information and license terms for this software can be
3
* found in the file LICENSE that is included with the distribution
4
*/
5
/* Author: Michael Davidsaver */
6
/* wrapper around shared_ptr which tracks backwards references.
7
* Can help to find ref. leaks, loops, and other exciting bugs.
8
* See comments in sharedPtr.h
9
*/
10
#ifndef DEBUGPTR_H
11
#define DEBUGPTR_H
12
13
#if __cplusplus<201103L
14
# error c++11 required
15
#endif
16
17
#include <
ostream
>
18
#include <
memory
>
19
#include <
set
>
20
21
#include <pv/epicsException.h>
22
23
#include <shareLib.h>
24
27
#define HAVE_SHOW_REFS
28
29
namespace
epics
{
30
namespace
debug {
31
32
struct
tracker;
33
class
shared_ptr_base
;
34
35
class
epicsShareClass ptr_base {
36
friend
class
shared_ptr_base;
37
template
<
typename
A>
38
friend
class
shared_ptr;
39
template
<
typename
A>
40
friend
class
weak_ptr;
41
protected
:
42
typedef
std::shared_ptr<tracker>
track_t;
43
track_t track;
44
45
ptr_base() noexcept : track() {}
46
ptr_base(
const
track_t& track) :track(track) {}
47
ptr_base(
const
ptr_base&) =
delete
;
48
ptr_base(ptr_base&&) =
delete
;
49
50
ptr_base&
operator=
(
const
ptr_base&) =
delete
;
51
52
public
:
53
typedef
std::set<const shared_ptr_base *>
ref_set_t;
54
void
show_refs(
std::ostream
&,
bool
self=
true
,
bool
weak=
false
)
const
;
55
void
spy_refs(ref_set_t&)
const
;
56
};
57
58
class
epicsShareClass weak_ptr_base :
public
ptr_base {
59
protected
:
60
weak_ptr_base() {}
61
weak_ptr_base(
const
track_t& track) :ptr_base(track) {}
62
};
63
64
class
epicsShareClass shared_ptr_base :
public
ptr_base {
65
protected
:
66
shared_ptr_base()
noexcept
67
#ifndef EXCEPT_USE_NONE
68
:m_stack(), m_depth(0)
69
#endif
70
{}
71
shared_ptr_base(
const
track_t& track) :ptr_base(track)
72
#ifndef EXCEPT_USE_NONE
73
,m_stack(), m_depth(0)
74
#endif
75
{}
76
~shared_ptr_base() {track_clear();}
77
78
// add ourselves to tracker
79
void
track_new();
80
// create new tracker if ptr!=nullptr, otherwise clear
81
void
track_new(
const
void
* ptr);
82
// copy tracker and add ourself
83
void
track_assign(
const
shared_ptr_base& o);
84
void
track_clear();
85
void
swap(shared_ptr_base& o);
86
void
snap_stack();
87
88
#ifndef EXCEPT_USE_NONE
89
void
*m_stack[EXCEPT_DEPTH];
90
int
m_depth;
// always <= EXCEPT_DEPTH
91
#endif
92
93
public
:
94
void
show_stack(
std::ostream
&)
const
;
95
};
96
97
98
99
template
<
typename
T>
100
class
shared_ptr
;
101
template
<
typename
T>
102
class
weak_ptr
;
103
template
<
class
Base>
104
class
enable_shared_from_this
;
105
106
template
<
typename
Store,
typename
Actual>
107
inline
void
108
do_enable_shared_from_this(
const
shared_ptr<Store>
& dest,
109
enable_shared_from_this<Actual>
* self
110
);
111
112
template
<
typename
T>
113
inline
void
114
do_enable_shared_from_this(
const
shared_ptr<T>
&, ...) {}
115
116
template
<
typename
T>
117
class
shared_ptr :
public
shared_ptr_base {
118
typedef ::std::shared_ptr<T> real_type;
119
120
real_type real;
121
122
template
<
typename
A>
123
friend
class
shared_ptr;
124
template
<
typename
A>
125
friend
class
weak_ptr;
126
127
// ctor for casts
128
shared_ptr(
const
real_type& r,
const
ptr_base::track_t& t)
129
:shared_ptr_base(t), real(r)
130
{track_new();}
131
public
:
132
typedef
typename
real_type::element_type
element_type;
133
typedef
weak_ptr<T> weak_type;
134
135
// new NULL
136
shared_ptr()
noexcept
{}
137
// copy existing same type
138
shared_ptr(
const
shared_ptr& o) :shared_ptr_base(o.track), real(o.real) {track_new();}
139
// copy existing of implicitly castable type
140
template
<
typename
A>
141
shared_ptr(
const
shared_ptr<A>& o) :shared_ptr_base(o.track), real(o.real) {track_new();}
142
143
// construct around new pointer
144
template
<
typename
A,
class
... Args>
145
explicit
shared_ptr(A* a, Args ... args) : shared_ptr_base(), real(a, args...) {
146
track_new(a);
147
do_enable_shared_from_this(*
this
, a);
148
}
149
150
// make strong ref from weak
151
template
<
typename
A>
152
shared_ptr(
const
weak_ptr<A>& o) :shared_ptr_base(o.track), real(o.real) {track_new();}
153
154
// takeover from unique_ptr
155
template
<
typename
A>
156
shared_ptr(
std::unique_ptr<A>
&& a) : shared_ptr_base(), real(a.release()) {track_new();}
157
158
~shared_ptr() {}
159
160
shared_ptr&
operator=
(
const
shared_ptr& o) {
161
if
(
this
!=&o) {
162
real = o.real;
163
track_assign(o);
164
}
165
return
*
this
;
166
}
167
template
<
typename
A>
168
shared_ptr&
operator=
(
const
shared_ptr<A>& o) {
169
if
(get()!=o.get()) {
170
real = o.real;
171
track_assign(o);
172
}
173
return
*
this
;
174
}
175
176
void
reset()
noexcept
{ real.reset(); track_clear(); }
177
template
<
typename
A,
class
... Args>
178
void
reset(A* a, Args ... args)
179
{
180
real.reset(a, args...);
181
track_new(a);
182
do_enable_shared_from_this(*
this
, a);
183
}
184
void
swap(shared_ptr &o)
noexcept
185
{
186
if
(
this
!=&o) {
187
real.swap(o.real);
188
shared_ptr_base::swap(o);
189
}
190
}
191
192
// proxy remaining to underlying shared_ptr
193
194
T* get()
const
noexcept
{
return
real.get(); }
195
typename
std::add_lvalue_reference<T>::type
operator*()
const
noexcept
{
return
*real; }
196
T* operator->()
const
noexcept
{
return
real.get(); }
197
long
use_count()
const
noexcept
{
return
real.use_count(); }
198
bool
unique()
const
noexcept
{
return
real.unique(); }
199
explicit
operator
bool()
const
noexcept
{
return
bool(real); }
200
201
bool
operator==(
const
shared_ptr<T>& o)
const
{
return
real==o.real; }
202
bool
operator!=(
const
shared_ptr<T>& o)
const
{
return
real!=o.real; }
203
bool
operator<(
const
shared_ptr<T>& o)
const
{
return
real<o.real; }
204
205
template
<
typename
A>
206
bool
owner_before(
const
shared_ptr<A>& o) {
return
real.owner_before(o); }
207
template
<
typename
A>
208
bool
owner_before(
const
weak_ptr<A>& o) {
return
real.owner_before(o); }
209
210
template
<
typename
TO,
typename
FROM>
211
friend
212
shared_ptr<TO> static_pointer_cast(
const
shared_ptr<FROM>& src);
213
template
<
typename
TO,
typename
FROM>
214
friend
215
shared_ptr<TO> const_pointer_cast(
const
shared_ptr<FROM>& src);
216
template
<
typename
TO,
typename
FROM>
217
friend
218
shared_ptr<TO> dynamic_pointer_cast(
const
shared_ptr<FROM>& src);
219
template
<
typename
Store,
typename
Actual>
220
friend
void
221
do_enable_shared_from_this(
const
shared_ptr<Store>& dest,
222
enable_shared_from_this<Actual>
* self
223
);
224
};
225
226
template
<
typename
TO,
typename
FROM>
227
shared_ptr<TO>
static_pointer_cast(
const
shared_ptr<FROM>
& src) {
228
return
shared_ptr<TO>
(
std::static_pointer_cast<TO>
(src.real), src.track);
229
}
230
231
template
<
typename
TO,
typename
FROM>
232
shared_ptr<TO>
const_pointer_cast
(
const
shared_ptr<FROM>& src) {
233
return
shared_ptr<TO>(
std::const_pointer_cast<TO>
(src.real), src.track);
234
}
235
236
template
<
typename
TO,
typename
FROM>
237
shared_ptr<TO>
dynamic_pointer_cast
(
const
shared_ptr<FROM>& src) {
238
return
shared_ptr<TO>(
std::dynamic_pointer_cast<TO>
(src.real), src.track);
239
}
240
241
template
<
typename
T>
242
class
weak_ptr :
public
weak_ptr_base {
243
typedef ::std::weak_ptr<T> real_type;
244
245
real_type real;
246
247
template
<
typename
A>
248
friend
class
shared_ptr;
249
template
<
typename
A>
250
friend
class
weak_ptr;
251
252
public
:
253
typedef
typename
real_type::element_type element_type;
254
typedef
weak_ptr<T> weak_type;
255
256
// new NULL
257
weak_ptr()
noexcept
{}
258
// copy existing same type
259
weak_ptr(
const
weak_ptr& o) :weak_ptr_base(o.track), real(o.real) {}
260
// copy existing of similar type
261
template
<
typename
A>
262
weak_ptr(
const
weak_ptr<A>& o) :weak_ptr_base(o.track), real(o.real) {}
263
264
// create week ref from strong ref
265
template
<
typename
A>
266
weak_ptr(
const
shared_ptr<A>& o) :weak_ptr_base(o.track), real(o.real) {}
267
268
~weak_ptr() {}
269
270
weak_ptr&
operator=
(
const
weak_ptr& o) {
271
if
(
this
!=&o) {
272
real = o.real;
273
track = o.track;
274
}
275
return
*
this
;
276
}
277
template
<
typename
A>
278
weak_ptr&
operator=
(
const
shared_ptr<A>& o) {
279
real = o.real;
280
track = o.track;
281
return
*
this
;
282
}
283
284
shared_ptr<T> lock()
const
noexcept
{
return
shared_ptr<T>(real.lock(), track); }
285
void
reset()
noexcept
{ track.reset(); real.reset(); }
286
287
long
use_count()
const
noexcept
{
return
real.use_count(); }
288
bool
unique()
const
noexcept
{
return
real.unique(); }
289
bool
expired()
const
noexcept
{
return
real.expired(); }
290
};
291
292
template
<
class
Base>
293
class
enable_shared_from_this
{
294
mutable
weak_ptr<Base>
xxInternalSelf;
295
296
template
<
typename
Store,
typename
Actual>
297
friend
298
void
299
do_enable_shared_from_this(
const
shared_ptr<Store>
& dest,
300
enable_shared_from_this<Actual>
* self
301
);
302
public
:
303
shared_ptr<Base>
shared_from_this()
const
{
304
return
shared_ptr<Base>
(xxInternalSelf);
305
}
306
};
307
308
template
<
typename
Store,
typename
Actual>
309
inline
void
310
do_enable_shared_from_this(
const
shared_ptr<Store>
& dest,
311
enable_shared_from_this<Actual>
* self
312
)
313
{
314
shared_ptr<Actual>
actual(dynamic_pointer_cast<Actual>(dest));
315
if
(!actual)
316
throw
std::logic_error
(
"epics::debug::enabled_shared_from_this fails"
);
317
self->xxInternalSelf = actual;
318
}
319
320
template
<
typename
T>
321
inline
std::ostream
&
operator<<
(
std::ostream
& strm,
const
shared_ptr<T>& ptr)
322
{
323
strm<<ptr.get();
324
return
strm;
325
}
326
327
}}
// namespace epics::debug
328
#endif
// DEBUGPTR_H
memory
ostream
set
operator=
constexpr complex< _Tp > & operator=(const _Tp &)
std::ostream
basic_ostream< char > ostream
dynamic_pointer_cast
__shared_ptr< _Tp, _Lp > dynamic_pointer_cast(const __shared_ptr< _Tp1, _Lp > &__r) noexcept
operator<<
basic_ostream< _CharT, _Traits > & operator<<(basic_ostream< _CharT, _Traits > &__os, const basic_string< _CharT, _Traits, _Alloc > &__str)
std::static_pointer_cast
__shared_ptr< _Tp, _Lp > static_pointer_cast(const __shared_ptr< _Tp1, _Lp > &__r) noexcept
const_pointer_cast
__shared_ptr< _Tp, _Lp > const_pointer_cast(const __shared_ptr< _Tp1, _Lp > &__r) noexcept
std::logic_error
std::add_lvalue_reference
std::shared_ptr
std::shared_ptr< T >::element_type
typename __shared_ptr< _Tp >::element_type element_type
std::set
std::unique_ptr
epics::debug::enable_shared_from_this
Definition
debugPtr.h:293
epics::debug::shared_ptr_base
Definition
debugPtr.h:64
epics::debug::shared_ptr
Definition
debugPtr.h:117
epics::debug::weak_ptr
Definition
debugPtr.h:242
epics
epics
Definition
convert.h:21
Generated on
for PVData C++ by
1.17.0