squashed commit of private hostlib-resource branch
[tangerine.git] / test / OOPDemos / oop.c
blobb83f864b57705ad98e0edce8839cd288cd173ae9
1 /*
2 Copyright © 1997-98, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Demo of new OOP system
6 Lang: english
7 */
10 #include "protos.h"
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
16 #include "oop.h"
18 #define SDEBUG 0
19 #define DEBUG 0
20 #include "debug.h"
22 /**************************************************/
23 VOID CleanupOOP();
24 BOOL InitOOP();
25 Class *MakeClass(STRPTR classID, STRPTR superID, struct InterfaceDescr *ifDescr,
26 ULONG instDataSize);
27 VOID FreeClass(Class * cl);
29 /* could go into a library base */
30 // struct SignalSemaphore ClassListSema;
31 Class RootClassMem;
32 struct OOPBase oopbasemem;
33 struct OOPBase *oopbase = &oopbasemem;
35 /******************************************************************/
37 /* The oop system code */
39 BOOL AllocDispatchTables(Class *cl, struct InterfaceDescr *iDescr);
40 VOID FreeDispatchTables(Class *cl);
42 /******************
43 ** MakeClass() **
44 ******************/
45 Class *MakeClass(STRPTR classID, STRPTR superID, struct InterfaceDescr *cl_Descr,
46 ULONG instDataSize)
48 #define UB(x) ((UBYTE *)x)
50 #define UnlockCL ReleaseSemaphore( &ClassListSema )
51 #define LockCLShared ObtainSemaphoreShared( &ClassListSema )
52 #define LockCL ObtainSemaphore( &ClassListSema )
54 #define ClassID ClassNode.ln_Name
56 Class *cl, *supercl;
58 /* Find superclass */
59 EnterFunc(bug("MakeClass(classID=%s, superID=%s, ifDescr=%p, instDataSize=%ld)\n",
60 classID, superID, cl_Descr, instDataSize));
62 LockCL;
63 supercl = (Class *)FindName( &(oopbase->ClassList), superID);
64 if (supercl)
66 /* Mark the class as busy, so it isn't freed while we are allocating
67 ** stuff for our class
69 supercl->SubClassCount ++;
71 UnlockCL;
73 if (!supercl)
74 return (FALSE);
76 D(bug("Found superclass %s\n", supercl->ClassID));
78 /* Allocate class structure */
79 D(bug("Allocating class of size %d\n", sizeof (Class) ));
80 cl = malloc(sizeof (Class));
81 if (cl)
84 D(bug("Allocated class structure\n"));
86 cl->ClassID = malloc( strlen(classID) + 1);
87 if (cl->ClassID)
89 D(bug("Allocated class id\n"));
90 strcpy(cl->ClassID, classID);
93 /* Must do this before calling AllocDispatchTables(), so that
94 ** it knows from where to copy dispatch tables.
96 cl->SuperClass = supercl;
97 if (AllocDispatchTables(cl, cl_Descr))
100 /* Update instance data info */
101 cl->InstOffset = supercl->InstOffset + supercl->InstSize;
102 cl->InstSize = instDataSize;
104 ReturnPtr("MakeClass", Class *, cl);
108 free(cl->ClassID);
112 free(cl);
116 /* Initalization failed, free lock on superclass */
117 supercl->SubClassCount --;
119 ReturnPtr ("MakeClass", Class *, NULL);
121 } /* CreateClass */
125 /******************
126 ** FreeClass() **
127 ******************/
129 VOID FreeClass(Class *cl)
132 EnterFunc(bug("FreeClass(classID=%s)\n", cl->ClassID));
134 if (cl)
137 /* What level are we ? */
138 if (cl->SuperClass == NULL) /* Someone trying to remove the rootclass */
139 ReturnVoid("FreeClass (Someone trying to remove rootclass)");
141 FreeDispatchTables(cl);
143 /* Free class ID */
144 D(bug("Freeing class ID %s\n", cl->ClassID));
145 free(cl->ClassID);
147 ReturnVoid("FreeClass");
150 /************************
151 ** Rootclass methods **
152 ************************/
153 struct RootData
155 ULONG dummy;
158 #define NUMROOTMETHODS 2
160 Object *_Root_New(Class *root_cl, Class *cl, APTR param)
162 struct _Object *o;
163 struct RootData *data;
165 EnterFunc(bug("Root::New(cl=%s, param = %p)\n",
166 cl->ClassNode.ln_Name, param));
168 /* Allocate memory for the object */
169 D(bug("Object size: %ld\n", cl->InstOffset + cl->InstSize + sizeof (struct _Object)));
170 o = malloc(cl->InstOffset + cl->InstSize + sizeof (struct _Object));
171 if (o)
173 D(bug("Mem allocated: %p\n", o));
174 o->o_Class = cl;
176 data = (struct RootData *)BASEOBJECT(o);
178 cl->ObjectCount ++;
180 ReturnPtr ("Root::New", Object *, BASEOBJECT(o) );
183 ReturnPtr ("Root::New", Object *, NULL);
186 VOID _Root_Dispose(Class *cl, Object *o, Msg msg)
188 EnterFunc(bug("Root::Dispose(o=%p, oclass=%s)\n", o, _OBJECT(o)->o_Class->ClassNode.ln_Name));
190 _OBJECT(o)->o_Class->ObjectCount --;
191 D(bug("Object mem: %p, size: %ld\n", _OBJECT(o), ((ULONG *)_OBJECT(o))[-1] ));
192 free(_OBJECT(o));
194 ReturnVoid("Root::Dispose");
198 /****************
199 ** InitOOP() **
200 ****************/
203 BOOL InitOOP()
205 #if (HASHED_STRINGS)
206 struct MethodDescr mdescr[]=
208 { (IPTR (*)())_Root_New, M_New },
209 { (IPTR (*)())_Root_Dispose, M_Dispose }
212 struct InterfaceDescr _Root_Descr[] =
214 {mdescr, "Root", 2},
215 {NULL, NULL, 0UL}
218 #endif
219 #if (HASHED_IFS || HASHED_METHODS)
220 IPTR (*_Root_MTab[])() =
222 (IPTR (*)())_Root_New,
223 (IPTR (*)())_Root_Dispose
226 struct InterfaceDescr _Root_Descr[] =
228 {_Root_MTab, I_Root, 2},
229 {NULL, 0UL, 0UL},
231 #endif
233 Class *RootClass = &RootClassMem;
235 InitSemaphore(&ClassListSema);
236 NEWLIST(&(oopbase->ClassList));
238 EnterFunc(bug("InitOOP()\n"));
240 /* Initialize rootclass */
241 RootClass->SuperClass = NULL;
242 if (AllocDispatchTables(RootClass, _Root_Descr))
244 RootClass->ClassID = ROOTCLASS;
245 RootClass->InstOffset = 0UL;
246 RootClass->InstSize = 0UL;
247 RootClass->SubClassCount = 0UL;
248 RootClass->ObjectCount = 0UL;
250 #ifdef HASHED_IFS
251 RootClass->NumInterfaces = 1UL;
252 #endif
254 AddClass(RootClass);
256 ReturnBool ("InitOOP", TRUE);
261 ReturnBool ("InitOOP", FALSE);
265 /*******************
266 ** CleanupOOP() **
267 *******************/
268 VOID CleanupOOP()
270 Class *RootClass = &RootClassMem;
272 EnterFunc(bug("CleanupOOP()\n"));
274 FreeDispatchTables(RootClass);
276 ReturnVoid("CleanupOOP");
280 /*****************
281 ** NewObject() **
282 *****************/
283 Object *NewObject(Class *cl, STRPTR classID, Msg msg)
285 Object *o;
287 struct P_New p;
289 if (!cl)
291 LockCL;
292 cl = (Class *)FindName(&(oopbase->ClassList), classID);
293 if (cl)
294 cl->ObjectCount ++; /* We don't want the class to be freed while we work on it */
296 UnlockCL;
298 if (!cl)
299 return (NULL);
301 /* Create a new instance */
303 p.MethodID = (IPTR)M_New;
304 p.ParamPtr = msg;
306 o = (Object *)CoerceMethodA(cl, (Object *)cl, (Msg)&p);
307 if (!o)
309 cl->ObjectCount --; /* Object creation failed, release lock */
311 return (o);
314 VOID DisposeObject(Object *o)
316 IPTR methodid = (IPTR)M_Dispose;
319 Class *cl = OCLASS(o);
321 DoMethodA(o, (Msg)&methodid);
323 cl->ObjectCount --;
325 return;
328 /***************
329 ** AddClass **
330 ***************/
331 VOID AddClass(Class *cl)
334 LockCL;
335 AddTail(&(oopbase->ClassList), &(cl->ClassNode) );
336 UnlockCL;
337 return;
340 /******************
341 ** RemoveClass **
342 ******************/
343 VOID RemoveClass(Class *cl)
345 LockCL;
346 Remove(&(cl->ClassNode) );
347 UnlockCL;
349 return;