summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2011-05-10 10:15:50 +0200
committerantirez <antirez@gmail.com>2011-05-10 11:04:03 +0200
commit2e638590ad13f9c6256d47237ae2f1166532c8a5 (patch)
treec6c210cb14c87f216a0426527256b8999e6bf47f
parent3554f09ddc44d1722c2f3687f006c0e3ff8d5f2c (diff)
downloadredis-2e638590ad13f9c6256d47237ae2f1166532c8a5.tar.gz
Introduced a safe iterator interface that can be used to iterate while accessing the dictionary at the same time. Now the default interface is consireded unsafe and should be used only with dictNext()
-rw-r--r--src/dict.c20
-rw-r--r--src/dict.h8
2 files changed, 21 insertions, 7 deletions
diff --git a/src/dict.c b/src/dict.c
index 9be7fb168..34f021bf5 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -244,9 +244,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
@@ -423,17 +423,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) {
@@ -460,7 +469,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);
}
diff --git a/src/dict.h b/src/dict.h
index 25cce4e50..74bcd2aad 100644
--- a/src/dict.h
+++ b/src/dict.h
@@ -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);