Skip to content

Commit a3b6bbf

Browse files
committed
Hash map fin.
1 parent 40261a6 commit a3b6bbf

3 files changed

Lines changed: 36 additions & 5 deletions

File tree

backend-v2/runtime/ConcurrentHashMap.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ ConcurrentHashMap *ConcurrentHashMap_create(unsigned char initialSizeExponent) {
5050
}
5151
atomic_store(&(self->root), node);
5252
Object_create(&(self->super), concurrentHashMapType);
53+
// Concurrent collections are shared by definition
54+
atomic_store_explicit(&self->super.atomicRefCount, COUNT_INC | SHARED_BIT, memory_order_release);
5355
return self;
5456
}
5557

@@ -96,6 +98,9 @@ inline bool tryReplacingEntry(ConcurrentHashMapEntry *entry, RTValue key, RTValu
9698

9799
/* MUTABLE: self is not conusmed. mem done */
98100
void ConcurrentHashMap_assoc(ConcurrentHashMap *self, RTValue key, RTValue value) {
101+
promoteToShared(key);
102+
promoteToShared(value);
103+
99104
ConcurrentHashMapNode *root = atomic_load_explicit(&(self->root), memory_order_relaxed);
100105

101106
uword_t keyHash = avalanche(hash(key));

backend-v2/runtime/PersistentList.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ uint64_t PersistentList_hash(PersistentList *self) {
101101
PersistentList *current = self->rest;
102102
while (current) {
103103
h = combineHash(h, PersistentList_hash(current));
104-
current = self->rest;
104+
current = current->rest;
105105
}
106106
return h;
107107
}

backend-v2/runtime/tests/ConcurrentHashMap_test.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
#include "../ConcurrentHashMap.h"
2+
#include "../PersistentList.h"
3+
#include "../Hash.h"
14
#include "TestTools.h"
25
#include <math.h>
36

47
#define THREAD_COUNT 10
58

9+
static bool Ptr_isShared(void *p) {
10+
return (Object_getRawRefCount((Object *)p) & SHARED_BIT) != 0;
11+
}
12+
613
typedef struct HashThreadParams {
714
int start;
815
int stop;
@@ -115,12 +122,31 @@ static void test_concurrent_hash_map_overcrowded(void **state) {
115122
});
116123
}
117124

125+
static void test_chm_promotion_on_assoc(void **state) {
126+
(void)state;
127+
// Initialize PersistentList_empty() singleton before the block
128+
// because otherwise it will be recorded as a "leak" (type 8)
129+
PersistentList_empty();
130+
ASSERT_MEMORY_ALL_BALANCED({
131+
// 1. Test shared-at-birth
132+
ConcurrentHashMap *m = ConcurrentHashMap_create(3);
133+
assert_true(Ptr_isShared(m));
134+
135+
// 2. Test promotion on assoc
136+
PersistentList *l = PersistentList_create(RT_boxInt32(1), PersistentList_empty());
137+
assert_false(Ptr_isShared(l));
138+
139+
ConcurrentHashMap_assoc(m, RT_boxPtr(l), RT_boxInt32(100));
140+
// The list should have been promoted because it was inserted into CHM
141+
assert_true(Ptr_isShared(l));
142+
143+
Ptr_release(m);
144+
});
145+
}
146+
118147
int main(void) {
119148
const struct CMUnitTest tests[] = {
120-
// There are problems with the map - bad performance all around and
121-
// possible
122-
// race conditions.
123-
// Needs to be re-implemented? or at least checked with emini
149+
cmocka_unit_test(test_chm_promotion_on_assoc),
124150
cmocka_unit_test_prestate(testScalingBehavior,
125151
concurrentMapThreadingAndPerformance),
126152
cmocka_unit_test(test_concurrent_hash_map_overcrowded),

0 commit comments

Comments
 (0)