forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathidset.c
118 lines (107 loc) · 3.9 KB
/
idset.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// This file is a part of Julia. License is MIT: https://julialang.org/license
static uint_t idset_hash(size_t idx, jl_value_t *data)
{
jl_value_t *x = jl_genericmemory_ptr_ref(data, idx);
// x should not be NULL, unless there was concurrent corruption
return x == NULL ? 0 : jl_object_id(x);
}
static int idset_eq(size_t idx, const void *y, jl_value_t *data, uint_t hv)
{
jl_value_t *x = jl_genericmemory_ptr_ref(data, idx);
// x should not be NULL, unless there was concurrent corruption
return x == NULL ? 0 : jl_egal(x, (jl_value_t*)y);
}
jl_genericmemory_t *jl_idset_rehash(jl_genericmemory_t *keys, jl_genericmemory_t *idxs, size_t newsz)
{
if (newsz == 0)
return idxs;
newsz = next_power_of_two(newsz);
//if (idxs->length == newsz)
// jl_idset_put_idx(keys, idxs, -newsz+1);
//else
return smallintset_rehash(idxs, idset_hash, (jl_value_t*)keys, newsz, 0);
}
// Return idx if key is in hash, otherwise -1
// Note: lookup in the IdSet is permitted concurrently, if you avoid deletions,
// and assuming you do use an external lock around all insertions
ssize_t jl_idset_peek_bp(jl_genericmemory_t *keys, jl_genericmemory_t *idxs, jl_value_t *key) JL_NOTSAFEPOINT
{
uintptr_t hv = jl_object_id(key);
return jl_smallintset_lookup(idxs, idset_eq, key, (jl_value_t*)keys, hv, 0);
}
jl_value_t *jl_idset_get(jl_genericmemory_t *keys, jl_genericmemory_t *idxs, jl_value_t *key) JL_NOTSAFEPOINT
{
ssize_t idx = jl_idset_peek_bp(keys, idxs, key);
if (idx == -1)
return NULL;
return jl_genericmemory_ptr_ref(keys, idx);
}
static ssize_t idset_compact(jl_genericmemory_t *keys)
{
// compact keys before rehashing idxs
ssize_t i, j;
ssize_t rehash = 0;
for (i = j = 0; i < keys->length; i++) {
jl_value_t *k = jl_genericmemory_ptr_ref(keys, i);
if (k != NULL) {
if (i != j) {
rehash = 1;
jl_genericmemory_ptr_set(keys, j, k);
jl_genericmemory_ptr_set(keys, i, NULL);
}
j++;
}
}
return rehash ? -j : j;
}
jl_genericmemory_t *jl_idset_put_key(jl_genericmemory_t *keys, jl_value_t *key, ssize_t *newidx)
{
ssize_t l = keys->length;
ssize_t i = l;
while (i > 0 && jl_genericmemory_ptr_ref(keys, i - 1) == NULL)
i--;
// i points to the place to insert
*newidx = i;
if (i == l) {
i = idset_compact(keys);
if (i < 0) {
*newidx = i - 1;
i = -i;
}
if (i >= l / 3 * 2) {
size_t nl = l < 4 ? 4 : (l * 3) >> 1; // grow space by 50% if less than 33% free after compacting
jl_genericmemory_t *nk = jl_alloc_genericmemory(jl_memory_any_type, nl);
if (i > 0)
memcpy(nk->ptr, keys->ptr, sizeof(void*) * i);
keys = nk;
}
}
assert(jl_genericmemory_ptr_ref(keys, i) == NULL);
jl_genericmemory_ptr_set(keys, i, key);
return keys;
}
jl_genericmemory_t *jl_idset_put_idx(jl_genericmemory_t *keys, jl_genericmemory_t *idxs, ssize_t idx)
{
_Atomic(jl_genericmemory_t*) newidxs = idxs;
JL_GC_PUSH1(&newidxs);
if (idx < 0) { // full rehash
smallintset_empty(idxs);
for (ssize_t i = 0; i < -idx; i++)
if (jl_genericmemory_ptr_ref(keys, i) != NULL)
jl_smallintset_insert(&newidxs, NULL, idset_hash, i, (jl_value_t*)keys);
}
else {
jl_smallintset_insert(&newidxs, NULL, idset_hash, idx, (jl_value_t*)keys);
}
JL_GC_POP();
return jl_atomic_load_relaxed(&newidxs);
}
/* returns idx if key is in hash, otherwise -1 */
ssize_t jl_idset_pop(jl_genericmemory_t *keys, jl_genericmemory_t *idxs, jl_value_t *key) JL_NOTSAFEPOINT
{
uintptr_t hv = jl_object_id(key);
ssize_t idx = jl_smallintset_lookup(idxs, idset_eq, key, (jl_value_t*)keys, hv, 1);
if (idx != -1)
jl_genericmemory_ptr_set(keys, idx, NULL);
return idx;
}