]> git.saurik.com Git - redis.git/commitdiff
Introduced a safe iterator interface that can be used to iterate while accessing...
authorantirez <antirez@gmail.com>
Tue, 10 May 2011 08:15:50 +0000 (10:15 +0200)
committerantirez <antirez@gmail.com>
Tue, 10 May 2011 08:15:50 +0000 (10:15 +0200)
src/dict.c
src/dict.h

index 6b7010ba2efba11231be224f5fe0479d8ccb605f..24001fdd0a520098eaecdc00bc893d2761968a40 100644 (file)
@@ -245,9 +245,9 @@ int dictRehashMilliseconds(dict *d, int ms) {
 }
 
 /* This function performs just a step of rehashing, and only if there are
- * not iterators bound to our hash table. When we have iterators in the middle
- * of a rehashing we can't mess with the two hash tables otherwise some element
- * can be missed or duplicated.
+ * no safe iterators bound to our hash table. When we have iterators in the
+ * middle of a rehashing we can't mess with the two hash tables otherwise
+ * some element can be missed or duplicated.
  *
  * This function is called by common lookup or update operations in the
  * dictionary so that the hash table automatically migrates from H1 to H2
@@ -424,17 +424,26 @@ dictIterator *dictGetIterator(dict *d)
     iter->d = d;
     iter->table = 0;
     iter->index = -1;
+    iter->safe = 0;
     iter->entry = NULL;
     iter->nextEntry = NULL;
     return iter;
 }
 
+dictIterator *dictGetSafeIterator(dict *d) {
+    dictIterator *i = dictGetIterator(d);
+
+    i->safe = 1;
+    return i;
+}
+
 dictEntry *dictNext(dictIterator *iter)
 {
     while (1) {
         if (iter->entry == NULL) {
             dictht *ht = &iter->d->ht[iter->table];
-            if (iter->index == -1 && iter->table == 0) iter->d->iterators++;
+            if (iter->safe && iter->index == -1 && iter->table == 0)
+                iter->d->iterators++;
             iter->index++;
             if (iter->index >= (signed) ht->size) {
                 if (dictIsRehashing(iter->d) && iter->table == 0) {
@@ -461,7 +470,8 @@ dictEntry *dictNext(dictIterator *iter)
 
 void dictReleaseIterator(dictIterator *iter)
 {
-    if (!(iter->index == -1 && iter->table == 0)) iter->d->iterators--;
+    if (iter->safe && !(iter->index == -1 && iter->table == 0))
+        iter->d->iterators--;
     zfree(iter);
 }
 
index 25cce4e50ef7f13a756251a6d91b405786e8ac33..74bcd2aad67531c9c08a1360736a98c740a8e284 100644 (file)
@@ -74,10 +74,13 @@ typedef struct dict {
     int iterators; /* number of iterators currently running */
 } dict;
 
+/* If safe is set to 1 this is a safe iteartor, that means, you can call
+ * dictAdd, dictFind, and other functions against the dictionary even while
+ * iterating. Otherwise it is a non safe iterator, and only dictNext()
+ * should be called while iterating. */
 typedef struct dictIterator {
     dict *d;
-    int table;
-    int index;
+    int table, index, safe;
     dictEntry *entry, *nextEntry;
 } dictIterator;
 
@@ -132,6 +135,7 @@ dictEntry * dictFind(dict *d, const void *key);
 void *dictFetchValue(dict *d, const void *key);
 int dictResize(dict *d);
 dictIterator *dictGetIterator(dict *d);
+dictIterator *dictGetSafeIterator(dict *d);
 dictEntry *dictNext(dictIterator *iter);
 void dictReleaseIterator(dictIterator *iter);
 dictEntry *dictGetRandomKey(dict *d);