class library: SynthDef - lazy implementation of removeUGen
[supercollider.git] / include / lang / PyrDeepCopier.h
blob18d9c6328412cc4ae9232ff5e03b00230c3901cd
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"
37 #include "ReadWriteMacros.h"
39 const int32 kDeepCopierObjectArrayInitialCapacity = 32;
41 class PyrDeepCopier
43 public:
44 PyrDeepCopier(VMGlobals *inG)
45 : g(inG), objectArray(initialObjectArray), numObjects(0),
46 objectArrayCapacity( kDeepCopierObjectArrayInitialCapacity )
50 ~PyrDeepCopier()
52 if (objectArrayCapacity > kDeepCopierObjectArrayInitialCapacity) {
53 g->allocPool->Free(objectArray);
57 long doDeepCopy(PyrSlot *objectSlot)
59 long err = errNone;
61 try {
62 if (IsObj(objectSlot)) {
63 constructObjectArray(slotRawObject(objectSlot));
64 for (int i=0; i<numObjects; ++i) {
65 fixSlots(objectArray[i]);
67 fixObjSlot(objectSlot);
68 for (int i=0; i<numObjects; ++i) {
69 objectArray[i]->ClearMark();
73 } catch (std::exception &ex) {
74 error(ex.what());
75 err = errFailed;
77 return err;
80 private:
82 void recurse(PyrObject *obj, int n)
84 //post("->recurse %s %08X\n", obj->classptr->name.us->name, obj);
85 PyrSlot *slot = obj->slots;
86 for (int i=0; i<n; ++i, ++slot) {
87 if (IsObj(slot)) constructObjectArray(slotRawObject(slot));
89 //post("<-recurse %s %08X\n", obj->classptr->name.us->name, obj);
92 void growObjectArray()
94 int32 newObjectArrayCapacity = objectArrayCapacity << 1;
96 int32 newSize = newObjectArrayCapacity * sizeof(PyrObject*);
97 PyrObject** newArray = (PyrObject**)g->allocPool->Alloc(newSize);
98 memcpy(newArray, objectArray, numObjects * sizeof(PyrObject*));
99 if (objectArrayCapacity > kDeepCopierObjectArrayInitialCapacity) {
100 g->allocPool->Free(objectArray);
102 objectArrayCapacity = newObjectArrayCapacity;
103 objectArray = newArray;
106 void putSelf(PyrObject *obj)
108 obj->SetMark();
109 obj->scratch1 = numObjects;
111 // expand array if needed
112 if (numObjects >= objectArrayCapacity) growObjectArray();
114 //post("putSelf %d %08X\n", numObjects, obj);
115 // add to array
116 objectArray[numObjects++] = obj;
119 void putCopy(PyrObject *obj)
121 obj->SetMark();
122 obj->scratch1 = numObjects;
124 // expand array if needed
125 if (numObjects+2 >= objectArrayCapacity) growObjectArray();
127 // add a shallow copy to object array
128 PyrObject *copy = copyObject(g->gc, obj, false);
129 copy->ClearMark();
131 //post("putCopy %d %08X\n", numObjects, copy);
133 // add to array
134 objectArray[numObjects++] = copy;
135 objectArray[numObjects++] = obj;
138 void constructObjectArray(PyrObject *obj)
140 //post("->constructObjectArray %s %08X\n", obj->classptr->name.us->name, obj);
141 if (!obj->IsMarked()) {
142 if (isKindOf(obj, class_class)) {
143 putSelf(obj);
144 } else if (isKindOf(obj, class_process)) {
145 putSelf(obj);
146 } else if (isKindOf(obj, s_interpreter->u.classobj)) {
147 putSelf(obj);
148 } else if (isKindOf(obj, class_rawarray)) {
149 putCopy(obj);
150 } else if (isKindOf(obj, class_array)) {
151 putCopy(obj);
152 recurse(obj, obj->size);
153 } else if (isKindOf(obj, class_func)) {
154 putSelf(obj);
155 } else if (isKindOf(obj, class_method)) {
156 putSelf(obj);
157 } else if (isKindOf(obj, class_thread)) {
158 putSelf(obj);
159 } else {
160 putCopy(obj);
161 recurse(obj, obj->size);
164 //post("<-constructObjectArray %s %08X\n", obj->classptr->name.us->name, obj);
167 void fixObjSlot(PyrSlot* slot)
169 //post("fixObjSlot %s %08X %d %08X\n", slotRawObject(slot)->classptr->name.us->name, slotRawObject(slot), slot->uo->scratch1, objectArray[slot->uo->scratch1]);
170 SetRaw(slot, objectArray[slotRawObject(slot)->scratch1]);
173 void fixSlots(PyrObject *obj)
175 //post("fixSlots %s %08X %d\n", obj->classptr->name.us->name, obj, obj->IsMarked());
176 if (!obj->IsMarked() && obj->obj_format <= obj_slot) { // it is a copy
177 PyrSlot *slot = obj->slots;
178 for (int i=0; i<obj->size; ++i, ++slot) {
179 if (IsObj(slot)) fixObjSlot(slot);
184 VMGlobals *g;
186 PyrObject **objectArray;
187 int32 numObjects;
188 int32 objectArrayCapacity;
190 PyrObject *initialObjectArray[kDeepCopierObjectArrayInitialCapacity];
194 SuperCollider real time audio synthesis system
195 Copyright (c) 2002 James McCartney. All rights reserved.
196 http://www.audiosynth.com
198 This program is free software; you can redistribute it and/or modify
199 it under the terms of the GNU General Public License as published by
200 the Free Software Foundation; either version 2 of the License, or
201 (at your option) any later version.
203 This program is distributed in the hope that it will be useful,
204 but WITHOUT ANY WARRANTY; without even the implied warranty of
205 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
206 GNU General Public License for more details.
208 You should have received a copy of the GNU General Public License
209 along with this program; if not, write to the Free Software
210 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
214 An object archiving system for SuperCollider.
220 #endif