~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/egl/main/eglhash.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * \file hash.c
3
 
 * Generic hash table. 
4
 
 *
5
 
 * This code taken from Mesa and adapted.
6
 
 */
7
 
 
8
 
#include <assert.h>
9
 
#include <stdlib.h>
10
 
#include <stdio.h>
11
 
#include "eglhash.h"
12
 
 
13
 
 
14
 
#define TABLE_SIZE 1023  /**< Size of lookup table/array */
15
 
 
16
 
#define HASH_FUNC(K)  ((K) % TABLE_SIZE)
17
 
 
18
 
 
19
 
/*
20
 
 * Unfinished mutex stuff
21
 
 */
22
 
 
23
 
typedef int _EGLMutex;
24
 
 
25
 
static void
26
 
_eglInitMutex(_EGLMutex m)
27
 
{
28
 
}
29
 
 
30
 
static void
31
 
_eglDestroyMutex(_EGLMutex m)
32
 
{
33
 
}
34
 
 
35
 
static void
36
 
_eglLockMutex(_EGLMutex m)
37
 
{
38
 
}
39
 
 
40
 
static void
41
 
_eglUnlockMutex(_EGLMutex m)
42
 
{
43
 
}
44
 
 
45
 
 
46
 
 
47
 
typedef struct _egl_hashentry _EGLHashentry;
48
 
 
49
 
struct _egl_hashentry
50
 
{
51
 
   EGLuint Key;            /**< the entry's key */
52
 
   void *Data;             /**< the entry's data */
53
 
   _EGLHashentry *Next;    /**< pointer to next entry */
54
 
};
55
 
 
56
 
 
57
 
struct _egl_hashtable
58
 
{
59
 
   _EGLHashentry *Table[TABLE_SIZE];  /**< the lookup table */
60
 
   EGLuint MaxKey;                    /**< highest key inserted so far */
61
 
   _EGLMutex Mutex;                   /**< mutual exclusion lock */
62
 
};
63
 
 
64
 
 
65
 
/**
66
 
 * Create a new hash table.
67
 
 * 
68
 
 * \return pointer to a new, empty hash table.
69
 
 */
70
 
_EGLHashtable *
71
 
_eglNewHashTable(void)
72
 
{
73
 
   _EGLHashtable *table = (_EGLHashtable *) calloc(1, sizeof(_EGLHashtable));
74
 
   if (table) {
75
 
      _eglInitMutex(table->Mutex);
76
 
      table->MaxKey = 1;
77
 
   }
78
 
   return table;
79
 
}
80
 
 
81
 
 
82
 
 
83
 
/**
84
 
 * Delete a hash table.
85
 
 * Frees each entry on the hash table and then the hash table structure itself.
86
 
 * Note that the caller should have already traversed the table and deleted
87
 
 * the objects in the table (i.e. We don't free the entries' data pointer).
88
 
 *
89
 
 * \param table the hash table to delete.
90
 
 */
91
 
void
92
 
_eglDeleteHashTable(_EGLHashtable *table)
93
 
{
94
 
   EGLuint i;
95
 
   assert(table);
96
 
   for (i = 0; i < TABLE_SIZE; i++) {
97
 
      _EGLHashentry *entry = table->Table[i];
98
 
      while (entry) {
99
 
         _EGLHashentry *next = entry->Next;
100
 
         free(entry);
101
 
         entry = next;
102
 
      }
103
 
   }
104
 
   _eglDestroyMutex(table->Mutex);
105
 
   free(table);
106
 
}
107
 
 
108
 
 
109
 
 
110
 
/**
111
 
 * Lookup an entry in the hash table.
112
 
 * 
113
 
 * \param table the hash table.
114
 
 * \param key the key.
115
 
 * 
116
 
 * \return pointer to user's data or NULL if key not in table
117
 
 */
118
 
void *
119
 
_eglHashLookup(const _EGLHashtable *table, EGLuint key)
120
 
{
121
 
   EGLuint pos;
122
 
   const _EGLHashentry *entry;
123
 
 
124
 
   assert(table);
125
 
 
126
 
   if (!key)
127
 
      return NULL;
128
 
 
129
 
   pos = HASH_FUNC(key);
130
 
   entry = table->Table[pos];
131
 
   while (entry) {
132
 
      if (entry->Key == key) {
133
 
         return entry->Data;
134
 
      }
135
 
      entry = entry->Next;
136
 
   }
137
 
   return NULL;
138
 
}
139
 
 
140
 
 
141
 
 
142
 
/**
143
 
 * Insert a key/pointer pair into the hash table.  
144
 
 * If an entry with this key already exists we'll replace the existing entry.
145
 
 * 
146
 
 * \param table the hash table.
147
 
 * \param key the key (not zero).
148
 
 * \param data pointer to user data.
149
 
 */
150
 
void
151
 
_eglHashInsert(_EGLHashtable *table, EGLuint key, void *data)
152
 
{
153
 
   /* search for existing entry with this key */
154
 
   EGLuint pos;
155
 
   _EGLHashentry *entry;
156
 
 
157
 
   assert(table);
158
 
   assert(key);
159
 
 
160
 
   _eglLockMutex(table->Mutex);
161
 
 
162
 
   if (key > table->MaxKey)
163
 
      table->MaxKey = key;
164
 
 
165
 
   pos = HASH_FUNC(key);
166
 
   entry = table->Table[pos];
167
 
   while (entry) {
168
 
      if (entry->Key == key) {
169
 
         /* replace entry's data */
170
 
         entry->Data = data;
171
 
         _eglUnlockMutex(table->Mutex);
172
 
         return;
173
 
      }
174
 
      entry = entry->Next;
175
 
   }
176
 
 
177
 
   /* alloc and insert new table entry */
178
 
   entry = (_EGLHashentry *) malloc(sizeof(_EGLHashentry));
179
 
   entry->Key = key;
180
 
   entry->Data = data;
181
 
   entry->Next = table->Table[pos];
182
 
   table->Table[pos] = entry;
183
 
 
184
 
   _eglUnlockMutex(table->Mutex);
185
 
}
186
 
 
187
 
 
188
 
 
189
 
/**
190
 
 * Remove an entry from the hash table.
191
 
 * 
192
 
 * \param table the hash table.
193
 
 * \param key key of entry to remove.
194
 
 *
195
 
 * While holding the hash table's lock, searches the entry with the matching
196
 
 * key and unlinks it.
197
 
 */
198
 
void
199
 
_eglHashRemove(_EGLHashtable *table, EGLuint key)
200
 
{
201
 
   EGLuint pos;
202
 
   _EGLHashentry *entry, *prev;
203
 
 
204
 
   assert(table);
205
 
   assert(key);
206
 
 
207
 
   _eglLockMutex(table->Mutex);
208
 
 
209
 
   pos = HASH_FUNC(key);
210
 
   prev = NULL;
211
 
   entry = table->Table[pos];
212
 
   while (entry) {
213
 
      if (entry->Key == key) {
214
 
         /* found it! */
215
 
         if (prev) {
216
 
            prev->Next = entry->Next;
217
 
         }
218
 
         else {
219
 
            table->Table[pos] = entry->Next;
220
 
         }
221
 
         free(entry);
222
 
         _eglUnlockMutex(table->Mutex);
223
 
         return;
224
 
      }
225
 
      prev = entry;
226
 
      entry = entry->Next;
227
 
   }
228
 
 
229
 
   _eglUnlockMutex(table->Mutex);
230
 
}
231
 
 
232
 
 
233
 
 
234
 
/**
235
 
 * Get the key of the "first" entry in the hash table.
236
 
 * 
237
 
 * This is used in the course of deleting all display lists when
238
 
 * a context is destroyed.
239
 
 * 
240
 
 * \param table the hash table
241
 
 * 
242
 
 * \return key for the "first" entry in the hash table.
243
 
 *
244
 
 * While holding the lock, walks through all table positions until finding
245
 
 * the first entry of the first non-empty one.
246
 
 */
247
 
EGLuint
248
 
_eglHashFirstEntry(_EGLHashtable *table)
249
 
{
250
 
   EGLuint pos;
251
 
   assert(table);
252
 
   _eglLockMutex(table->Mutex);
253
 
   for (pos = 0; pos < TABLE_SIZE; pos++) {
254
 
      if (table->Table[pos]) {
255
 
         _eglUnlockMutex(table->Mutex);
256
 
         return table->Table[pos]->Key;
257
 
      }
258
 
   }
259
 
   _eglUnlockMutex(table->Mutex);
260
 
   return 0;
261
 
}
262
 
 
263
 
 
264
 
/**
265
 
 * Given a hash table key, return the next key.  This is used to walk
266
 
 * over all entries in the table.  Note that the keys returned during
267
 
 * walking won't be in any particular order.
268
 
 * \return next hash key or 0 if end of table.
269
 
 */
270
 
EGLuint
271
 
_eglHashNextEntry(const _EGLHashtable *table, EGLuint key)
272
 
{
273
 
   const _EGLHashentry *entry;
274
 
   EGLuint pos;
275
 
 
276
 
   assert(table);
277
 
   assert(key);
278
 
 
279
 
   /* Find the entry with given key */
280
 
   pos = HASH_FUNC(key);
281
 
   entry = table->Table[pos];
282
 
   while (entry) {
283
 
      if (entry->Key == key) {
284
 
         break;
285
 
      }
286
 
      entry = entry->Next;
287
 
   }
288
 
 
289
 
   if (!entry) {
290
 
      /* the key was not found, we can't find next entry */
291
 
      return 0;
292
 
   }
293
 
 
294
 
   if (entry->Next) {
295
 
      /* return next in linked list */
296
 
      return entry->Next->Key;
297
 
   }
298
 
   else {
299
 
      /* look for next non-empty table slot */
300
 
      pos++;
301
 
      while (pos < TABLE_SIZE) {
302
 
         if (table->Table[pos]) {
303
 
            return table->Table[pos]->Key;
304
 
         }
305
 
         pos++;
306
 
      }
307
 
      return 0;
308
 
   }
309
 
}
310
 
 
311
 
 
312
 
/**
313
 
 * Dump contents of hash table for debugging.
314
 
 * 
315
 
 * \param table the hash table.
316
 
 */
317
 
void
318
 
_eglHashPrint(const _EGLHashtable *table)
319
 
{
320
 
   EGLuint i;
321
 
   assert(table);
322
 
   for (i = 0; i < TABLE_SIZE; i++) {
323
 
      const _EGLHashentry *entry = table->Table[i];
324
 
      while (entry) {
325
 
         printf("%u %p\n", entry->Key, entry->Data);
326
 
         entry = entry->Next;
327
 
      }
328
 
   }
329
 
}
330
 
 
331
 
 
332
 
 
333
 
/**
334
 
 * Return a new, unused hash key.
335
 
 */
336
 
EGLuint
337
 
_eglHashGenKey(_EGLHashtable *table)
338
 
{
339
 
   EGLuint k;
340
 
 
341
 
   _eglLockMutex(table->Mutex);
342
 
   k = table->MaxKey;
343
 
   table->MaxKey++;
344
 
   _eglUnlockMutex(table->Mutex);
345
 
   return k;
346
 
}
347