Skip to content

Instantly share code, notes, and snippets.

@jonwis
Created August 24, 2025 18:32
Show Gist options
  • Save jonwis/f50d8f3d28a85a074cb74aa13d4c774c to your computer and use it in GitHub Desktop.
Save jonwis/f50d8f3d28a85a074cb74aa13d4c774c to your computer and use it in GitHub Desktop.
Per-thread bucket storage
#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 &current->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