aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llpagemem.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llcommon/llpagemem.h392
1 files changed, 392 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llpagemem.h b/linden/indra/llcommon/llpagemem.h
new file mode 100644
index 0000000..7081251
--- /dev/null
+++ b/linden/indra/llcommon/llpagemem.h
@@ -0,0 +1,392 @@
1/**
2 * @file llpagemem.h
3 *
4 * Copyright (c) 2002-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26#ifndef LL_LLPAGEMEM_H
27#define LL_LLPAGEMEM_H
28
29#if !LL_DARWIN
30#include "malloc.h"
31#endif
32
33#include "llrand.h"
34
35
36#ifndef __GNUC__
37template <class Object, U32 mPageSize=1024>
38class LLPageMemory
39{
40private:
41
42 union XObject
43 {
44 XObject *mNextFreeObject;
45 U8 mObject[sizeof(Object)];
46 };
47
48 template <U32 mPageSize> struct Page
49 {
50 XObject *mFirstFreeObject;
51 U32 mObjectCount;
52 U8 mObjects[mPageSize-8];
53
54 void init(U32 mObjPerPage)
55 {
56 XObject *o = (XObject*)&mObjects;
57 mObjectCount = 0;
58 mFirstFreeObject = o;
59
60 for (U32 i = 0; i < mObjPerPage-1; i++)
61 {
62 o->mNextFreeObject = o+1;
63 o++;
64 }
65 o->mNextFreeObject = NULL;
66 };
67
68 Object* alloc()
69 {
70 if (mFirstFreeObject)
71 {
72 XObject *ret = mFirstFreeObject;
73 mFirstFreeObject = mFirstFreeObject->mNextFreeObject;
74 ret->mNextFreeObject = NULL;
75 mObjectCount++;
76 return (Object*)&ret->mObject;
77 };
78 return NULL;
79 }
80 };
81
82 U32 mObjPerPage;
83 U32 mMaxPages;
84 U32 mObjectCount;
85
86 Page<mPageSize>* mPageMemory;
87 Page<mPageSize>* mFirstPage;
88
89public:
90 U32 precise, anywhere, fail;
91
92 void init()
93 {
94 Page<mPageSize> *p = mFirstPage;
95 for (U32 i = 0; i < mMaxPages; i++)
96 {
97 p[i].init(mObjPerPage);
98 }
99
100 precise = 0;
101 anywhere = 0;
102 fail = 0;
103 };
104
105public:
106
107 Page<mPageSize>* pageof(Object *object)
108 {
109 return (Page<mPageSize>*) ((((U32)object - 8) / mPageSize) * mPageSize );
110 }
111
112 LLPageMemory(U32 maxObjects)
113 {
114 mObjPerPage = (mPageSize-8) / sizeof(Object);
115 mMaxPages = (maxObjects / mObjPerPage) + 1;
116 mObjectCount= 0;
117
118 //printf("%d objects per page, %d pages total, %d/%d objects\n",
119 // mObjPerPage, mMaxPages, mMaxPages * mObjPerPage,maxObjects);
120
121 mPageMemory = (Page<mPageSize>*)calloc(mPageSize,mMaxPages+1);
122 mFirstPage = mPageMemory;
123 U32 fix = ((U32)mPageMemory % mPageSize);
124 if (fix) mFirstPage = (Page<mPageSize>*)((U32)mPageMemory+mPageSize-fix);
125
126 //printf("fix = %d\n",fix);
127
128 init();
129 };
130
131 LLPageMemory(void *pageMem, U32 bytes)
132 {
133 }
134
135 ~LLPageMemory()
136 {
137 if (mPageMemory)
138 {
139 free(mPageMemory);
140 }
141 }
142
143 Object* alloc(Object *after=NULL)
144 {
145 Page<mPageSize> * p = mFirstPage;
146 Object * o = NULL;
147 U32 i = mMaxPages;
148
149 if (after)
150 {
151 o = pageof(after)->alloc();
152 if (o)
153 {
154 precise++;
155 return o;
156 }
157 return NULL;
158 }
159
160 F32 frac = 1.0f / (F32)mMaxPages;
161 F32 thresh = 0.0f;
162 for (i = 0; i < mMaxPages; i++)
163 {
164 if (thresh > ((F32)p[i].mObjectCount / (F32)mObjPerPage))
165 {
166 o = p[i].alloc();
167 if (o)
168 {
169 //printf("allocating page %x obj %x\n",p, o);
170 anywhere++;
171 return o;
172 }
173 }
174 thresh += frac;
175 }
176
177 fail++;
178 return NULL;
179 };
180
181 void free(Object *o)
182 {
183 if (!o) return;
184
185 Page<mPageSize> *page = pageof(o);
186 XObject *obj = (XObject*)o;
187
188 //printf("freeing %x\n",obj);
189
190 obj->mNextFreeObject = page->mFirstFreeObject;
191 page->mFirstFreeObject = obj;
192 page->mObjectCount--;
193
194 //printf("freeing page %x %d\n",page, page->mObjectCount);
195 };
196
197 U32 indexof(Object *object)
198 {
199 if (!object) return -1;
200
201 return ((((U32)object-8) % mPageSize) / sizeof(Object)) +
202 ((pageof(object) - mFirstPage) * mObjPerPage);
203 }
204
205
206 void dump()
207 {
208
209 for (U32 i=0;i < mMaxPages;i++)
210 {
211 //printf("page %d %d/%d objects\n",i,mFirstPage[i].mObjectCount,mObjPerPage);
212 }
213 //printf("precise = %d anywhere %d ratio = %f\n",precise,anywhere,(F32)precise/(F32)(anywhere+precise));
214 //printf("fail = %d\n",fail);
215
216 }
217
218 static void test()
219 {
220 struct Foo
221 {
222 U32 ord;
223 U32 foo[8];
224 };
225
226 const U32 count = 100;
227 U32 i,c;
228 U32 mix = 50;
229
230 LLPageMemory<Foo> mem(count);
231 LLRand rand(LLUUID::getRandomSeed());
232
233 Foo *obj[count];
234
235 for (i=0;i<count;i++) obj[i] = 0;
236
237 U32 x= 0;
238 for (U32 run=0; run < 10000 ;run++)
239 {
240 U32 m =rand.llrand(count);
241 for (c=0;c < m;c++)
242 {
243 U32 j = rand.llrand(count);
244 if (obj[j])
245 {
246 mem.free(obj[j]);
247 obj[j] = 0;
248 }
249 }
250
251 m =rand.llrand(count);
252 for (c=0;c<m;c++)
253 {
254 U32 i = rand.llrand(count);
255 while (obj[i] && i < count) i++;
256
257 if (!obj[i])
258 {
259 if (i > 0) obj[i] = mem.alloc(obj[i-1]);
260 else obj[i] = mem.alloc();
261 if (obj[i]) obj[i]->ord = x++;
262 }
263 }
264 }
265
266 for (i = 0; i< count; i++)
267 {
268 //printf("obj[%2d] = %08x %02d %4d\n",i,obj[i],mem.indexof(obj[i]),(obj[i] ? obj[i]->ord : -1));
269 }
270
271 mem.dump();
272 }
273};
274
275
276template <class Object>
277class LLObjectPool
278{
279private:
280
281 class XObject
282 {
283 public:
284 Object mObject;
285 U32 mNextFreeObject;
286
287 XObject() { mObject = NULL; mNextFreeObject = 0; }
288 };
289
290 U32 mNumObjects;
291 U32 mMaxObjects;
292 XObject* mObjects;
293 U32 mFirstFreeObject;
294
295 U32 indexof(XObject *xobj) { return (xobj - mObjects); }
296
297public:
298 LLObjectPool(U32 maxObjects)
299 {
300 mMaxObjects = maxObjects;
301 mFirstFreeObject = 0;
302
303 mObjects = new XObject[mMaxObjects];
304
305 //printf("objectpool allocated %d bytes\n",sizeof(XObject) * mMaxObjects);
306
307 for (U32 i=0;i<mMaxObjects;i++) mObjects[i].mNextFreeObject = i+1;
308 };
309
310 ~LLObjectPool()
311 {
312 delete [] mObjects;
313 mObjects = NULL;
314 }
315
316 Object* alloc(Object *after=NULL)
317 {
318 XObject *obj = &mObjects[mFirstFreeObject];
319 mFirstFreeObject = obj->mNextFreeObject;
320 if (mFirstFreeObject >= mMaxObjects)
321 {
322 llerrs << "Attempted to allocate too many objects out of pool\n" << llendl;
323 llassert(0);
324 }
325 return &obj->mObject;
326 };
327
328 void free(Object *obj)
329 {
330 if (!obj) return;
331 XObject *xobj = (XObject*)obj;
332 xobj->mNextFreeObject = mFirstFreeObject;
333 mFirstFreeObject = indexof(xobj);
334 };
335
336 static void test()
337 {
338 struct Foo
339 {
340 U32 ord;
341 U32 foo[8];
342 };
343
344 const U32 count = 100;
345 U32 i,c;
346 U32 mix = 50;
347
348 LLPageMemory<Foo> mem(count);
349 LLRand rand(LLUUID::getRandomSeed());
350
351 Foo *obj[count];
352
353 for (i=0;i<count;i++) obj[i] = 0;
354
355 U32 x= 0;
356 for (U32 run=0; run < 10000 ;run++)
357 {
358 U32 m =rand.llrand(count);
359 for (c=0;c < m;c++)
360 {
361 U32 j = rand.llrand(count);
362 if (obj[j])
363 {
364 mem.free(obj[j]);
365 obj[j] = 0;
366 }
367 }
368
369 m =rand.llrand(count);
370 for (c=0;c<m;c++)
371 {
372 U32 i = rand.llrand(count);
373 while (obj[i] && i < count) i++;
374
375 if (!obj[i])
376 {
377 if (i > 0) obj[i] = mem.alloc(obj[i-1]);
378 else obj[i] = mem.alloc();
379 if (obj[i]) obj[i]->ord = x++;
380 }
381 }
382 }
383
384 for (i = 0; i< count; i++)
385 {
386 //printf("obj[%2d] = %08x %02d %4d\n",i,obj[i],mem.indexof(obj[i]),(obj[i] ? obj[i]->ord : -1));
387 }
388 }
389};
390#endif // !defined __GNUC__
391
392#endif