add option for classic magicmenu "mixed" menu style (pull donw on screen title, pop...
[AROS.git] / rom / graphics / objcache.c
blob2efaa0bbfcc2cebdb33f3c209dbd4c8727e545fc
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <proto/exec.h>
9 #include <proto/oop.h>
10 #include <proto/utility.h>
11 #include <proto/arossupport.h>
13 #include <oop/oop.h>
14 #include <exec/alerts.h>
15 #include <exec/memory.h>
16 #include <utility/tagitem.h>
18 #include <string.h>
20 #include "graphics_intern.h"
21 #include "objcache.h"
23 #define CACHE_INCREMENT 4
25 struct cacheitem
27 OOP_Object *obj;
28 BOOL used;
31 struct objcache
33 struct TagItem *create_tags;
34 struct SignalSemaphore lock;
35 struct cacheitem *cache;
36 ULONG cachesize;
37 ULONG num_objects;
38 STRPTR class_id;
39 OOP_Class *class_ptr;
43 ObjectCache *create_object_cache(OOP_Class *classPtr, STRPTR classID, struct TagItem *createTags, struct GfxBase *GfxBase)
45 struct objcache *oc;
48 if ( (NULL == classPtr && NULL == classID)
49 || (NULL != classPtr && NULL != classID) )
50 return NULL;
53 oc = AllocMem(sizeof (*oc), MEMF_PUBLIC|MEMF_CLEAR);
54 if (NULL != oc) {
56 InitSemaphore(&oc->lock);
57 oc->cachesize = CACHE_INCREMENT;
58 oc->num_objects = 0;
60 oc->create_tags = CloneTagItems(createTags);
61 if (NULL != oc->create_tags) {
62 BOOL got_class = FALSE;
64 if (NULL != classID) {
65 oc->class_id = AllocVec(strlen(classID) + 1, MEMF_ANY);
66 if (NULL != oc->class_id) {
67 strcpy(oc->class_id, classID);
68 got_class = TRUE;
70 } else {
71 oc->class_ptr = classPtr;
72 got_class = TRUE;
75 if (got_class) {
77 oc->cache = AllocMem(sizeof (*oc->cache) * oc->cachesize, MEMF_CLEAR);
78 if (NULL != oc->cache) {
79 return (ObjectCache *)oc;
82 if (NULL != oc->class_id)
83 FreeVec(oc->class_id);
85 } /* if (got class) */
87 FreeTagItems(oc->create_tags);
89 } /* if (tagitems copied) */
91 FreeMem(oc, sizeof (*oc));
92 } /* if (objcache struct allocated) */
94 return NULL;
97 VOID delete_object_cache(ObjectCache *objectCache, struct GfxBase *GfxBase)
99 struct objcache *oc;
101 ULONG i;
103 oc = (struct objcache *)objectCache;
105 ObtainSemaphore(&oc->lock);
107 /* Check if all elements in the object cache are unused */
108 for (i = 0; i < oc->num_objects; i ++) {
109 if (oc->cache[i].used) {
110 D(bug("!!!! TRYING TO DELETE AN OBJECT CACHE WITH USED OBJECTS !!!!\n"));
111 ReleaseSemaphore(&oc->lock);
112 return;
120 for (i = 0; i < oc->num_objects; i ++) {
121 if (NULL != oc->cache[i].obj)
122 OOP_DisposeObject(oc->cache[i].obj);
123 else
124 break;
127 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
129 FreeTagItems(oc->create_tags);
131 if (NULL != oc->class_id)
132 FreeVec(oc->class_id);
134 ReleaseSemaphore(&oc->lock);
136 FreeMem(oc, sizeof (*oc));
138 return;
143 OOP_Object *obtain_cache_object(ObjectCache *objectCache, struct GfxBase *GfxBase)
145 struct objcache *oc;
146 ULONG i;
147 OOP_Object *obj = NULL;
149 oc = (struct objcache *)objectCache;
151 /* bug("obtain_cache_object(classID=%s, classPtr=%p)\n"
152 , oc->class_id, oc->class_ptr);
154 ObtainSemaphore(&oc->lock);
157 /* Look to see if we can find a free object */
158 for (i = 0; i < oc->cachesize; i ++) {
159 struct cacheitem *ci;
161 ci = &oc->cache[i];
162 /* bug("cache[%d]=%p, %d\n", i, ci->obj, ci->used);
163 */ if (NULL == ci->obj) {
164 break;
165 } else {
166 if (!ci->used) {
167 obj = ci->obj;
168 ci->used = TRUE;
169 break;
174 /* bug("obj found in cache: %p\n", obj);
175 */ if (NULL == obj) {
176 struct cacheitem *ci;
177 /* No object free, so we try to create a new one.
178 But first we see if the cache can hold it */
180 if (oc->num_objects == oc->cachesize) {
181 /* Not more space in the cache, try to expand it */
182 struct cacheitem *newcache;
184 newcache = AllocMem(sizeof (*oc->cache) * (oc->cachesize + CACHE_INCREMENT), MEMF_CLEAR);
185 if (NULL == newcache)
186 goto exit;
188 /* Copy the old cache data */
189 memcpy(newcache, oc->cache, sizeof (*oc->cache) * oc->cachesize);
191 /* Free old cache */
192 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
194 /* Use new cache */
195 oc->cache = newcache;
196 oc->cachesize +=CACHE_INCREMENT;
200 /* Try to create a new object */
201 /* bug("Trying to create new object\n");
202 */ ci = &oc->cache[oc->num_objects];
204 if (oc->class_id)
205 ci->obj = OOP_NewObject(NULL, oc->class_id, oc->create_tags);
206 else
207 ci->obj = OOP_NewObject(oc->class_ptr, NULL, oc->create_tags);
209 if (NULL == ci->obj)
210 goto exit;
212 oc->num_objects ++;
213 ci->used = TRUE;
215 obj = ci->obj;
219 exit:
220 ReleaseSemaphore(&oc->lock);
222 return obj;
227 VOID release_cache_object(ObjectCache *objectCache, OOP_Object *object, struct GfxBase *GfxBase)
229 struct objcache *oc;
230 ULONG i;
231 D(BOOL found = FALSE);
233 oc = (struct objcache *)objectCache;
235 ObtainSemaphore(&oc->lock);
237 for (i = 0; i < oc->cachesize; i ++) {
238 struct cacheitem *ci;
240 ci = &oc->cache[i];
241 if (NULL == ci->obj) {
242 break;
243 } else {
244 if (ci->obj == object) {
245 /* Object found */
246 ci->used = FALSE;
247 D(found = TRUE);
252 #if DEBUG
253 if (!found)
254 bug("!!!! TRYING TO RELEASE OBJECT CACHE ELEMENT WHICH WAS NOT PRESENT IN CACHE\n");
255 #endif
257 ReleaseSemaphore(&oc->lock);
259 return;