Restored work-around for hangs when trying to use disk-based handlers
[tangerine.git] / rom / oop / support.c
blob3c2dd279013dc18c9f1d58cc62450d24b7bcf707
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <string.h>
11 #include <proto/exec.h>
12 #include <exec/memory.h>
13 #include <exec/lists.h>
15 #include <proto/oop.h>
16 #include <oop/oop.h>
18 #include "intern.h"
19 #include "hash.h"
20 #include "private.h"
23 #undef SDEBUG
24 #undef DEBUG
25 #define SDEBUG 0
26 #define DEBUG 0
27 #include <aros/debug.h>
30 #define UB(x) ((UBYTE *)x)
32 #define ClassID PPart.ClassNode.ln_Name
37 /***************
38 ** GetIDs() **
39 ***************/
41 /* Used to do several string interface ID to numeric interface ID mappings in one call */
42 BOOL GetIDs(struct IDDescr *idDescr, struct IntOOPBase *OOPBase)
44 while (idDescr->ID)
46 *(idDescr->Storage) = OOP_ObtainAttrBase(idDescr->ID);
47 if (0UL == *(idDescr->Storage))
48 return (FALSE);
50 idDescr ++;
52 return (TRUE);
55 /*********************
56 ** hasinterface() **
57 *********************/
59 BOOL hasinterface(OOP_Class *cl, STRPTR interface_id)
61 ULONG num_methods = 0UL;
62 return (meta_getifinfo((OOP_Object *)cl, interface_id, &num_methods) != NULL) ? TRUE : FALSE;
65 /**********************
66 ** findinterface() **
67 **********************/
68 struct IFMethod *findinterface(OOP_Class *cl, STRPTR interface_id)
70 ULONG num_methods = 0UL;
72 return meta_getifinfo((OOP_Object *)cl, interface_id, &num_methods);
75 /***************************
76 ** init_mi_methodbase() **
77 ***************************/
78 /* Intializes a methodbase to be used for the classes supporting multiple
79 interfaces (MI), ie. objects of th IFMeta class.
81 BOOL init_mi_methodbase(STRPTR interface_id, ULONG *methodbase_ptr, struct IntOOPBase *OOPBase)
83 ULONG mbase;
84 BOOL success;
85 EnterFunc(bug("init_mi_methodbase(interface_id=%s)\n", interface_id));
87 mbase = OOPBase->ob_CurrentMethodBase ++;
88 mbase <<= NUM_METHOD_BITS;
89 success = init_methodbase(interface_id, mbase, methodbase_ptr, OOPBase);
90 if (success)
92 if (*methodbase_ptr != mbase)
94 /* Methodbase had allready been inited, reset current ID */
95 OOPBase->ob_CurrentMethodBase --;
98 ReturnBool ("init_mi_methodbase", success);
102 /************************
103 ** init_methodbase() **
104 ************************/
106 /* Adds the local ID equivalent to the global string ID
107 to the ID hashtable
110 BOOL init_methodbase(STRPTR interface_id, ULONG methodbase, ULONG *methodbase_ptr, struct IntOOPBase *OOPBase)
112 BOOL inited = FALSE;
113 struct iid_bucket *idb = NULL;
114 struct HashTable *iidtable = OOPBase->ob_IIDTable;
117 EnterFunc(bug("init_methodbase(interface_id=%s, methodbase=%ld)\n",
118 interface_id, methodbase));
120 ObtainSemaphore(&OOPBase->ob_IIDTableLock);
122 /* Has ID allready been mapped to a methodbase ? */
123 idb = (struct iid_bucket *)iidtable->Lookup(iidtable, (IPTR)interface_id, (struct IntOOPBase *)OOPBase);
124 if (idb)
126 if (idb->methodbase == (ULONG)-1)
128 idb->methodbase = methodbase;
131 *methodbase_ptr = idb->methodbase;
132 inited = TRUE;
135 else
138 D(bug("Initing methodbase...\n"));
141 /* If not, then map it and create a new bucket in the
142 ** hashtable to store it
144 idb = AllocMem(sizeof (struct iid_bucket), MEMF_ANY);
145 if (idb)
147 idb->interface_id = AllocVec(strlen(interface_id) + 1, MEMF_ANY);
148 if (idb->interface_id)
150 D(bug("Allocated bucket\n"));
151 strcpy(idb->interface_id, interface_id);
153 /* Get next free ID, and increase the free ID to mark it as used */
155 idb->methodbase = methodbase;
156 *methodbase_ptr = methodbase;
158 /* Leave attrbase field unitialized */
159 idb->attrbase = -1UL;
161 /* Insert bucket into hash table */
162 InsertBucket(iidtable, (struct Bucket *)idb, (struct IntOOPBase *)OOPBase);
163 inited = TRUE;
165 else
167 FreeMem(idb, sizeof (struct iid_bucket));
171 if (idb)
173 idb->refcount ++;
176 ReleaseSemaphore(&OOPBase->ob_IIDTableLock);
178 ReturnBool ("init_methodbase", inited);
182 /* Release a interface bucket */
183 VOID release_idbucket(STRPTR interface_id, struct IntOOPBase *OOPBase)
185 /* Look up ID */
186 struct iid_bucket *idb;
187 struct HashTable *iidtable = GetOBase(OOPBase)->ob_IIDTable;
189 ObtainSemaphore(&OOPBase->ob_IIDTableLock);
190 /* Has ID allready been mapped to a numeric ID ? */
191 idb = (struct iid_bucket *)iidtable->Lookup(iidtable, (IPTR)interface_id, OOPBase);
192 if (idb)
194 /* Reduce interface bucket's refcount */
195 idb->refcount --;
197 /* Last ref released ? */
198 if (idb->refcount == 0)
200 /* Remove and free the bucket */
201 RemoveBucket(iidtable, (struct Bucket *)idb);
202 FreeVec(idb->interface_id);
203 FreeMem(idb, sizeof (struct iid_bucket));
207 ReleaseSemaphore(&OOPBase->ob_IIDTableLock);
209 ReturnVoid ("ReleaseAttrBase");
212 /* Increase an idbucket's refcount, to lock it.
213 Calling this function MUST ONLY be used for IFs
214 that are known to exist in the IID table
216 VOID obtain_idbucket(STRPTR interface_id, struct IntOOPBase *OOPBase)
218 struct iid_bucket *idb;
219 struct HashTable *iidtable = GetOBase(OOPBase)->ob_IIDTable;
221 ObtainSemaphore(&OOPBase->ob_IIDTableLock);
222 /* Has ID allready been mapped to a numeric ID ? */
223 idb = (struct iid_bucket *)iidtable->Lookup(iidtable, (IPTR)interface_id, OOPBase);
224 /* Reduce interface bucket's refcount */
225 idb->refcount ++;
226 ReleaseSemaphore(&OOPBase->ob_IIDTableLock);
228 return;