PengZheng commented on code in PR #470:
URL: https://github.com/apache/celix/pull/470#discussion_r1383248138


##########
libs/utils/src/celix_hash_map.c:
##########
@@ -237,11 +235,12 @@ static void celix_hashMap_addEntry(celix_hash_map_t* map, 
unsigned int hash, con
     newEntry->next = entry;
     map->buckets[bucketIndex] = newEntry;
     if (map->size++ >= celix_hashMap_threshold(map)) {
-        celix_hashMap_resize(map, 2 * map->bucketsSize);
+        return celix_hashMap_resize(map, 2 * map->bucketsSize);

Review Comment:
   if `newEntry` is added but `celix_hashMap_resize` failed, should it return 
SUCCESS or error code? 



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -599,33 +675,49 @@ bool celix_longHashMapIterator_isEnd(const 
celix_long_hash_map_iterator_t* iter)
 void celix_stringHashMapIterator_next(celix_string_hash_map_iterator_t* iter) {
     const celix_hash_map_t* map = iter->_internal[0];
     celix_hash_map_entry_t *entry = iter->_internal[1];
+    iter->index += 1;
     entry = celix_hashMap_nextEntry(map, entry);
-    if (entry != NULL) {
+    if (entry) {
         iter->_internal[1] = entry;
-        iter->index += 1;
         iter->key = entry->key.strKey;
         iter->value = entry->value;
     } else {
-        memset(iter, 0, sizeof(*iter));
-        iter->_internal[0] = (void*)map;
+        iter->_internal[1] = NULL;
+        iter->key = NULL;

Review Comment:
   In `celix_stringHashMap_end`, `key` is set to "".



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -339,21 +327,27 @@ static bool celix_hashMap_remove(celix_hash_map_t* map, 
const char* strKey, long
         visit = visit->next;
     }
     if (removedEntry != NULL) {
+        char* removedKey = NULL;
+        if (map->keyType == CELIX_HASH_MAP_STRING_KEY) {
+            removedKey = (char*)removedEntry->key.strKey;
+        }
         celix_hashMap_destroyRemovedEntry(map, removedEntry);
+        if (removedKey) {
+            celix_hashMap_destroyRemovedKey(map, removedKey);
+        }
         return true;
     }
     return false;
 }
 
-static void celix_hashMap_init(
+celix_status_t celix_hashMap_init(
         celix_hash_map_t* map,
         celix_hash_map_key_type_e keyType,
         unsigned int initialCapacity,
         double loadFactor,
         unsigned int (*hashKeyFn)(const celix_hash_map_key_t*),
         bool (*equalsKeyFn)(const celix_hash_map_key_t*, const 
celix_hash_map_key_t*)) {
     map->loadFactor = loadFactor;

Review Comment:
   `loadFactor`, which is always less than 1,  does not apply to separate 
chaining hash table.  It does apply to linear probing and double hashing 
implementation, both of which have nothing to do with our implementation.
   
   For separate chaining implementation, it is normal for a list to contain 
about 5 or 10 keys.  Our resize implementation will lead to too many 
unnecessary resize.
   
   For reference, I quote an exercise in Robert Sedgewick's Algorithms in C++:
   
   >  14.45 Implement a version of Program 14.7 for separate chaining that 
increases the table size by a factor of 10 each time the average list length is 
equal to 10.
   
   



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -237,11 +235,12 @@ static void celix_hashMap_addEntry(celix_hash_map_t* map, 
unsigned int hash, con
     newEntry->next = entry;
     map->buckets[bucketIndex] = newEntry;
     if (map->size++ >= celix_hashMap_threshold(map)) {
-        celix_hashMap_resize(map, 2 * map->bucketsSize);
+        return celix_hashMap_resize(map, 2 * map->bucketsSize);

Review Comment:
   For weakly stored key, it will make huge difference.



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -599,33 +675,49 @@ bool celix_longHashMapIterator_isEnd(const 
celix_long_hash_map_iterator_t* iter)
 void celix_stringHashMapIterator_next(celix_string_hash_map_iterator_t* iter) {
     const celix_hash_map_t* map = iter->_internal[0];
     celix_hash_map_entry_t *entry = iter->_internal[1];
+    iter->index += 1;

Review Comment:
   `iter.index` will be larger than  `map->genericMap.size` even if it has 
reached the end. Does this break some invariant?



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -562,6 +591,33 @@ void celix_longHashMap_clear(celix_long_hash_map_t* map) {
     celix_hashMap_clear(&map->genericMap);
 }
 
+static bool celix_hashMap_equals(const celix_hash_map_t* map1, const 
celix_hash_map_t* map2) {
+    if (map1 == NULL && map2 == NULL) {
+        return true;
+    }
+    if (map1 == NULL || map2 == NULL) {
+            return false;
+    }
+    if (map1->size != map2->size) {
+        return false;
+    }
+    for (celix_hash_map_entry_t* entry = celix_hashMap_firstEntry(map1); entry 
!= NULL; entry = celix_hashMap_nextEntry(map1, entry)) {
+        void* value = celix_hashMap_get(map2, entry->key.strKey, 
entry->key.longKey);
+        if (value == NULL || memcmp(&entry->value, value, 
sizeof(entry->value)) != 0) {

Review Comment:
   This assumes `sizeof(void*) >= sizeof(double)`, which is not true on ARM32. 
`celix_hashMap_get` should return `celix_hash_map_entry_t` instead.



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -256,57 +255,46 @@ static bool celix_hashMap_putValue(celix_hash_map_t* map, 
const char* strKey, lo
             if (replacedValueOut != NULL) {
                 *replacedValueOut = entry->value;
             }
+            celix_hashMap_callRemovedCallback(map, entry);
             memcpy(&entry->value, value, sizeof(*value));
-            return true;
+            return CELIX_SUCCESS;
         }
     }
-    celix_hashMap_addEntry(map, hash, &key, value, index);
-    if (replacedValueOut != NULL) {
+    celix_status_t status = celix_hashMap_addEntry(map, hash, &key, value, 
index);
+    if (status == CELIX_SUCCESS && replacedValueOut != NULL) {
         memset(replacedValueOut, 0, sizeof(*replacedValueOut));
     }
-    return false;
+    return status;
 }
 
-static void* celix_hashMap_put(celix_hash_map_t* map, const char* strKey, long 
longKey, void* v) {
+static celix_status_t celix_hashMap_put(celix_hash_map_t* map, const char* 
strKey, long longKey, void* v, void** previousValueOut) {

Review Comment:
   `previousValueOut` is unused. Shall we remove it?



##########
libs/utils/src/celix_hash_map.c:
##########
@@ -94,11 +83,11 @@ static unsigned int celix_longHashMap_hash(const 
celix_hash_map_key_t* key) {
     return key->longKey ^ (key->longKey >> (sizeof(key->longKey)*8/2));

Review Comment:
   Suppose that `sizeof(long)==8`, when the table size is very small (like 16), 
only 8 bits of `longKey` (the lower 4 bits of the upper and lower 32bit) will 
affect the resulting hash value. This is a bad hash functino.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@celix.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to