Skip to content

Commit

Permalink
small fixes and prepare for AtomicDict.__delitem__ refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
dpdani committed Aug 1, 2024
1 parent 8eca42f commit 2e6857a
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 194 deletions.
49 changes: 28 additions & 21 deletions src/cereggii/atomic_dict/atomic_dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,27 +546,34 @@ PyObject *
AtomicDict_Debug(AtomicDict *self)
{
AtomicDict_Meta *meta = NULL;
PyObject *metadata = NULL;
PyObject *index_nodes = NULL;
PyObject *blocks = NULL;
PyObject *entries = NULL;
PyObject *entry_tuple = NULL;
PyObject *block_info = NULL;

meta = (AtomicDict_Meta *) AtomicRef_Get(self->metadata);
PyObject *metadata = Py_BuildValue("{sOsOsOsOsOsOsOsOsOsOsOsOsO}",
"log_size\0", Py_BuildValue("B", meta->log_size),
"generation\0", Py_BuildValue("O", meta->generation),
"node_size\0", Py_BuildValue("B", meta->node_size),
"distance_size\0", Py_BuildValue("B", meta->distance_size),
"tag_size\0", Py_BuildValue("B", meta->tag_size),
"node_mask\0", Py_BuildValue("k", meta->node_mask),
"index_mask\0", Py_BuildValue("k", meta->index_mask),
"distance_mask\0", Py_BuildValue("k", meta->distance_mask),
"tag_mask\0", Py_BuildValue("k", meta->tag_mask),
"tombstone\0", Py_BuildValue("k", meta->tombstone.node),
"is_compact\0", Py_BuildValue("B", meta->is_compact),
"inserting_block\0", Py_BuildValue("l", meta->inserting_block),
"greatest_allocated_block\0", Py_BuildValue("l", meta->greatest_allocated_block),
"greatest_deleted_block\0", Py_BuildValue("l", meta->greatest_deleted_block),
"greatest_refilled_block\0", Py_BuildValue("l", meta->greatest_refilled_block));
metadata = Py_BuildValue("{sOsOsOsOsOsOsOsOsOsOsOsOsOsOsO}",
"log_size\0", Py_BuildValue("B", meta->log_size),
"generation\0", Py_BuildValue("O", meta->generation),
"node_size\0", Py_BuildValue("B", meta->node_size),
"distance_size\0", Py_BuildValue("B", meta->distance_size),
"tag_size\0", Py_BuildValue("B", meta->tag_size),
"node_mask\0", Py_BuildValue("k", meta->node_mask),
"index_mask\0", Py_BuildValue("k", meta->index_mask),
"distance_mask\0", Py_BuildValue("k", meta->distance_mask),
"tag_mask\0", Py_BuildValue("k", meta->tag_mask),
"tombstone\0", Py_BuildValue("k", meta->tombstone.node),
"is_compact\0", Py_BuildValue("B", meta->is_compact),
"inserting_block\0", Py_BuildValue("l", meta->inserting_block),
"greatest_allocated_block\0", Py_BuildValue("l", meta->greatest_allocated_block),
"greatest_deleted_block\0", Py_BuildValue("l", meta->greatest_deleted_block),
"greatest_refilled_block\0", Py_BuildValue("l", meta->greatest_refilled_block));
if (metadata == NULL)
goto fail;

PyObject *index_nodes = Py_BuildValue("[]");
index_nodes = Py_BuildValue("[]");
if (index_nodes == NULL)
goto fail;

Expand All @@ -580,14 +587,14 @@ AtomicDict_Debug(AtomicDict *self)
Py_DECREF(n);
}

PyObject *blocks = Py_BuildValue("[]");
blocks = Py_BuildValue("[]");
if (blocks == NULL)
goto fail;

AtomicDict_Block *block;
PyObject *entries = NULL;
PyObject *entry_tuple = NULL;
PyObject *block_info = NULL;
entries = NULL;
entry_tuple = NULL;
block_info = NULL;
for (uint64_t i = 0; i <= meta->greatest_allocated_block; i++) {
block = meta->blocks[i];
entries = Py_BuildValue("[]");
Expand Down
160 changes: 80 additions & 80 deletions src/cereggii/atomic_dict/delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,49 +44,49 @@ AtomicDict_Delete(AtomicDict_Meta *meta, PyObject *key, Py_hash_t hash)
Py_DECREF(result.entry.value);
result.entry.value = NULL;

do {
if (CereggiiAtomic_CompareExchangeUInt8(
&result.entry_p->flags,
result.entry.flags,
result.entry.flags | ENTRY_FLAGS_TOMBSTONE
)) {
result.entry.flags |= ENTRY_FLAGS_TOMBSTONE;
} else {
// what if swapped?
AtomicDict_ReadEntry(result.entry_p, &result.entry);
}
} while (!(result.entry.flags & ENTRY_FLAGS_TOMBSTONE));

uint64_t entry_ix = result.node.index;
AtomicDict_BufferedNodeReader reader;
AtomicDict_Node temp[16];
int begin_write, end_write;

do {
AtomicDict_LookupEntry(meta, entry_ix, hash, &result);
assert(!result.error);
assert(result.found);
reader.zone = -1;
AtomicDict_ReadNodesFromZoneStartIntoBuffer(result.position, &reader, meta);
AtomicDict_CopyNodeBuffers(reader.buffer, temp);
AtomicDict_RobinHoodDelete(meta, temp, reader.idx_in_buffer);
AtomicDict_ComputeBeginEndWrite(meta, reader.buffer, temp, &begin_write, &end_write);
} while (!AtomicDict_AtomicWriteNodesAt(result.position - reader.idx_in_buffer + begin_write,
end_write - begin_write,
&reader.buffer[begin_write], &temp[begin_write], meta));

// do {
// if (CereggiiAtomic_CompareExchangeUInt8(
// &result.entry_p->flags,
// result.entry.flags,
// result.entry.flags | ENTRY_FLAGS_TOMBSTONE
// )) {
// result.entry.flags |= ENTRY_FLAGS_TOMBSTONE;
// } else {
// // what if swapped?
// AtomicDict_ReadEntry(result.entry_p, &result.entry);
// }
// } while (!(result.entry.flags & ENTRY_FLAGS_TOMBSTONE));
//
// uint64_t entry_ix = result.node.index;
// AtomicDict_BufferedNodeReader reader;
// AtomicDict_Node temp[16];
// int begin_write, end_write;
//
// do {
// AtomicDict_LookupEntry(meta, entry_ix, hash, &result);
// assert(!result.error);
// assert(result.found);
// reader.zone = -1;
// AtomicDict_ReadNodesFromZoneStartIntoBuffer(result.position, &reader, meta);
// AtomicDict_CopyNodeBuffers(reader.buffer, temp);
// AtomicDict_RobinHoodDelete(meta, temp, reader.idx_in_buffer);
// AtomicDict_ComputeBeginEndWrite(meta, reader.buffer, temp, &begin_write, &end_write);
// } while (!AtomicDict_AtomicWriteNodesAt(result.position - reader.idx_in_buffer + begin_write,
// end_write - begin_write,
// &reader.buffer[begin_write], &temp[begin_write], meta));
//
uint64_t block_num;
int64_t gab, gdb;
AtomicDict_EntryLoc swap_loc;
AtomicDict_Entry swap;

recycle_entry:
block_num = AtomicDict_BlockOf(entry_ix);
//
// recycle_entry:
block_num = AtomicDict_BlockOf(result.node.index);
gab = meta->greatest_allocated_block;
gdb = meta->greatest_deleted_block;

if (gdb > gab)
goto recycle_entry;
//
// if (gdb > gab)
// goto recycle_entry;

if (block_num == gdb + 1) {
int all_deleted = 1;
Expand All @@ -111,49 +111,49 @@ AtomicDict_Delete(AtomicDict_Meta *meta, PyObject *key, Py_hash_t hash)
}

if (block_num > gdb + 1) {
for (int i = 0; i < ATOMIC_DICT_ENTRIES_IN_BLOCK; ++i) {
swap_loc.location = ((gdb + 1) << ATOMIC_DICT_LOG_ENTRIES_IN_BLOCK) +
((i + hash) % ATOMIC_DICT_ENTRIES_IN_BLOCK);
swap_loc.entry = AtomicDict_GetEntryAt(swap_loc.location, meta);
AtomicDict_ReadEntry(swap_loc.entry, &swap);

if (!(swap.value == NULL || swap.flags & ENTRY_FLAGS_TOMBSTONE || swap.flags & ENTRY_FLAGS_SWAPPED))
goto swap_found;
}

should_shrink = AtomicDict_IncrementGreatestDeletedBlock(meta, gab, gdb);
goto recycle_entry; // don't handle failure

swap_found:
result.entry_p->key = swap.key;
result.entry_p->value = swap.value; // todo: what if value was updated? => use AtomicRef
result.entry_p->hash = swap.hash;
if (!CereggiiAtomic_CompareExchangeUInt8(
&swap_loc.entry->flags,
swap.flags,
swap.flags | ENTRY_FLAGS_SWAPPED
)) {
AtomicDict_ReadEntry(swap_loc.entry, &swap);
if (swap.value == NULL || swap.flags & ENTRY_FLAGS_TOMBSTONE || swap.flags & ENTRY_FLAGS_SWAPPED)
goto recycle_entry;
}

CereggiiAtomic_StoreUInt8(&result.entry_p->flags, result.entry.flags & ~ENTRY_FLAGS_TOMBSTONE);

AtomicDict_SearchResult swap_search;
do_swap:
AtomicDict_LookupEntry(meta, swap_loc.location, swap.hash, &swap_search);
AtomicDict_Node swapped = {
.tag = swap_search.node.tag,
.distance = swap_search.node.distance,
.index = entry_ix,
};

if (!AtomicDict_AtomicWriteNodesAt(swap_search.position, 1, &swap_search.node, &swapped, meta)) {
goto do_swap;
}
swap_loc.entry->key = NULL;
swap_loc.entry->value = NULL;
// for (int i = 0; i < ATOMIC_DICT_ENTRIES_IN_BLOCK; ++i) {
// swap_loc.location = ((gdb + 1) << ATOMIC_DICT_LOG_ENTRIES_IN_BLOCK) +
// ((i + hash) % ATOMIC_DICT_ENTRIES_IN_BLOCK);
// swap_loc.entry = AtomicDict_GetEntryAt(swap_loc.location, meta);
// AtomicDict_ReadEntry(swap_loc.entry, &swap);
//
// if (!(swap.value == NULL || swap.flags & ENTRY_FLAGS_TOMBSTONE || swap.flags & ENTRY_FLAGS_SWAPPED))
// goto swap_found;
// }

// should_shrink = AtomicDict_IncrementGreatestDeletedBlock(meta, gab, gdb);
// goto recycle_entry; // don't handle failure

// swap_found:
// result.entry_p->key = swap.key;
// result.entry_p->value = swap.value; // todo: what if value was updated? => use AtomicRef
// result.entry_p->hash = swap.hash;
// if (!CereggiiAtomic_CompareExchangeUInt8(
// &swap_loc.entry->flags,
// swap.flags,
// swap.flags | ENTRY_FLAGS_SWAPPED
// )) {
// AtomicDict_ReadEntry(swap_loc.entry, &swap);
// if (swap.value == NULL || swap.flags & ENTRY_FLAGS_TOMBSTONE || swap.flags & ENTRY_FLAGS_SWAPPED)
// goto recycle_entry;
// }
//
// CereggiiAtomic_StoreUInt8(&result.entry_p->flags, result.entry.flags & ~ENTRY_FLAGS_TOMBSTONE);
//
// AtomicDict_SearchResult swap_search;
// do_swap:
// AtomicDict_LookupEntry(meta, swap_loc.location, swap.hash, &swap_search);
// AtomicDict_Node swapped = {
// .tag = swap_search.node.tag,
// .distance = swap_search.node.distance,
// .index = entry_ix,
// };
//
// if (!AtomicDict_AtomicWriteNodesAt(swap_search.position, 1, &swap_search.node, &swapped, meta)) {
// goto do_swap;
// }
// swap_loc.entry->key = NULL;
// swap_loc.entry->value = NULL;
}

if (should_shrink)
Expand Down
4 changes: 3 additions & 1 deletion src/cereggii/atomic_dict/insert.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,10 @@ AtomicDict_CompareAndSet(AtomicDict *self, PyObject *key, PyObject *expected, Py
};
if (expected == NOT_FOUND || expected == ANY) {
int got_entry = AtomicDict_GetEmptyEntry(self, meta, &storage->reservation_buffer, &entry_loc, hash);
if (entry_loc.entry == NULL || got_entry == -1)
if (entry_loc.entry == NULL || got_entry == -1) {
_PyMutex_unlock(&storage->self_mutex);
goto fail;
}

if (got_entry == 0) { // => must grow
_PyMutex_unlock(&storage->self_mutex);
Expand Down
2 changes: 1 addition & 1 deletion src/cereggii/atomic_dict/lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ AtomicDict_LookupEntry(AtomicDict_Meta *meta, uint64_t entry_ix, Py_hash_t hash,
PyObject *
AtomicDict_GetItemOrDefault(AtomicDict *self, PyObject *key, PyObject *default_value)
{
AtomicDict_Meta *meta = NULL;
Py_hash_t hash = PyObject_Hash(key);
if (hash == -1)
goto fail;

AtomicDict_SearchResult result;
AtomicDict_Meta *meta = NULL;
retry:
meta = (AtomicDict_Meta *) AtomicRef_Get(self->metadata);

Expand Down
Loading

0 comments on commit 2e6857a

Please sign in to comment.