-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsmart_ptr.h
153 lines (124 loc) · 3.39 KB
/
smart_ptr.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
#pragma once
#ifndef __CUTEPIG_SMART_PTR__
#define __CUTEPIG_SMART_PTR__
// uncomment
#define __DEBUG_PRINT_REFCOUNT__
#ifdef __DEBUG_PRINT_REFCOUNT__
#include <iostream>
#endif
namespace cutepig {
// thank you http://www.eetimes.com/discussion/programming-pointers/4025549/Catching-errors-early-with-compile-time-assertions
#define cutepig_ctassert(cond, msg) \
typedef char msg[(cond) ? 1 : 0]
// delete wrapper
template<typename T>
struct __delete__ {
inline void operator()( T *ptr ) { delete ptr; }
};
// simple smart_ptr, deletor has to be object with operator()
template<typename T, typename Delete= __delete__<T> >
class smart_ptr {
protected:
typedef T * ptr_type;
typedef const T *const_ptr_type;
typedef smart_ptr<T, Delete> self_type;
typedef self_type *self_ptr_type;
ptr_type ptr; // data referenced
self_ptr_type link; // next in chain
self_ptr_type root; // object that contains refcount info
size_t count; // refcount (active only in root)
private:
// private default constructor.. dont use
smart_ptr() : ptr(0), link(0), root(this), count(0)
{}
public:
// initial assignment, assigns ptr to referenced object,
// roots the chain to itself and sets initial refcount to 1
explicit smart_ptr(ptr_type _ptr) : ptr(_ptr), link(0), root(this), count(1)
{
#ifdef __DEBUG_PRINT_REFCOUNT__
std::cout << "smart_ptr::refcount " << root->count << std::endl;
#endif
}
// copy ctor
explicit smart_ptr(const smart_ptr &other)
: ptr(other.ptr), link(other.root->link), root(other.root), count(0)
{
// ptr, link and root are now assigned
// insert to list after the root
root->link = this;
// refcount
++root->count;
#ifdef __DEBUG_PRINT_REFCOUNT__
std::cout << "smart_ptr::refcount " << root->count << std::endl;
#endif
}
// destructor, tougher one. remove reference -> possibly destroy
// otherwise we might have to re-root the chain and remove this link
~smart_ptr() {
destruct();
}
self_type &operator=( const self_type &other ) {
destruct();
ptr = other.ptr;
root = other.root;
count = 0;
// insert after root
link = other.root->link;
root->link = this;
// recount
++root->count;
#ifdef __DEBUG_PRINT_REFCOUNT__
std::cout << "smart_ptr::refcount " << root->count << std::endl;
#endif
return *this;
}
self_type &operator=( ptr_type _ptr ) {
destruct();
ptr = _ptr;
root = this;
link = 0;
count = 1;
}
// accessors
ptr_type operator->() { return ptr; }
const_ptr_type operator->() const { return ptr; }
private:
void destruct() {
// check for destruction
if( --root->count == 0 ) {
Delete()( ptr );
return;
}
#ifdef __DEBUG_PRINT_REFCOUNT__
std::cout << "smart_ptr::refcount " << root->count << std::endl;
#endif
// check for re-rooting
if( root == this )
reroot();
else
unlink();
}
// re-root assigns the 'root' for the whole chain to the next of 'root'
void reroot() {
root = root->link;
// iterator
self_ptr_type p = root;
while( p ) {
// re-root element
p->root = root;
p = p->link;
}
}
// remove this object from the chain
void unlink() {
// find 'previous', downside of singly-linked list
self_ptr_type p = root;
while( p && p->link != this )
p = p->link;
if( p )
p->link = link;
}
};
}
#endif