Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / include / lang / PyrDeepCopier.h
blobb57d5e54614286802c40013ddbe346c4838fe609
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 An object archiving system for SuperCollider.
27 #ifndef _PyrDeepCopier_
28 #define _PyrDeepCopier_
30 #include "PyrObject.h"
31 #include "SC_AllocPool.h"
33 #include "PyrKernel.h"
34 #include "PyrPrimitive.h"
35 #include "VMGlobals.h"
36 #include "GC.h"
38 const int32 kDeepCopierObjectArrayInitialCapacity = 32;
40 class PyrDeepCopier
42 public:
43 PyrDeepCopier(VMGlobals *inG)
44 : g(inG), objectArray(initialObjectArray), numObjects(0),
45 objectArrayCapacity( kDeepCopierObjectArrayInitialCapacity )
48 ~PyrDeepCopier()
50 if (objectArrayCapacity > kDeepCopierObjectArrayInitialCapacity) {
51 g->allocPool->Free(objectArray);
55 long doDeepCopy(PyrSlot *objectSlot)
57 long err = errNone;
59 try {
60 if (IsObj(objectSlot)) {
61 constructObjectArray(slotRawObject(objectSlot));
62 for (int i=0; i<numObjects; ++i) {
63 fixSlots(objectArray[i]);
65 fixObjSlot(objectSlot);
66 for (int i=0; i<numObjects; ++i) {
67 objectArray[i]->ClearMark();
71 } catch (std::exception &ex) {
72 error(ex.what());
73 err = errFailed;
75 return err;
78 private:
80 void recurse(PyrObject *obj, size_t n)
82 //post("->recurse %s %08X\n", obj->classptr->name.us->name, obj);
83 PyrSlot *slot = obj->slots;
84 for (size_t i=0; i<n; ++i, ++slot) {
85 if (IsObj(slot))
86 constructObjectArray(slotRawObject(slot));
88 //post("<-recurse %s %08X\n", obj->classptr->name.us->name, obj);
91 void growObjectArray()
93 int32 newObjectArrayCapacity = objectArrayCapacity << 1;
95 int32 newSize = newObjectArrayCapacity * sizeof(PyrObject*);
96 PyrObject** newArray = (PyrObject**)g->allocPool->Alloc(newSize);
97 memcpy(newArray, objectArray, numObjects * sizeof(PyrObject*));
98 if (objectArrayCapacity > kDeepCopierObjectArrayInitialCapacity) {
99 g->allocPool->Free(objectArray);
101 objectArrayCapacity = newObjectArrayCapacity;
102 objectArray = newArray;
105 void putSelf(PyrObject *obj)
107 obj->SetMark();
108 obj->scratch1 = numObjects;
110 // expand array if needed
111 if (numObjects >= objectArrayCapacity) growObjectArray();
113 //post("putSelf %d %08X\n", numObjects, obj);
114 // add to array
115 objectArray[numObjects++] = obj;
118 void putCopy(PyrObject *obj)
120 obj->SetMark();
121 obj->scratch1 = numObjects;
123 // expand array if needed
124 if (numObjects+2 >= objectArrayCapacity) growObjectArray();
126 // add a shallow copy to object array
127 PyrObject *copy = copyObject(g->gc, obj, false);
128 copy->ClearMark();
130 //post("putCopy %d %08X\n", numObjects, copy);
132 // add to array
133 objectArray[numObjects++] = copy;
134 objectArray[numObjects++] = obj;
137 void constructObjectArray(PyrObject *obj)
139 //post("->constructObjectArray %s %08X\n", obj->classptr->name.us->name, obj);
140 if (!obj->IsMarked()) {
141 if (isKindOf(obj, class_class)) {
142 putSelf(obj);
143 } else if (isKindOf(obj, class_process)) {
144 putSelf(obj);
145 } else if (isKindOf(obj, s_interpreter->u.classobj)) {
146 putSelf(obj);
147 } else if (isKindOf(obj, class_rawarray)) {
148 putCopy(obj);
149 } else if (isKindOf(obj, class_array)) {
150 putCopy(obj);
151 recurse(obj, obj->size);
152 } else if (isKindOf(obj, class_func)) {
153 putSelf(obj);
154 } else if (isKindOf(obj, class_method)) {
155 putSelf(obj);
156 } else if (isKindOf(obj, class_thread)) {
157 putSelf(obj);
158 } else if (isKindOf(obj, class_server_shm_interface)) {
159 putSelf(obj);
160 } else {
161 putCopy(obj);
162 recurse(obj, obj->size);
165 //post("<-constructObjectArray %s %08X\n", obj->classptr->name.us->name, obj);
168 void fixObjSlot(PyrSlot* slot)
170 //post("fixObjSlot %s %08X %d %08X\n", slotRawObject(slot)->classptr->name.us->name, slotRawObject(slot), slot->uo->scratch1, objectArray[slot->uo->scratch1]);
171 SetRaw(slot, objectArray[slotRawObject(slot)->scratch1]);
174 void fixSlots(PyrObject *obj)
176 //post("fixSlots %s %08X %d\n", obj->classptr->name.us->name, obj, obj->IsMarked());
177 if (!obj->IsMarked() && obj->obj_format <= obj_slot) { // it is a copy
178 PyrSlot *slot = obj->slots;
179 for (int i=0; i<obj->size; ++i, ++slot) {
180 if (IsObj(slot)) fixObjSlot(slot);
185 VMGlobals *g;
187 PyrObject **objectArray;
188 int32 numObjects;
189 int32 objectArrayCapacity;
191 PyrObject *initialObjectArray[kDeepCopierObjectArrayInitialCapacity];
194 #endif