- return NULL;
- }
-
- Value* remove(Key *key, Value *value) {
- MODEL_ASSERT (key);
- int hash = hashKey(key);
- Segment *seg = segments[hash & SEGMENT_MASK];
- atomic<Entry*> *tab;
-
- seg->lock(); // Critical region begins
- tab = table;
- int index = hash & (capacity - 1);
-
- atomic<Entry*> *first = &tab[index];
- Entry *e;
- Value *oldValue = NULL;
-
- // The written of the entry is synchronized by locking
- Entry *firstPtr = first->load(relaxed);
- e = firstPtr;
-
- while (true) {
- if (e != NULL) {
- seg->unlock(); // Don't forget to unlock
- return NULL;
- }
- if (e->hash == hash && eq(key, e->key))
- break;
- // Synchronized by locking
- e = e->next.load(relaxed);
- }
-
- // FIXME: This could be a relaxed (because locking synchronize
- // with the previous put())?? No need to be acquire
- oldValue = e->value.load(relaxed);
- // If the value parameter is NULL, we will remove the entry anyway
- if (value != NULL && value->equals(oldValue)) {
- seg->unlock();
- return NULL;
- }
-
- // Force the get() to grab the lock and retry
- e->value.store(NULL, relaxed);
-
- // The strategy to remove the entry is to keep the entries after the
- // removed one and copy the ones before it
- Entry *head = e->next.load(relaxed);
- Entry *p;
- p = first->load(relaxed);
- while (p != e) {
- head = new Entry(p->hash, p->key, p->value.load(relaxed), head);
- p = p->next.load(relaxed);
- }
-
- // Publish the new head to readers
- first->store(head, release);
- seg->unlock(); // Critical region ends
- return oldValue;