00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "pointer-set.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 struct pointer_set_t
00034 {
00035 size_t log_slots;
00036 size_t n_slots;
00037 size_t n_elements;
00038
00039 void **slots;
00040 };
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 static inline size_t
00057 hash1 (const void *p, unsigned long max, unsigned long logmax)
00058 {
00059 #if HOST_BITS_PER_LONG == 32
00060 const unsigned long A = 0x9e3779b9u;
00061 #elif HOST_BITS_PER_LONG == 64
00062 const unsigned long A = 0x9e3779b97f4a7c16ul;
00063 #else
00064 const unsigned long A
00065 = (ULONG_MAX + 1.0L) * 0.6180339887498948482045868343656381177203L;
00066 #endif
00067 const unsigned long shift = HOST_BITS_PER_LONG - logmax;
00068
00069 return ((A * (unsigned long) p) >> shift) & (max - 1);
00070 }
00071
00072
00073 struct pointer_set_t *
00074 pointer_set_create (void)
00075 {
00076 struct pointer_set_t *result = XNEW (struct pointer_set_t);
00077
00078 result->n_elements = 0;
00079 result->log_slots = 8;
00080 result->n_slots = (size_t) 1 << result->log_slots;
00081
00082 result->slots = XCNEWVEC (void *, result->n_slots);
00083 return result;
00084 }
00085
00086
00087 void pointer_set_destroy (struct pointer_set_t *pset)
00088 {
00089 XDELETEVEC (pset->slots);
00090 XDELETE (pset);
00091 }
00092
00093
00094
00095
00096 int
00097 pointer_set_contains (struct pointer_set_t *pset, void *p)
00098 {
00099 size_t n = hash1 (p, pset->n_slots, pset->log_slots);
00100
00101 while (true)
00102 {
00103 if (pset->slots[n] == p)
00104 return 1;
00105 else if (pset->slots[n] == 0)
00106 return 0;
00107 else
00108 {
00109 ++n;
00110 if (n == pset->n_slots)
00111 n = 0;
00112 }
00113 }
00114 }
00115
00116
00117
00118
00119 static int
00120 insert_aux (void *p, void **slots, size_t n_slots, size_t log_slots)
00121 {
00122 size_t n = hash1 (p, n_slots, log_slots);
00123 while (true)
00124 {
00125 if (slots[n] == p)
00126 return 1;
00127 else if (slots[n] == 0)
00128 {
00129 slots[n] = p;
00130 return 0;
00131 }
00132 else
00133 {
00134 ++n;
00135 if (n == n_slots)
00136 n = 0;
00137 }
00138 }
00139 }
00140
00141
00142
00143 int
00144 pointer_set_insert (struct pointer_set_t *pset, void *p)
00145 {
00146 if (insert_aux (p, pset->slots, pset->n_slots, pset->log_slots))
00147 return 1;
00148
00149
00150
00151 ++pset->n_elements;
00152 if (pset->n_elements > pset->n_slots / 4)
00153 {
00154 size_t new_log_slots = pset->log_slots + 1;
00155 size_t new_n_slots = pset->n_slots * 2;
00156 void **new_slots = XCNEWVEC (void *, new_n_slots);
00157 size_t i;
00158
00159 for (i = 0; i < pset->n_slots; ++i)
00160 {
00161 if (pset->slots[i])
00162 insert_aux (pset->slots[i], new_slots, new_n_slots, new_log_slots);
00163 }
00164
00165 XDELETEVEC (pset->slots);
00166 pset->n_slots = new_n_slots;
00167 pset->log_slots = new_log_slots;
00168 pset->slots = new_slots;
00169 }
00170
00171 return 0;
00172 }