-
Notifications
You must be signed in to change notification settings - Fork 0
/
gcptr.h
161 lines (134 loc) · 3.86 KB
/
gcptr.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
/******************************************************************************
* History: 2015-10-07 DMP Initial Creation
******************************************************************************/
#ifndef HDR_GCPTR_H_6E131858_6D41_11E5_B707_00FF90F8250A__
#define HDR_GCPTR_H_6E131858_6D41_11E5_B707_00FF90F8250A__
template <class T>
class GCDellocator
{
public:
static DLLEXPORT void freemem(T*thingmem)
{
::operator delete(thingmem);
}
};
template <class T>
class GCDeleter
{
public:
static void deleter( T* thing )
{
thing->~T();
GCDellocator<T>::freemem(thing);
}
};
struct Uncopyable
{
private:
Uncopyable( const Uncopyable& );
public:
Uncopyable( Uncopyable&& other ) {}
Uncopyable() {}
};
template <class T>
class gcbase : private Uncopyable
{
long refcount_;
void (*deleter_)( T* );
//~~~ wait, what? I don't know that this makes sense either, unless the other guy's
// refcount is 1 (and is about to be decremented); otherwise people are hanging on to a
// a moved object, and nobody is necessarily referencing the new object, so what should
// his refcount be?? . Maybe it makes sense to allow the rest of the objects content to
// be moved while just assuming a 'first initialization' refcount of 1 here.
// But Let's start with it disabled and see how that goes.
gcbase( gcbase& other );
gcbase( gcbase&& other );
gcbase& operator=( gcbase& other );
gcbase& operator=( gcbase&& other );
// {
// refcount_ = other.refcount_;
// }
public:
gcbase()
: refcount_(0),
deleter_( &GCDeleter<T>::deleter )
{}
long refcount() const { return refcount_; }
void ref()
{
// ++refcount_;
// std::cerr << "gcbase=" << this << " ref=" << refcount_ << "\n";
MT_SAFEISH_INC( refcount_ );
}
void unref()
{
// std::cerr << "gcbase=" << this << " UNREF=" << refcount_ << "\n";
if (MT_SAFEISH_DEC( refcount_ ))
{
deleter_(static_cast<T*>(this));
}
}
};
template <class T> // T must derive from gcbase
class gcptr
{
private:
T* ptr_;
public:
gcptr() : ptr_(nullptr) {}
gcptr( T* ptr )
: ptr_( ptr )
{
if (ptr_) ptr_->ref();
}
gcptr( const gcptr& other )
: ptr_( other.ptr_ )
{
if (ptr_) ptr_->ref();
}
~gcptr()
{
if (ptr_) ptr_->unref();
}
bool operator==( const gcptr<T>& rhs )
{
return rhs.ptr_ == ptr_;
}
#if 1
gcptr( gcptr&& other )
: ptr_( other.ptr_ )
{
other.ptr_ = nullptr;
}
gcptr& operator=( gcptr&& other )
{
gcptr( static_cast<gcptr&&>(other) ).swap(*this);
return *this;
}
#endif
gcptr& operator=( const gcptr& other )
{
gcptr(other).swap(*this);
return *this;
}
gcptr& operator=( T* other )
{
gcptr(other).swap(*this);
return *this;
}
T* get() const { return ptr_; }
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
operator bool () const { return ptr_ ? true : false; }
void reset()
{
gcptr().swap( *this );
}
void swap(gcptr & other)
{
T * tmp = ptr_;
ptr_ = other.ptr_;
other.ptr_ = tmp;
}
};
#endif /* ifndef HDR_GCPTR_H_6E131858_6D41_11E5_B707_00FF90F8250A__ */