debug.library: use quick sort to sort the segments
[AROS.git] / rom / graphics / objcache.c
blob00b16b9969eb9670f0402fdee2ea2d09ead7e3dc
1 /*
2 Copyright © 1995-2013, 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 FreeVec(oc->class_id);
84 } /* if (got class) */
86 FreeTagItems(oc->create_tags);
88 } /* if (tagitems copied) */
90 FreeMem(oc, sizeof (*oc));
91 } /* if (objcache struct allocated) */
93 return NULL;
96 VOID delete_object_cache(ObjectCache *objectCache, struct GfxBase *GfxBase)
98 struct objcache *oc;
100 ULONG i;
102 oc = (struct objcache *)objectCache;
104 ObtainSemaphore(&oc->lock);
106 /* Check if all elements in the object cache are unused */
107 for (i = 0; i < oc->num_objects; i ++) {
108 if (oc->cache[i].used) {
109 D(bug("!!!! TRYING TO DELETE AN OBJECT CACHE WITH USED OBJECTS !!!!\n"));
110 ReleaseSemaphore(&oc->lock);
111 return;
119 for (i = 0; i < oc->num_objects; i ++) {
120 if (NULL != oc->cache[i].obj)
121 OOP_DisposeObject(oc->cache[i].obj);
122 else
123 break;
126 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
128 FreeTagItems(oc->create_tags);
130 FreeVec(oc->class_id);
132 ReleaseSemaphore(&oc->lock);
134 FreeMem(oc, sizeof (*oc));
136 return;
141 OOP_Object *obtain_cache_object(ObjectCache *objectCache, struct GfxBase *GfxBase)
143 struct objcache *oc;
144 ULONG i;
145 OOP_Object *obj = NULL;
147 oc = (struct objcache *)objectCache;
149 /* bug("obtain_cache_object(classID=%s, classPtr=%p)\n"
150 , oc->class_id, oc->class_ptr);
152 ObtainSemaphore(&oc->lock);
155 /* Look to see if we can find a free object */
156 for (i = 0; i < oc->cachesize; i ++) {
157 struct cacheitem *ci;
159 ci = &oc->cache[i];
160 /* bug("cache[%d]=%p, %d\n", i, ci->obj, ci->used);
161 */ if (NULL == ci->obj) {
162 break;
163 } else {
164 if (!ci->used) {
165 obj = ci->obj;
166 ci->used = TRUE;
167 break;
172 /* bug("obj found in cache: %p\n", obj);
173 */ if (NULL == obj) {
174 struct cacheitem *ci;
175 /* No object free, so we try to create a new one.
176 But first we see if the cache can hold it */
178 if (oc->num_objects == oc->cachesize) {
179 /* Not more space in the cache, try to expand it */
180 struct cacheitem *newcache;
182 newcache = AllocMem(sizeof (*oc->cache) * (oc->cachesize + CACHE_INCREMENT), MEMF_CLEAR);
183 if (NULL == newcache)
184 goto exit;
186 /* Copy the old cache data */
187 memcpy(newcache, oc->cache, sizeof (*oc->cache) * oc->cachesize);
189 /* Free old cache */
190 FreeMem(oc->cache, sizeof (*oc->cache) * oc->cachesize);
192 /* Use new cache */
193 oc->cache = newcache;
194 oc->cachesize +=CACHE_INCREMENT;
198 /* Try to create a new object */
199 /* bug("Trying to create new object\n");
200 */ ci = &oc->cache[oc->num_objects];
202 if (oc->class_id)
203 ci->obj = OOP_NewObject(NULL, oc->class_id, oc->create_tags);
204 else
205 ci->obj = OOP_NewObject(oc->class_ptr, NULL, oc->create_tags);
207 if (NULL == ci->obj)
208 goto exit;
210 oc->num_objects ++;
211 ci->used = TRUE;
213 obj = ci->obj;
217 exit:
218 ReleaseSemaphore(&oc->lock);
220 return obj;
225 VOID release_cache_object(ObjectCache *objectCache, OOP_Object *object, struct GfxBase *GfxBase)
227 struct objcache *oc;
228 ULONG i;
229 D(BOOL found = FALSE);
231 oc = (struct objcache *)objectCache;
233 ObtainSemaphore(&oc->lock);
235 for (i = 0; i < oc->cachesize; i ++) {
236 struct cacheitem *ci;
238 ci = &oc->cache[i];
239 if (NULL == ci->obj) {
240 break;
241 } else {
242 if (ci->obj == object) {
243 /* Object found */
244 ci->used = FALSE;
245 D(found = TRUE);
250 #if DEBUG
251 if (!found)
252 bug("!!!! TRYING TO RELEASE OBJECT CACHE ELEMENT WHICH WAS NOT PRESENT IN CACHE\n");
253 #endif
255 ReleaseSemaphore(&oc->lock);
257 return;