Mixed tabs/spaces to spaces.
[AROS.git] / rom / graphics / objcache.c
blob95886de80d1b5a5a2bd2baf6880561ea5e72b17b
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <proto/oop.h>
8 #include <proto/utility.h>
9 #include <proto/arossupport.h>
11 #include <oop/oop.h>
12 #include <exec/alerts.h>
13 #include <exec/memory.h>
14 #include <utility/tagitem.h>
16 #include <string.h>
18 #include "graphics_intern.h"
19 #include "objcache.h"
21 #define DEBUG 0
22 #include <aros/debug.h>
24 #define CACHE_INCREMENT 4
26 struct cacheitem
28 OOP_Object *obj;
29 BOOL used;
32 struct objcache
34 struct TagItem *create_tags;
35 struct SignalSemaphore lock;
36 struct cacheitem *cache;
37 ULONG cachesize;
38 ULONG num_objects;
39 STRPTR class_id;
40 OOP_Class *class_ptr;
44 ObjectCache *create_object_cache(OOP_Class *classPtr, STRPTR classID, struct TagItem *createTags, struct GfxBase *GfxBase)
46 struct objcache *oc;
49 if ( (NULL == classPtr && NULL == classID)
50 || (NULL != classPtr && NULL != classID) )
51 return NULL;
54 oc = AllocMem(sizeof (*oc), MEMF_PUBLIC|MEMF_CLEAR);
55 if (NULL != oc) {
57 InitSemaphore(&oc->lock);
58 oc->cachesize = CACHE_INCREMENT;
59 oc->num_objects = 0;
61 oc->create_tags = CloneTagItems(createTags);
62 if (NULL != oc->create_tags) {
63 BOOL got_class = FALSE;
65 if (NULL != classID) {
66 oc->class_id = AllocVec(strlen(classID) + 1, MEMF_ANY);
67 if (NULL != oc->class_id) {
68 strcpy(oc->class_id, classID);
69 got_class = TRUE;
71 } else {
72 oc->class_ptr = classPtr;
73 got_class = TRUE;
76 if (got_class) {
78 oc->cache = AllocMem(sizeof (*oc->cache) * oc->cachesize, MEMF_CLEAR);
79 if (NULL != oc->cache) {
80 return (ObjectCache *)oc;
83 if (NULL != oc->class_id)
84 FreeVec(oc->class_id);
86 } /* if (got class) */
88 FreeTagItems(oc->create_tags);
90 } /* if (tagitems copied) */
92 FreeMem(oc, sizeof (*oc));
93 } /* if (objcache struct allocated) */
95 return NULL;
98 VOID delete_object_cache(ObjectCache *objectCache, struct GfxBase *GfxBase)
100 struct objcache *oc;
102 ULONG i;
104 oc = (struct objcache *)objectCache;
106 ObtainSemaphore(&oc->lock);
108 /* Check if all elements in the object cache are unused */
109 for (i = 0; i < oc->num_objects; i ++) {
110 if (oc->cache[i].used) {
111 D(bug("!!!! TRYING TO DELETE AN OBJECT CACHE WITH USED OBJECTS !!!!\n"));
112 ReleaseSemaphore(&oc->lock);
113 return;
121 for (i = 0; i < oc->num_objects; i ++) {
122 if (NULL != oc->cache[i].obj)
123 OOP_DisposeObject(oc->cache[i].obj);
124 else
125 break;
128 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
130 FreeTagItems(oc->create_tags);
132 if (NULL != oc->class_id)
133 FreeVec(oc->class_id);
135 ReleaseSemaphore(&oc->lock);
137 FreeMem(oc, sizeof (*oc));
139 return;
144 OOP_Object *obtain_cache_object(ObjectCache *objectCache, struct GfxBase *GfxBase)
146 struct objcache *oc;
147 ULONG i;
148 OOP_Object *obj = NULL;
150 oc = (struct objcache *)objectCache;
152 /* bug("obtain_cache_object(classID=%s, classPtr=%p)\n"
153 , oc->class_id, oc->class_ptr);
155 ObtainSemaphore(&oc->lock);
158 /* Look to see if we can find a free object */
159 for (i = 0; i < oc->cachesize; i ++) {
160 struct cacheitem *ci;
162 ci = &oc->cache[i];
163 /* bug("cache[%d]=%p, %d\n", i, ci->obj, ci->used);
164 */ if (NULL == ci->obj) {
165 break;
166 } else {
167 if (!ci->used) {
168 obj = ci->obj;
169 ci->used = TRUE;
170 break;
175 /* bug("obj found in cache: %p\n", obj);
176 */ if (NULL == obj) {
177 struct cacheitem *ci;
178 /* No object free, so we try to create a new one.
179 But first we see if the cache can hold it */
181 if (oc->num_objects == oc->cachesize) {
182 /* Not more space in the cache, try to expand it */
183 struct cacheitem *newcache;
185 newcache = AllocMem(sizeof (*oc->cache) * (oc->cachesize + CACHE_INCREMENT), MEMF_CLEAR);
186 if (NULL == newcache)
187 goto exit;
189 /* Copy the old cache data */
190 memcpy(newcache, oc->cache, sizeof (*oc->cache) * oc->cachesize);
192 /* Free old cache */
193 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
195 /* Use new cache */
196 oc->cache = newcache;
197 oc->cachesize +=CACHE_INCREMENT;
201 /* Try to create a new object */
202 /* bug("Trying to create new object\n");
203 */ ci = &oc->cache[oc->num_objects];
205 if (oc->class_id)
206 ci->obj = OOP_NewObject(NULL, oc->class_id, oc->create_tags);
207 else
208 ci->obj = OOP_NewObject(oc->class_ptr, NULL, oc->create_tags);
210 if (NULL == ci->obj)
211 goto exit;
213 oc->num_objects ++;
214 ci->used = TRUE;
216 obj = ci->obj;
220 exit:
221 ReleaseSemaphore(&oc->lock);
223 return obj;
228 VOID release_cache_object(ObjectCache *objectCache, OOP_Object *object, struct GfxBase *GfxBase)
230 struct objcache *oc;
231 ULONG i;
232 D(BOOL found = FALSE);
234 oc = (struct objcache *)objectCache;
236 ObtainSemaphore(&oc->lock);
238 for (i = 0; i < oc->cachesize; i ++) {
239 struct cacheitem *ci;
241 ci = &oc->cache[i];
242 if (NULL == ci->obj) {
243 break;
244 } else {
245 if (ci->obj == object) {
246 /* Object found */
247 ci->used = FALSE;
248 D(found = TRUE);
253 #if DEBUG
254 if (!found)
255 bug("!!!! TRYING TO RELEASE OBJECT CACHE ELEMENT WHICH WAS NOT PRESENT IN CACHE\n");
256 #endif
258 ReleaseSemaphore(&oc->lock);
260 return;