-
Notifications
You must be signed in to change notification settings - Fork 40
/
SmartPointer.h
177 lines (159 loc) · 6.46 KB
/
SmartPointer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**************************************************************
* Copyright (c) 2010, Dynamic Network Services, Inc.
* Jake Montgomery (jmontgomery@dyn.com) & Tom Daly (tom@dyn.com)
* Distributed under the FreeBSD License - see LICENSE
***************************************************************/
// Base header for various "smart" pointer type classes.
#pragma once
#include <stdio.h>
namespace openbfdd
{
/**
* RIAA base class for self deleting types that use a value besides NULL for
* empty. T Must have simple copy semantics & compare semantic for
* nullcomapreval
*
*/
template <typename T, T nullval, void (*freeFn)(T)> class RiaaBase
{
public:
T val;
RiaaBase() : val(nullval) {}
RiaaBase(const T val) : val(val) {}
~RiaaBase() {Dispose();}
operator T() const { return val;}
T operator=(T newval) {Dispose();val = newval; return newval;}
bool operator==(T cmp) const {return val == cmp;}
T Detach() {T old = val; val = nullval;return old;} // detach without freeing
void Dispose() {if (!isNull()) freeFn(val);val=nullval;}
bool IsValid() const {return !isNull();}
protected:
bool isNull() const {return val==nullval;}
private:
RiaaBase& operator=(RiaaBase<T, nullval, freeFn> &src); // don't want two RiaaBase freeing the same object
RiaaBase(const RiaaBase<T, nullval, freeFn> &src); // never use this.
};
/**
* RIAA base class for self deleting pointer types that use NULL for empty. T
* Must have simple copy semantics & compare semantics.
*
* (We need a separate template class, because NULL is not allowed as a template
* parameter.)
*/
template <typename T, void (*freeFn)(T*)> class RiaaNullBase
{
public:
T* val;
RiaaNullBase() : val(NULL) {}
RiaaNullBase( T *val) : val(val) {}
~RiaaNullBase() {Dispose();}
operator T*() const { return val;}
T* operator=(T* newval) {Dispose();val = newval; return newval;}
bool operator==(T* cmp) const {return val == cmp;}
T* Detach() {T* old = val; val = NULL;return old;} // detach without freeing
void Dispose() {if (!isNull()) freeFn(val);val=NULL;}
bool IsValid() const {return !isNull();}
T* operator->() { return val;}
protected:
bool isNull() const {return val==NULL;}
private:
RiaaNullBase& operator=(RiaaNullBase<T, freeFn> &src) ; // don't want two RiaaNullBase freeing the same object
RiaaNullBase(const RiaaNullBase<T, freeFn> &src); // never use this.
};
/**
* RAII class for file descriptors.
*
*/
void CloseFileDescriptor(int val);
typedef RiaaBase<int, -1, CloseFileDescriptor> FileDescriptor;
/**
* RAII class for FILE* handles.
*
*/
void CloseFileHandle(FILE *val);
typedef RiaaNullBase<FILE, CloseFileHandle> FileHandle;
/**
* RIAA class for simple array allocated with new or new[]
*/
template <typename T> void FreeFree(T *val) {free(val);}
template <typename T> void FreeArray(T *val) {delete[] val;}
template <typename T> void FreeDelete(T *val) {delete val;}
template <typename T> struct Riaa
{
typedef RiaaNullBase<T, FreeArray<T> > DeleteArray;
typedef RiaaNullBase<T, FreeDelete<T> > Delete;
typedef RiaaNullBase<T, FreeFree<T> > Free;
};
/**
* RIAA class for self deleting pointer types that use NULL for empty, that
* calls a delete function on a class. T Must have simple copy semantics &
* compare semantics.
*
* (We need a separate template class, because NULL is not allowed as a template
* parameter.)
*/
template <typename T, typename C, void (C::*freeFn)(T*)> class RiaaClassCall
{
public:
T* val;
C* myClass;
RiaaClassCall(C* myClass) : val(NULL), myClass(myClass) {}
RiaaClassCall(const T* val, C* myClass) : val(val), myClass(myClass) {}
~RiaaClassCall() {Dispose();}
operator T*() const { return val;}
T* operator=(T* newval) {Dispose();val = newval; return newval;}
bool operator==(T* cmp) const {return val == cmp;}
T* Detach() {T* old = val; val = NULL;return old;} // detach without freeing
void Dispose() {if (!isNull()) (myClass->*freeFn)(val);val=NULL;}
bool IsValid() const {return !isNull();}
T* operator->() { return val;}
protected:
bool isNull() const {return val==NULL;}
private:
RiaaClassCall& operator=(RiaaClassCall<T, C, freeFn> &src) ; // don't want two RiaaClassCall freeing the same object
RiaaClassCall(const RiaaClassCall<T, C, freeFn> &src); // never use this.
};
/**
* RIAA class for self deleting NON pointer type, that calls a function on a
* class. T Must have simple copy semantics & compare semantics.
*
* (We need a separate template class from RiaaClassCall, because NULL is not
* allowed as a template parameter.)
*/
template <typename T, typename C, typename R, R (C::*freeFn)(T)> class RiaaObjCallVar
{
public:
T val;
bool valid;
C* myClass;
RiaaObjCallVar(C* myClass) : val(T()), valid(false), myClass(myClass) {}
RiaaObjCallVar(T val, C* myClass) : val(val), valid(true), myClass(myClass) {}
~RiaaObjCallVar() {Dispose();}
operator T&() { return val;}
T& operator=(T newval) {Dispose();val = newval; valid=true; return val;}
bool operator==(T cmp) const {return val == cmp;}
T& Detach() {valid = false; return val;} // detach without calling the callback
void Attach(T newval) {val = newval; valid=true;} // change/set without calling the callback.
void Dispose() {if (valid) (myClass->*freeFn)(val);valid=false;}
bool IsValid() const {return valid;}
//T& operator->() { return val; } //??
protected:
private:
RiaaObjCallVar& operator=(RiaaObjCallVar<T, C, R, freeFn> &src) ; // don't want two RiaaObjCallVar freeing the same object
RiaaObjCallVar(const RiaaObjCallVar<T, C, R, freeFn> &src); // never use this.
};
/**
* Same as RiaaObjCallVar, but with void return type.
*
*/
template <typename T, typename C, void (C::*freeFn)(T)> class RiaaObjCall : public RiaaObjCallVar<T, C, void, freeFn >
{
public:
RiaaObjCall(C* myClass) : RiaaObjCallVar<T, C, void, freeFn >(myClass) {}
RiaaObjCall(T val, C* myClass) : RiaaObjCallVar<T, C, void, freeFn >(val, myClass) {}
T& operator=(T newval) {return RiaaObjCallVar<T, C, void, freeFn >::operator=(newval);}
private:
RiaaObjCall& operator=(RiaaObjCall<T, C, freeFn> &src) ; // don't want two RiaaObjCallVar freeing the same object
RiaaObjCall(const RiaaObjCall<T, C, freeFn> &src); // never use this.
};
};