Created
August 24, 2025 18:32
-
-
Save jonwis/f50d8f3d28a85a074cb74aa13d4c774c to your computer and use it in GitHub Desktop.
Per-thread bucket storage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <wil/wistd_type_traits.h> | |
#include <wil/resource.h> | |
template<typename Q> struct bucketed_hash | |
{ | |
struct entry | |
{ | |
uint32_t thread_id; | |
wil::unique_process_heap_ptr<entry> next; | |
Q value; | |
}; | |
struct bucket_entry | |
{ | |
wil::srwlock lock; | |
wil::unique_process_heap_ptr<entry> head; | |
}; | |
const uint32_t bucket_count = 7; | |
bucket_entry[bucket_count] buckets; | |
Q* Get() | |
{ | |
// Get the current thread ID | |
uint32_t thread_id = GetCurrentThreadId(); | |
// Determine the appropriate bucket for this thread | |
size_t bucket_index = (thread_id >> 2) % bucket_count; | |
bucket_entry& bucket = buckets[bucket_index]; | |
// Lock the bucket and search for an existing entry | |
{ | |
auto lock = bucket.lock.lock_shared(); | |
for (auto current = bucket.head.get(); current != nullptr; current = current->next.get()) | |
{ | |
if (current->thread_id == thread_id) | |
{ | |
return ¤t->value; | |
} | |
} | |
} | |
// No entry for us, make a new one and insert it at the head | |
wil::unique_process_heap_ptr<entry> new_entry; | |
void* new_memory = allocProcessHeap(sizeof(entry)); | |
if (!new_memory) | |
{ | |
return nullptr; | |
} | |
new_entry.reset(new (new_memory) entry{ thread_id, Q{} }); | |
auto lock = bucket.lock.lock_exclusive(); | |
new_entry->next = wistd::move(bucket.head); | |
bucket.head = wistd::move(new_entry); | |
return &bucket.head->value; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment