"Post Window" -> "Post window" prevents it being seen as two separate
[supercollider.git] / include / lang / PyrDeepFreezer.h
blob8908fe137b02c2ac38488ee71fbe29660abcb22e
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.
26 #ifndef _PyrDeepFreezer_
27 #define _PyrDeepFreezer_
29 #include <stdexcept>
30 #include <cstring>
32 #include "PyrObject.h"
33 #include "SC_AllocPool.h"
34 #include "PyrKernel.h"
35 #include "PyrPrimitive.h"
36 #include "VMGlobals.h"
37 #include "GC.h"
39 const int32 kDeepFreezerObjectArrayInitialCapacity = 32;
41 class PyrDeepFreezer
43 public:
44 PyrDeepFreezer(VMGlobals *inG)
45 : g(inG), objectArray(initialObjectArray), numObjects(0),
46 objectArrayCapacity( kDeepFreezerObjectArrayInitialCapacity )
49 ~PyrDeepFreezer()
51 if (objectArrayCapacity > kDeepFreezerObjectArrayInitialCapacity)
52 g->allocPool->Free(objectArray);
55 long doDeepFreeze(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 g->gc->BecomePermanent( objectArray[i] );
64 objectArray[i]->ClearMark();
67 } catch (std::exception &ex) {
68 error(ex.what());
69 err = errFailed;
70 for (int i=0; i<numObjects; ++i)
71 objectArray[i]->ClearMark();
73 return err;
76 private:
78 void recurse(PyrObject *obj, int n)
80 PyrSlot *slot = obj->slots;
81 for (int i=0; i<n; ++i, ++slot)
82 if (IsObj(slot))
83 constructObjectArray(slotRawObject(slot));
86 void growObjectArray()
88 int32 newObjectArrayCapacity = objectArrayCapacity << 1;
90 int32 newSize = newObjectArrayCapacity * sizeof(PyrObject*);
91 PyrObject** newArray = (PyrObject**)g->allocPool->Alloc(newSize);
92 memcpy(newArray, objectArray, numObjects * sizeof(PyrObject*));
93 if (objectArrayCapacity > kDeepFreezerObjectArrayInitialCapacity)
94 g->allocPool->Free(objectArray);
96 objectArrayCapacity = newObjectArrayCapacity;
97 objectArray = newArray;
100 void putObject(PyrObject *obj)
102 obj->SetMark();
104 // expand array if needed
105 if (numObjects >= objectArrayCapacity) growObjectArray();
107 // add to array
108 objectArray[numObjects++] = obj;
111 void constructObjectArray(PyrObject *obj)
113 if (obj->IsPermanent()) return;
115 if (!obj->IsMarked()) {
116 if (isKindOf(obj, class_process)) {
117 throw std::runtime_error("cannot freeze Process.\n");
118 } else if (isKindOf(obj, s_interpreter->u.classobj)) {
119 throw std::runtime_error("cannot freeze Interpreter.\n");
120 } else if (isKindOf(obj, class_rawarray)) {
121 putObject(obj);
122 } else if (isKindOf(obj, class_array)) {
123 putObject(obj);
124 recurse(obj, obj->size);
125 } else if (isKindOf(obj, class_func)) {
126 if (NotNil(&slotRawBlock(&((PyrClosure*)obj)->block)->contextDef)) {
127 throw std::runtime_error("open Function can not be frozen.\n");
129 putObject(obj);
130 recurse(obj, obj->size);
131 } else if (isKindOf(obj, class_method)) {
132 throw std::runtime_error("cannot freeze Methods.\n");
133 } else if (isKindOf(obj, class_thread)) {
134 throw std::runtime_error("cannot freeze Threads.\n");
135 } else if (isKindOf(obj, class_frame)) {
136 throw std::runtime_error("cannot freeze Frames.\n");
137 } else {
138 putObject(obj);
139 recurse(obj, obj->size);
144 VMGlobals *g;
146 PyrObject **objectArray;
147 int32 numObjects;
148 int32 objectArrayCapacity;
150 PyrObject *initialObjectArray[kDeepFreezerObjectArrayInitialCapacity];
154 #endif