Commit 4b53e736 authored by antirez's avatar antirez
Browse files

Introduced a safe iterator interface that can be used to iterate while...

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()
parent f13cb0d9
...@@ -245,9 +245,9 @@ int dictRehashMilliseconds(dict *d, int ms) { ...@@ -245,9 +245,9 @@ int dictRehashMilliseconds(dict *d, int ms) {
} }
/* This function performs just a step of rehashing, and only if there are /* 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 * no safe iterators bound to our hash table. When we have iterators in the
* of a rehashing we can't mess with the two hash tables otherwise some element * middle of a rehashing we can't mess with the two hash tables otherwise
* can be missed or duplicated. * some element can be missed or duplicated.
* *
* This function is called by common lookup or update operations in the * This function is called by common lookup or update operations in the
* dictionary so that the hash table automatically migrates from H1 to H2 * dictionary so that the hash table automatically migrates from H1 to H2
...@@ -424,17 +424,26 @@ dictIterator *dictGetIterator(dict *d) ...@@ -424,17 +424,26 @@ dictIterator *dictGetIterator(dict *d)
iter->d = d; iter->d = d;
iter->table = 0; iter->table = 0;
iter->index = -1; iter->index = -1;
iter->safe = 0;
iter->entry = NULL; iter->entry = NULL;
iter->nextEntry = NULL; iter->nextEntry = NULL;
return iter; return iter;
} }
dictIterator *dictGetSafeIterator(dict *d) {
dictIterator *i = dictGetIterator(d);
i->safe = 1;
return i;
}
dictEntry *dictNext(dictIterator *iter) dictEntry *dictNext(dictIterator *iter)
{ {
while (1) { while (1) {
if (iter->entry == NULL) { if (iter->entry == NULL) {
dictht *ht = &iter->d->ht[iter->table]; 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++; iter->index++;
if (iter->index >= (signed) ht->size) { if (iter->index >= (signed) ht->size) {
if (dictIsRehashing(iter->d) && iter->table == 0) { if (dictIsRehashing(iter->d) && iter->table == 0) {
...@@ -461,7 +470,8 @@ dictEntry *dictNext(dictIterator *iter) ...@@ -461,7 +470,8 @@ dictEntry *dictNext(dictIterator *iter)
void dictReleaseIterator(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); zfree(iter);
} }
......
...@@ -74,10 +74,13 @@ typedef struct dict { ...@@ -74,10 +74,13 @@ typedef struct dict {
int iterators; /* number of iterators currently running */ int iterators; /* number of iterators currently running */
} dict; } 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 { typedef struct dictIterator {
dict *d; dict *d;
int table; int table, index, safe;
int index;
dictEntry *entry, *nextEntry; dictEntry *entry, *nextEntry;
} dictIterator; } dictIterator;
...@@ -132,6 +135,7 @@ dictEntry * dictFind(dict *d, const void *key); ...@@ -132,6 +135,7 @@ dictEntry * dictFind(dict *d, const void *key);
void *dictFetchValue(dict *d, const void *key); void *dictFetchValue(dict *d, const void *key);
int dictResize(dict *d); int dictResize(dict *d);
dictIterator *dictGetIterator(dict *d); dictIterator *dictGetIterator(dict *d);
dictIterator *dictGetSafeIterator(dict *d);
dictEntry *dictNext(dictIterator *iter); dictEntry *dictNext(dictIterator *iter);
void dictReleaseIterator(dictIterator *iter); void dictReleaseIterator(dictIterator *iter);
dictEntry *dictGetRandomKey(dict *d); dictEntry *dictGetRandomKey(dict *d);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment