uintmap.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "config.h"
  2. #include "uintmap.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "almalloc.h"
  6. extern inline void LockUIntMapRead(UIntMap *map);
  7. extern inline void UnlockUIntMapRead(UIntMap *map);
  8. extern inline void LockUIntMapWrite(UIntMap *map);
  9. extern inline void UnlockUIntMapWrite(UIntMap *map);
  10. void InitUIntMap(UIntMap *map, ALsizei limit)
  11. {
  12. map->keys = NULL;
  13. map->values = NULL;
  14. map->size = 0;
  15. map->capacity = 0;
  16. map->limit = limit;
  17. RWLockInit(&map->lock);
  18. }
  19. void ResetUIntMap(UIntMap *map)
  20. {
  21. WriteLock(&map->lock);
  22. al_free(map->keys);
  23. map->keys = NULL;
  24. map->values = NULL;
  25. map->size = 0;
  26. map->capacity = 0;
  27. WriteUnlock(&map->lock);
  28. }
  29. ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
  30. {
  31. ALsizei pos = 0;
  32. WriteLock(&map->lock);
  33. if(map->size > 0)
  34. {
  35. ALsizei low = 0;
  36. ALsizei high = map->size - 1;
  37. while(low < high)
  38. {
  39. ALsizei mid = low + (high-low)/2;
  40. if(map->keys[mid] < key)
  41. low = mid + 1;
  42. else
  43. high = mid;
  44. }
  45. if(map->keys[low] < key)
  46. low++;
  47. pos = low;
  48. }
  49. if(pos == map->size || map->keys[pos] != key)
  50. {
  51. if(map->size == map->limit)
  52. {
  53. WriteUnlock(&map->lock);
  54. return AL_OUT_OF_MEMORY;
  55. }
  56. if(map->size == map->capacity)
  57. {
  58. ALuint *keys = NULL;
  59. ALvoid **values;
  60. ALsizei newcap, keylen;
  61. newcap = (map->capacity ? (map->capacity<<1) : 4);
  62. if(map->limit > 0 && newcap > map->limit)
  63. newcap = map->limit;
  64. if(newcap > map->capacity)
  65. {
  66. /* Round the memory size for keys up to a multiple of the
  67. * pointer size.
  68. */
  69. keylen = newcap * sizeof(map->keys[0]);
  70. keylen += sizeof(map->values[0]) - 1;
  71. keylen -= keylen%sizeof(map->values[0]);
  72. keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
  73. }
  74. if(!keys)
  75. {
  76. WriteUnlock(&map->lock);
  77. return AL_OUT_OF_MEMORY;
  78. }
  79. values = (ALvoid**)((ALbyte*)keys + keylen);
  80. if(map->keys)
  81. {
  82. memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
  83. memcpy(values, map->values, map->size*sizeof(map->values[0]));
  84. }
  85. al_free(map->keys);
  86. map->keys = keys;
  87. map->values = values;
  88. map->capacity = newcap;
  89. }
  90. if(pos < map->size)
  91. {
  92. memmove(&map->keys[pos+1], &map->keys[pos],
  93. (map->size-pos)*sizeof(map->keys[0]));
  94. memmove(&map->values[pos+1], &map->values[pos],
  95. (map->size-pos)*sizeof(map->values[0]));
  96. }
  97. map->size++;
  98. }
  99. map->keys[pos] = key;
  100. map->values[pos] = value;
  101. WriteUnlock(&map->lock);
  102. return AL_NO_ERROR;
  103. }
  104. ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
  105. {
  106. ALvoid *ptr = NULL;
  107. WriteLock(&map->lock);
  108. if(map->size > 0)
  109. {
  110. ALsizei low = 0;
  111. ALsizei high = map->size - 1;
  112. while(low < high)
  113. {
  114. ALsizei mid = low + (high-low)/2;
  115. if(map->keys[mid] < key)
  116. low = mid + 1;
  117. else
  118. high = mid;
  119. }
  120. if(map->keys[low] == key)
  121. {
  122. ptr = map->values[low];
  123. if(low < map->size-1)
  124. {
  125. memmove(&map->keys[low], &map->keys[low+1],
  126. (map->size-1-low)*sizeof(map->keys[0]));
  127. memmove(&map->values[low], &map->values[low+1],
  128. (map->size-1-low)*sizeof(map->values[0]));
  129. }
  130. map->size--;
  131. }
  132. }
  133. WriteUnlock(&map->lock);
  134. return ptr;
  135. }
  136. ALvoid *RemoveUIntMapKeyNoLock(UIntMap *map, ALuint key)
  137. {
  138. if(map->size > 0)
  139. {
  140. ALsizei low = 0;
  141. ALsizei high = map->size - 1;
  142. while(low < high)
  143. {
  144. ALsizei mid = low + (high-low)/2;
  145. if(map->keys[mid] < key)
  146. low = mid + 1;
  147. else
  148. high = mid;
  149. }
  150. if(map->keys[low] == key)
  151. {
  152. ALvoid *ptr = map->values[low];
  153. if(low < map->size-1)
  154. {
  155. memmove(&map->keys[low], &map->keys[low+1],
  156. (map->size-1-low)*sizeof(map->keys[0]));
  157. memmove(&map->values[low], &map->values[low+1],
  158. (map->size-1-low)*sizeof(map->values[0]));
  159. }
  160. map->size--;
  161. return ptr;
  162. }
  163. }
  164. return NULL;
  165. }
  166. ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
  167. {
  168. ALvoid *ptr = NULL;
  169. ReadLock(&map->lock);
  170. if(map->size > 0)
  171. {
  172. ALsizei low = 0;
  173. ALsizei high = map->size - 1;
  174. while(low < high)
  175. {
  176. ALsizei mid = low + (high-low)/2;
  177. if(map->keys[mid] < key)
  178. low = mid + 1;
  179. else
  180. high = mid;
  181. }
  182. if(map->keys[low] == key)
  183. ptr = map->values[low];
  184. }
  185. ReadUnlock(&map->lock);
  186. return ptr;
  187. }
  188. ALvoid *LookupUIntMapKeyNoLock(UIntMap *map, ALuint key)
  189. {
  190. if(map->size > 0)
  191. {
  192. ALsizei low = 0;
  193. ALsizei high = map->size - 1;
  194. while(low < high)
  195. {
  196. ALsizei mid = low + (high-low)/2;
  197. if(map->keys[mid] < key)
  198. low = mid + 1;
  199. else
  200. high = mid;
  201. }
  202. if(map->keys[low] == key)
  203. return map->values[low];
  204. }
  205. return NULL;
  206. }