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_
32 #include "PyrObject.h"
33 #include "SC_AllocPool.h"
34 #include "PyrKernel.h"
35 #include "PyrPrimitive.h"
36 #include "VMGlobals.h"
39 const int32 kDeepFreezerObjectArrayInitialCapacity
= 32;
44 PyrDeepFreezer(VMGlobals
*inG
)
45 : g(inG
), objectArray(initialObjectArray
), numObjects(0),
46 objectArrayCapacity( kDeepFreezerObjectArrayInitialCapacity
)
51 if (objectArrayCapacity
> kDeepFreezerObjectArrayInitialCapacity
)
52 g
->allocPool
->Free(objectArray
);
55 long doDeepFreeze(PyrSlot
*objectSlot
)
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
) {
70 for (int i
=0; i
<numObjects
; ++i
)
71 objectArray
[i
]->ClearMark();
78 void recurse(PyrObject
*obj
, int n
)
80 PyrSlot
*slot
= obj
->slots
;
81 for (int i
=0; i
<n
; ++i
, ++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
)
104 // expand array if needed
105 if (numObjects
>= objectArrayCapacity
) growObjectArray();
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
)) {
122 } else if (isKindOf(obj
, class_array
)) {
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");
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");
139 recurse(obj
, obj
->size
);
146 PyrObject
**objectArray
;
148 int32 objectArrayCapacity
;
150 PyrObject
*initialObjectArray
[kDeepFreezerObjectArrayInitialCapacity
];