2 Copyright © 1997-98, The AROS Development Team. All rights reserved.
5 Desc: Demo of new OOP system
10 /* These are not necessary in the demo */
11 #define InitSemaphore(x)
12 #define ObtainSemaphore(x)
13 #define ObtainSemaphoreShared(x)
14 #define ReleaseSemaphore(x)
27 #define UB(x) ((UBYTE *)x)
28 /* could go into a library base */
29 /*struct SignalSemaphore ClassListSema;
31 struct List ClassList
;
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
);
48 Class
*MakeClass(STRPTR classID
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
65 D(bug("CreateClass(classID=%s, superID=%s, mDescr=%p, instDataSize=%ld)\n",
66 classID
, superID
, mDescr
, instDataSize
));
69 supercl
= (Class
*)FindName( &ClassList
, superID
);
72 /* Mark the class as busy, so it isn't freed while we are allocating
73 ** stuff for our class
75 supercl
->SubClassCount
++;
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
));
90 cl
->ClassID
= malloc( strlen(classID
) + 1 );
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
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
);
130 /* Initalization failed, free lock on superclass */
131 supercl
->SubClassCount
--;
133 ReturnPtr ("MakeClass", Class
*, NULL
);
138 /*************************
139 ** AllocMethodTable() **
140 *************************/
142 static BOOL
AllocMTable(Class
*cl
, ULONG numNewMethods
)
148 struct Method
*mtable
= NULL
;
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
);
177 memset(mtable
, 0, mtable_size
);
179 ReturnBool("AllocMTable", TRUE
);
183 ReturnBool ("AllocMTable", FALSE
);
187 static VOID
InitMTable(Class
*cl
, APTR
*mDescr
)
190 Class
*super
= cl
->SuperClass
;
193 D(bug("InitMTable(cl=%s, mDescr=%p\n", cl
->ClassID
, mDescr
));
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
)
232 VOID
FreeClass(Class
*cl
)
235 D(bug("FreeClass(cl=%s)\n", cl
->ClassID
));
240 /* What level are we ? */
241 if (cl
->SuperClass
== NULL
) /* Someone trying to remove the rootclass */
242 ReturnVoid("FreeClass (Someone trying to remove rootclass)");
248 ReturnVoid("FreeClass");
251 /************************
252 ** Rootclass methods **
253 ************************/
259 #define NUMROOTMETHODS 2
261 Object
*Root_New(Class
*rootcl
, Class
*cl
, Msg msg
)
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
) );
273 D(bug("Mem allocated: %p\n", o
));
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
) ));
292 ReturnVoid("Root::Dispose");
304 Class
*RootClass
= &RootClassMem
;
312 D(bug("InitOOP()\n"));
314 InitSemaphore(&ClassListSema
);
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
);
354 Class
*RootClass
= &RootClassMem
;
356 D(bug("CleanupOOP()\n"));
358 FreeMTable(RootClass
);
360 ReturnVoid("CleanupOOP");
366 Object
*NewObject(Class
*cl
, STRPTR classID
, Msg msg
)
375 cl
= (Class
*)FindName(&ClassList
, classID
);
377 cl
->ObjectCount
++; /* We don't want the class to be freed while we work on it */
384 /* Create a new instance */
389 o
= (Object
*)CoerceMethodA(cl
, (Object
*)cl
, (Msg
)&p
);
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
);
414 VOID
AddClass(Class
*cl
)
418 AddTail(&ClassList
, &(cl
->ClassNode
) );
426 VOID
RemoveClass(Class
*cl
)
429 Remove(&(cl
->ClassNode
) );