Re-enabled use of AROS.Boot file due to lack of general enthusiasm for
[tangerine.git] / test / oop2 / oop.c
blobd2d7328f633b23644f90fa42784c2fc9ec7358f9
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 /* These are not necessary in the demo */
11 #define InitSemaphore(x)
12 #define ObtainSemaphore(x)
13 #define ObtainSemaphoreShared(x)
14 #define ReleaseSemaphore(x)
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdlib.h>
20 #include "types.h"
21 #include "oop.h"
22 #include "protos.h"
24 #define DEBUG 0
25 #include "debug.h"
27 #define UB(x) ((UBYTE *)x)
28 /* could go into a library base */
29 /*struct SignalSemaphore ClassListSema;
31 struct List ClassList;
32 Class RootClassMem;
34 /* Method implementations */
37 /******************************************************************/
39 /* The oop system code */
41 static BOOL AllocMTable(Class *cl, ULONG numNewMethods);
42 static VOID InitMTable(Class *cl, APTR *mDescr);
43 static VOID FreeMTable(Class *cl);
45 /****************
46 ** MakeClass **
47 ****************/
48 Class *MakeClass(STRPTR classID
49 ,STRPTR superID
50 ,APTR *mDescr
51 ,ULONG instDataSize
52 ,ULONG numNewMethods)
54 #define UB(x) ((UBYTE *)x)
56 #define UnlockCL ReleaseSemaphore( &ClassListSema )
57 #define LockCLShared ObtainSemaphoreShared( &ClassListSema )
58 #define LockCL ObtainSemaphore( &ClassListSema )
60 #define ClassID ClassNode.ln_Name
62 Class *cl, *supercl;
64 /* Find superclass */
65 D(bug("CreateClass(classID=%s, superID=%s, mDescr=%p, instDataSize=%ld)\n",
66 classID, superID, mDescr, instDataSize));
68 LockCL;
69 supercl = (Class *)FindName( &ClassList, superID);
70 if (supercl)
72 /* Mark the class as busy, so it isn't freed while we are allocating
73 ** stuff for our class
75 supercl->SubClassCount ++;
77 UnlockCL;
79 if (!supercl)
80 return (FALSE);
82 D(bug("Found superclass %s\n", supercl->ClassID));
84 /* Allocate class structure */
85 D(bug("Allocating class of size %d\n", sizeof (Class) ));
86 cl = malloc(sizeof (Class));
87 if (cl)
90 cl->ClassID = malloc( strlen(classID) + 1 );
92 if (cl->ClassID)
95 /* Copy class ID */
96 strcpy(cl->ClassID, classID);
97 D(bug("class ID copied\n"));
99 /* Must be done before calling AllocMethodTable().
100 ** This is because AllocMethodTable() must know the number
101 ** of new methods.
103 cl->SuperClass = supercl;
104 cl->NumMethods = numNewMethods;
106 D(bug("Number of methods introduced by class: %ld\n", numNewMethods));
108 /* Allocate method table for class */
109 if ( AllocMTable(cl, numNewMethods) )
111 /* Initialize method table with supplied methods */
112 InitMTable(cl, mDescr);
114 /* Well, same as in BOOPSI */
115 cl->InstOffset = supercl->InstOffset + supercl->InstSize;
116 cl->InstSize = instDataSize;
118 supercl->SubClassCount ++;
120 ReturnPtr ("MakeClass", Class *, cl);
125 free(cl->ClassID);
127 free(cl);
130 /* Initalization failed, free lock on superclass */
131 supercl->SubClassCount --;
133 ReturnPtr ("MakeClass", Class *, NULL);
135 } /* CreateClass */
138 /*************************
139 ** AllocMethodTable() **
140 *************************/
142 static BOOL AllocMTable(Class *cl, ULONG numNewMethods)
145 LONG mtable_size;
147 ULONG nummethods;
148 struct Method *mtable = NULL;
150 Class *super;
152 D(bug("AllocMTable(class=%s, numNewMethods=%ld)\n",
153 cl->ClassID, numNewMethods));
155 /* Count the number of methods for superclasses.
156 ** Note that the same methods are NOT counted twice as
157 ** class->NumMethods is the number of methods that are new for 'class'.
159 nummethods = numNewMethods;
160 for (super = cl->SuperClass; super; super = super->SuperClass)
161 nummethods += super->NumMethods;
163 D(bug("Total number of methods: %ld\n", nummethods));
165 /* Calculate method table size, counted in bytes */
166 mtable_size = UB(&mtable[nummethods]) - UB(&mtable[0]);
168 D(bug("Method table size: %ld\n", mtable_size));
170 /* Save hash table size, counted in entries */
171 cl->MTableSize = nummethods;
173 /* Allocate hash table */
174 mtable = malloc(mtable_size);
175 if (mtable)
177 memset(mtable, 0, mtable_size);
178 cl->MTable = mtable;
179 ReturnBool("AllocMTable", TRUE);
183 ReturnBool ("AllocMTable", FALSE);
187 static VOID InitMTable(Class *cl, APTR *mDescr)
190 Class *super = cl->SuperClass;
191 ULONG i;
193 D(bug("InitMTable(cl=%s, mDescr=%p\n", cl->ClassID, mDescr));
195 if (super)
197 ULONG super_mtable_size;
199 D(bug("Superclass found: %s\n", super->ClassID));
200 super_mtable_size = UB(&(super->MTable[super->MTableSize]))
201 - UB(&(super->MTable[0]));
203 memcpy(cl->MTable, super->MTable, super_mtable_size);
206 /* Override using the methods supplied in MakeClass() */
207 D(bug("Overriding methods\n"));
209 for (i = 0; i < cl->MTableSize; i ++)
211 if (mDescr[i] != NULL)
214 D(bug("Overriding method %ld\n", i));
215 cl->MTable[i].MethodFunc = mDescr[i];
216 cl->MTable[i].m_Class = cl;
219 ReturnVoid("InitMTable");
223 static VOID FreeMTable(Class *cl)
225 free(cl->MTable);
226 return;
229 /*****************
230 ** Freelass() **
231 *****************/
232 VOID FreeClass(Class *cl)
235 D(bug("FreeClass(cl=%s)\n", cl->ClassID));
238 if (cl)
240 /* What level are we ? */
241 if (cl->SuperClass == NULL) /* Someone trying to remove the rootclass */
242 ReturnVoid("FreeClass (Someone trying to remove rootclass)");
244 FreeMTable(cl);
245 free(cl->ClassID);
246 free(cl);
248 ReturnVoid("FreeClass");
251 /************************
252 ** Rootclass methods **
253 ************************/
254 struct RootData
256 ULONG dummy;
259 #define NUMROOTMETHODS 2
261 Object *Root_New(Class *rootcl, Class *cl, Msg msg)
263 struct _Object *o;
265 D(bug("Root::New(cl=%s, msg = %p)\n",
266 cl->ClassNode.ln_Name, msg));
268 /* Allocate memory for the object */
269 D(bug("Object size: %ld\n", cl->InstOffset + cl->InstSize + sizeof (struct _Object)));
270 o = malloc(cl->InstOffset + cl->InstSize + sizeof (struct _Object) );
271 if (o)
273 D(bug("Mem allocated: %p\n", o));
274 o->o_Class = cl;
276 cl->ObjectCount ++;
278 ReturnPtr ("Root::New", Object *, BASEOBJECT(o) );
281 ReturnPtr ("Root::New", Object *, NULL);
284 VOID Root_Dispose(Class *cl, Object *o, Msg msg)
286 D(bug("Root::Dispose(o=%p, oclass=%s)\n", o, _OBJECT(o)->o_Class->ClassNode.ln_Name));
288 _OBJECT(o)->o_Class->ObjectCount --;
289 D(bug("Object mem: %p\n", _OBJECT(o) ));
290 free(_OBJECT(o));
292 ReturnVoid("Root::Dispose");
296 /****************
297 ** InitOOP() **
298 ****************/
302 BOOL InitOOP()
304 Class *RootClass = &RootClassMem;
305 APTR RootMTable[] =
307 Root_New,
308 Root_Dispose,
309 NULL
312 D(bug("InitOOP()\n"));
314 InitSemaphore(&ClassListSema);
315 NEWLIST(&ClassList);
318 /* We must initialize the rootclass by hand */
320 RootClass->SuperClass = NULL; /* !!! Very important to do before AllocMTable() !!! */
321 if (AllocMTable(RootClass, NUM_ROOT_METHODS))
323 D(bug("MTable allocated\n"));
324 InitMTable(RootClass, RootMTable);
326 /* Fill in other stuff into the class structure */
327 RootClass->ClassNode.ln_Name = ROOTCLASS;
328 RootClass->InstOffset = 0UL;
329 RootClass->InstSize = sizeof (struct RootData);
330 RootClass->NumMethods = NUMROOTMETHODS;
331 RootClass->SubClassCount = 0UL;
332 RootClass->ObjectCount = 0UL;
333 RootClass->SuperClass = NULL;
335 /* Add the class. Arbitration not necessary, as
336 ** noone know about us yet
338 AddTail(&ClassList, &(RootClass->ClassNode) );
340 ReturnBool ("InitOOP", TRUE);
344 ReturnBool ("InitOOP", FALSE);
348 /*******************
349 ** CleanupOOP() **
350 *******************/
351 VOID CleanupOOP()
354 Class *RootClass = &RootClassMem;
356 D(bug("CleanupOOP()\n"));
358 FreeMTable(RootClass);
360 ReturnVoid("CleanupOOP");
363 /*****************
364 ** NewObject() **
365 *****************/
366 Object *NewObject(Class *cl, STRPTR classID, Msg msg)
368 Object *o;
370 struct P_New p;
372 if (!cl)
374 LockCL;
375 cl = (Class *)FindName(&ClassList, classID);
376 if (cl)
377 cl->ObjectCount ++; /* We don't want the class to be freed while we work on it */
379 UnlockCL;
381 if (!cl)
382 return (NULL);
384 /* Create a new instance */
386 p.MethodID = M_New;
387 p.ParamPtr = msg;
389 o = (Object *)CoerceMethodA(cl, (Object *)cl, (Msg)&p);
390 if (!o)
392 cl->ObjectCount --; /* Object creation failed, release lock */
394 ReturnPtr ("NewInstance", Object *, o);
397 VOID DisposeObject(Object *o)
399 ULONG methodid = M_Dispose;
402 Class *cl = OCLASS(o);
404 DoMethodA(o, (Msg)&methodid);
406 cl->ObjectCount --;
408 return;
411 /***************
412 ** AddClass **
413 ***************/
414 VOID AddClass(Class *cl)
417 LockCL;
418 AddTail(&ClassList, &(cl->ClassNode) );
419 UnlockCL;
420 return;
423 /******************
424 ** RemoveClass **
425 ******************/
426 VOID RemoveClass(Class *cl)
428 LockCL;
429 Remove(&(cl->ClassNode) );
430 UnlockCL;
432 return;