1 krisbash 1.1 #include <pal/ownedmemory.h>
2 #include <pal/hashmap.h>
3 #include <pal/lock.h>
4
5 static Lock s_ownedMemoryLock = LOCK_INITIALIZER;
6 static HashMap _ownedMemoryHashmap;
7 static PAL_Boolean _ownedMemoryInitialized = PAL_FALSE;
8
9 /*
10 **==============================================================================
11 **
12 ** OwnedMemory hash implementation
13 **
14 **==============================================================================
15 */
16
17 typedef struct _OwnedMemoryBucket /* derives from HashBucket */
18 {
19 struct _OwnedMemoryBucket* next;
20 void *key;
21 }
22 krisbash 1.1 OwnedMemoryBucket;
23
24 static size_t _OwnedMemoryHash(
25 const HashBucket* bucket_)
26 {
27 OwnedMemoryBucket* bucket = (OwnedMemoryBucket*)bucket_;
28 void *key = bucket->key;
29 size_t h = (size_t)key >> 4;
30 return h;
31 }
32
33 static int _OwnedMemoryEqual(
34 const HashBucket* bucket1_,
35 const HashBucket* bucket2_)
36 {
37 OwnedMemoryBucket* bucket1 = (OwnedMemoryBucket*)bucket1_;
38 OwnedMemoryBucket* bucket2 = (OwnedMemoryBucket*)bucket2_;
39 return (bucket1->key == bucket2->key);
40 }
41
42 static void _OwnedMemoryRelease(
43 krisbash 1.1 HashBucket* bucket_)
44 {
45 OwnedMemoryBucket* bucket = (OwnedMemoryBucket*)bucket_;
46
47 PAL_Free(bucket->key);
48 PAL_Free(bucket);
49 }
50
51 /*
52 * Called by atexit handler
53 */
54 static void ATEXIT_API _OwnedMemory_DeInitialize(void)
55 {
56 Lock_Acquire(&s_ownedMemoryLock);
57
58 if(_ownedMemoryInitialized)
59 {
60 HashMap_Destroy(&_ownedMemoryHashmap);
61 }
62
63 Lock_Release(&s_ownedMemoryLock);
64 krisbash 1.1 }
65
66 /*
67 * Assumes that it is called under lock
68 */
69 PAL_Boolean _OwnedMemory_Initialize()
70 {
71 int result = 0;
72
73 if(!_ownedMemoryInitialized)
74 {
75 result = HashMap_Init(
76 &_ownedMemoryHashmap,
77 64,
78 _OwnedMemoryHash,
79 _OwnedMemoryEqual,
80 _OwnedMemoryRelease);
81
82 if(result == 0)
83 {
84 PAL_Atexit(_OwnedMemory_DeInitialize);
85 krisbash 1.1
86 _ownedMemoryInitialized = PAL_TRUE;
87 }
88 }
89
90 return (result == 0);
91 }
92
93 /*
94 * Initializes HashMap if not done so yet
95 * allocates a hash bucket, allocates new memory; stores the bucket in hashmap
96 * returns the new memory ptr
97 */
98 void *OwnedMemory_Alloc(size_t length)
99 {
100 OwnedMemoryBucket* bucket = NULL;
101 void *newMemory = NULL;
102
103 Lock_Acquire(&s_ownedMemoryLock);
104 if(!_OwnedMemory_Initialize())
105 goto end;
106 krisbash 1.1
107 bucket = (OwnedMemoryBucket*)PAL_Calloc(1, sizeof(OwnedMemoryBucket));
108 if(!bucket)
109 goto end;
110
111 newMemory = PAL_Calloc(1, length);
112
113 if(!newMemory)
114 {
115 PAL_Free(bucket);
116 goto end;
117 }
118 bucket->key = newMemory;
119
120 if(HashMap_Insert(&_ownedMemoryHashmap, (HashBucket *) bucket) != 0)
121 {
122 /* this will never happen since same memory location will not be returned
123 on two allocations unless first one is freed by the user explicitly
124 giving the error to the user by returning NULL in this case */
125 PAL_Free(bucket);
126 PAL_Free(newMemory);
127 krisbash 1.1 newMemory = NULL;
128 }
129
130 end:
131 Lock_Release(&s_ownedMemoryLock);
132
133 return newMemory;
134 }
135
136 /*
137 * Attempts to remove the ptr from the hash map and free it;
138 * returns whether it succeeded in doing so or not
139 */
140 int OwnedMemory_Free(void *ptr)
141 {
142 int result = 0;
143 OwnedMemoryBucket bucket;
144 bucket.key = ptr;
145
146 Lock_Acquire(&s_ownedMemoryLock);
147
148 krisbash 1.1 result = HashMap_Remove(&_ownedMemoryHashmap, (const HashBucket *) &bucket);
149
150 Lock_Release(&s_ownedMemoryLock);
151
152 return result;
153 }
|