summaryrefslogtreecommitdiff
path: root/src/sharedcore.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sharedcore.h')
-rw-r--r--src/sharedcore.h77
1 files changed, 75 insertions, 2 deletions
diff --git a/src/sharedcore.h b/src/sharedcore.h
index 5a44df9..1887ca2 100644
--- a/src/sharedcore.h
+++ b/src/sharedcore.h
@@ -15,10 +15,57 @@
15 15
16namespace Bu 16namespace Bu
17{ 17{
18 template<typename Core> 18 /**
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
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
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
25 * happen.
26 *
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
29 * object.
30 *
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
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
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
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
39 * List object, and when it returns it, it's local copy will be destroyed.
40 *
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
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
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
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.
49 *
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.
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
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
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
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
60 * function that may change data you want to call _hardCopy().
61 *
62 * That's more or less it. A more detailed guide will be written soon.
63 * @todo Write a guide for this.
64 */
65 template<typename Shell, typename Core>
19 class SharedCore 66 class SharedCore
20 { 67 {
21 typedef class SharedCore<Core> _SharedType; 68 typedef class SharedCore<Shell, Core> _SharedType;
22 public: 69 public:
23 SharedCore() : 70 SharedCore() :
24 core( NULL ), 71 core( NULL ),
@@ -54,6 +101,18 @@ namespace Bu
54 return *iRefCount; 101 return *iRefCount;
55 } 102 }
56 103
104 Shell clone() const
105 {
106 Shell s( dynamic_cast<const Shell &>(*this) );
107 s._hardCopy();
108 return s;
109 }
110
111 bool isCoreShared( const Shell &rOther ) const
112 {
113 return rOther.core == core;
114 }
115
57 protected: 116 protected:
58 Core *core; 117 Core *core;
59 void _hardCopy() 118 void _hardCopy()
@@ -68,6 +127,20 @@ namespace Bu
68 iRefCount = new int( 1 ); 127 iRefCount = new int( 1 );
69 } 128 }
70 129
130 /**
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.
133 *
134 * Very useful in functions used to reset the state of an object.
135 */
136 void _resetCore()
137 {
138 if( core )
139 _deref();
140 core = _allocateCore();
141 iRefCount = new int( 1 );
142 }
143
71 virtual Core *_allocateCore() 144 virtual Core *_allocateCore()
72 { 145 {
73 return new Core(); 146 return new Core();