Skip to content

Commit

Permalink
Introduced a safe iterator interface that can be used to iterate whil…
Browse files Browse the repository at this point in the history
…e accessing the dictionary at the same time. Now the default interface is consireded unsafe and should be used only with dictNext()
  • Loading branch information
antirez committed May 10, 2011
1 parent f13cb0d commit 4b53e73
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
20 changes: 15 additions & 5 deletions src/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}

Expand Down
8 changes: 6 additions & 2 deletions src/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 4b53e73

Please sign in to comment.