aboutsummaryrefslogtreecommitdiff
path: root/src/stable/sharedcore.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/stable/sharedcore.h340
1 files changed, 170 insertions, 170 deletions
diff --git a/src/stable/sharedcore.h b/src/stable/sharedcore.h
index f000077..f8b9d4e 100644
--- a/src/stable/sharedcore.h
+++ b/src/stable/sharedcore.h
@@ -15,176 +15,176 @@
15 15
16namespace Bu 16namespace Bu
17{ 17{
18 /** 18 /**
19 * A mechanism for creating classes that perform lazy copies. The concept 19 * A mechanism for creating classes that perform lazy copies. The concept
20 * behind this is that instead of copying a large object when it is assigned 20 * behind this is that instead of copying a large object when it is assigned
21 * or passed into a copy constructor we simply copy a pointer internally. 21 * or passed into a copy constructor we simply copy a pointer internally.
22 * The assumption is that many times when an object is passed by value we 22 * The assumption is that many times when an object is passed by value we
23 * don't really want to keep the object around, we want the recipient to 23 * don't really want to keep the object around, we want the recipient to
24 * take ownership without allocating a new object. This allows that to 24 * take ownership without allocating a new object. This allows that to
25 * happen. 25 * happen.
26 * 26 *
27 * When used properly this makes object copying essentially free (O(1), 27 * When used properly this makes object copying essentially free (O(1),
28 * that is) and performs the actual copy when a user tries to modify the 28 * that is) and performs the actual copy when a user tries to modify the
29 * object. 29 * object.
30 * 30 *
31 * For example, lets look at something like the getKeys function in 31 * For example, lets look at something like the getKeys function in
32 * Bu::Hash. When this function is called it creates a Bu::List of 32 * Bu::Hash. When this function is called it creates a Bu::List of
33 * appropriate type, fills it with keys, and returns it. This is a good 33 * appropriate type, fills it with keys, and returns it. This is a good
34 * way for this function to behave, there may be additional issues if the 34 * way for this function to behave, there may be additional issues if the
35 * List object were allocated with new and not on the stack. However, 35 * List object were allocated with new and not on the stack. However,
36 * returning the List at the end of the function could potentially take 36 * returning the List at the end of the function could potentially take
37 * a very long time depending on the size of the list and the type of the 37 * a very long time depending on the size of the list and the type of the
38 * key. In this case the getKeys function doesn't want ownership of the 38 * key. In this case the getKeys function doesn't want ownership of the
39 * List object, and when it returns it, it's local copy will be destroyed. 39 * List object, and when it returns it, it's local copy will be destroyed.
40 * 40 *
41 * However, List inherits from SharedCore, which means that when it is 41 * However, List inherits from SharedCore, which means that when it is
42 * returned all we do is copy a pointer to the "core" of the list, which 42 * returned all we do is copy a pointer to the "core" of the list, which
43 * is a very fast operatorion. For a brief moment, before anyone can do 43 * is a very fast operatorion. For a brief moment, before anyone can do
44 * anything else, there are two objects referencing the core of that single 44 * anything else, there are two objects referencing the core of that single
45 * list. However, the getKeys() function will destroy it's local copy 45 * list. However, the getKeys() function will destroy it's local copy
46 * before the calling function can use it's new copy. That means that by 46 * before the calling function can use it's new copy. That means that by
47 * the time the calling function can use it's new List of keys it is the 47 * the time the calling function can use it's new List of keys it is the
48 * only one with a reference to the core, and no copy will need to happen. 48 * only one with a reference to the core, and no copy will need to happen.
49 * 49 *
50 * Using SharedCore on your own classes is fairly straight forward. There 50 * Using SharedCore on your own classes is fairly straight forward. There
51 * are only a couple of steps. First, break the class into two classes. 51 * are only a couple of steps. First, break the class into two classes.
52 * Move every variable from the original class (generally everything that's 52 * Move every variable from the original class (generally everything that's
53 * private) into the new class. Then make the original class inherit from 53 * private) into the new class. Then make the original class inherit from
54 * SharedCore. The SharedCore template takes 2 parameters, first is the 54 * SharedCore. The SharedCore template takes 2 parameters, first is the
55 * class it's inheriting from, second is the new core class. Now, in your 55 * class it's inheriting from, second is the new core class. Now, in your
56 * original class you will have one class variable, a pointer named core. 56 * original class you will have one class variable, a pointer named core.
57 * All of your original variables will be accessable through core. The next 57 * All of your original variables will be accessable through core. The next
58 * step is to access everything you used to through core, and to find 58 * step is to access everything you used to through core, and to find
59 * every function that may change data in the core. At the top of every 59 * every function that may change data in the core. At the top of every
60 * function that may change data you want to call _hardCopy(). 60 * function that may change data you want to call _hardCopy().
61 * 61 *
62 * That's more or less it. A more detailed guide will be written soon. 62 * That's more or less it. A more detailed guide will be written soon.
63 * @todo Write a guide for this. 63 * @todo Write a guide for this.
64 */ 64 */
65 template<typename Shell, typename Core> 65 template<typename Shell, typename Core>
66 class SharedCore 66 class SharedCore
67 { 67 {
68 typedef class SharedCore<Shell, Core> _SharedType; 68 typedef class SharedCore<Shell, Core> _SharedType;
69 public: 69 public:
70 SharedCore() : 70 SharedCore() :
71 core( NULL ), 71 core( NULL ),
72 iRefCount( NULL ) 72 iRefCount( NULL )
73 { 73 {
74 core = _allocateCore(); 74 core = _allocateCore();
75 iRefCount = new int(1); 75 iRefCount = new int(1);
76 } 76 }
77 77
78 SharedCore( const _SharedType &rSrc ) : 78 SharedCore( const _SharedType &rSrc ) :
79 core( NULL ), 79 core( NULL ),
80 iRefCount( NULL ) 80 iRefCount( NULL )
81 { 81 {
82 _softCopy( rSrc ); 82 _softCopy( rSrc );
83 } 83 }
84 84
85 virtual ~SharedCore() 85 virtual ~SharedCore()
86 { 86 {
87 _deref(); 87 _deref();
88 } 88 }
89 89
90 SharedCore &operator=( const SharedCore &rhs ) 90 SharedCore &operator=( const SharedCore &rhs )
91 { 91 {
92 if( core == rhs.core ) 92 if( core == rhs.core )
93 return *this; 93 return *this;
94 94
95 _softCopy( rhs ); 95 _softCopy( rhs );
96 return *this; 96 return *this;
97 } 97 }
98 98
99 int getRefCount() const 99 int getRefCount() const
100 { 100 {
101 return *iRefCount; 101 return *iRefCount;
102 } 102 }
103 103
104 Shell clone() const 104 Shell clone() const
105 { 105 {
106 Shell s( dynamic_cast<const Shell &>(*this) ); 106 Shell s( dynamic_cast<const Shell &>(*this) );
107 s._hardCopy(); 107 s._hardCopy();
108 return s; 108 return s;
109 } 109 }
110 110
111 bool isCoreShared( const Shell &rOther ) const 111 bool isCoreShared( const Shell &rOther ) const
112 { 112 {
113 return rOther.core == core; 113 return rOther.core == core;
114 } 114 }
115 115
116 protected: 116 protected:
117 Core *core; 117 Core *core;
118 void _hardCopy() 118 void _hardCopy()
119 { 119 {
120 if( !core || !iRefCount ) 120 if( !core || !iRefCount )
121 return; 121 return;
122 if( (*iRefCount) == 1 ) 122 if( (*iRefCount) == 1 )
123 return; 123 return;
124 Core *copy = _copyCore( core ); 124 Core *copy = _copyCore( core );
125 _deref(); 125 _deref();
126 core = copy; 126 core = copy;
127 iRefCount = new int( 1 ); 127 iRefCount = new int( 1 );
128 } 128 }
129 129
130 /** 130 /**
131 * Reset core acts like a hard copy, except instead of providing a 131 * Reset core acts like a hard copy, except instead of providing a
132 * standalone copy of the shared core, it provides a brand new core. 132 * standalone copy of the shared core, it provides a brand new core.
133 * 133 *
134 * Very useful in functions used to reset the state of an object. 134 * Very useful in functions used to reset the state of an object.
135 */ 135 */
136 void _resetCore() 136 void _resetCore()
137 { 137 {
138 if( core ) 138 if( core )
139 _deref(); 139 _deref();
140 core = _allocateCore(); 140 core = _allocateCore();
141 iRefCount = new int( 1 ); 141 iRefCount = new int( 1 );
142 } 142 }
143 143
144 virtual Core *_allocateCore() 144 virtual Core *_allocateCore()
145 { 145 {
146 return new Core(); 146 return new Core();
147 } 147 }
148 148
149 virtual Core *_copyCore( Core *pSrc ) 149 virtual Core *_copyCore( Core *pSrc )
150 { 150 {
151 return new Core( *pSrc ); 151 return new Core( *pSrc );
152 } 152 }
153 153
154 virtual void _deallocateCore( Core *pSrc ) 154 virtual void _deallocateCore( Core *pSrc )
155 { 155 {
156 delete pSrc; 156 delete pSrc;
157 } 157 }
158 158
159 private: 159 private:
160 void _deref() 160 void _deref()
161 { 161 {
162 if( (--(*iRefCount)) == 0 ) 162 if( (--(*iRefCount)) == 0 )
163 { 163 {
164 _deallocateCore( core ); 164 _deallocateCore( core );
165 delete iRefCount; 165 delete iRefCount;
166 } 166 }
167 core = NULL; 167 core = NULL;
168 iRefCount = NULL; 168 iRefCount = NULL;
169 } 169 }
170 170
171 void _incRefCount() 171 void _incRefCount()
172 { 172 {
173 if( iRefCount && core ) 173 if( iRefCount && core )
174 ++(*iRefCount); 174 ++(*iRefCount);
175 } 175 }
176 176
177 void _softCopy( const _SharedType &rSrc ) 177 void _softCopy( const _SharedType &rSrc )
178 { 178 {
179 if( core ) 179 if( core )
180 _deref(); 180 _deref();
181 core = rSrc.core; 181 core = rSrc.core;
182 iRefCount = rSrc.iRefCount; 182 iRefCount = rSrc.iRefCount;
183 _incRefCount(); 183 _incRefCount();
184 } 184 }
185 185
186 int *iRefCount; 186 int *iRefCount;
187 }; 187 };
188}; 188};
189 189
190#undef fin 190#undef fin