rename all 'buckets' -> 'bins'

This commit is contained in:
jacob 2025-02-25 12:03:13 -06:00
parent 50da5f1bc6
commit a6d103f391
12 changed files with 251 additions and 251 deletions

View File

@ -29,8 +29,8 @@
#define IMAGE_PIXELS_PER_UNIT 256.0 #define IMAGE_PIXELS_PER_UNIT 256.0
/* 256^2 = 65536 buckets */ /* 64^2 = 4096 bins */
#define SPACE_CELL_BUCKETS_SQRT (256) #define SPACE_CELL_BINS_SQRT (64)
#define SPACE_CELL_SIZE 1.0f #define SPACE_CELL_SIZE 1.0f
#define SIM_TICKS_PER_SECOND 50 #define SIM_TICKS_PER_SECOND 50

View File

@ -26,8 +26,8 @@
#define PACKET_MSG_CHUNK_MAX_LEN 1024 #define PACKET_MSG_CHUNK_MAX_LEN 1024
#define PACKET_DATA_MAX_LEN 1280 /* Give enough space for msg chunk + header */ #define PACKET_DATA_MAX_LEN 1280 /* Give enough space for msg chunk + header */
#define NUM_CHANNEL_LOOKUP_BUCKETS 512 #define NUM_CHANNEL_LOOKUP_BINS 512
#define NUM_MSG_ASSEMBLER_LOOKUP_BUCKETS 16384 #define NUM_MSG_ASSEMBLER_LOOKUP_BINS 16384
enum host_packet_kind { enum host_packet_kind {
HOST_PACKET_KIND_NONE, HOST_PACKET_KIND_NONE,
@ -91,7 +91,7 @@ struct host_channel_list {
struct host_channel_node *last; struct host_channel_node *last;
}; };
struct host_channel_lookup_bucket { struct host_channel_lookup_bin {
struct host_channel *first; struct host_channel *first;
struct host_channel *last; struct host_channel *last;
}; };
@ -143,7 +143,7 @@ struct host_msg_assembler {
u8 *chunk_data; u8 *chunk_data;
}; };
struct host_msg_assembler_lookup_bucket { struct host_msg_assembler_lookup_bin {
struct host_msg_assembler *first; struct host_msg_assembler *first;
struct host_msg_assembler *last; struct host_msg_assembler *last;
}; };
@ -189,11 +189,11 @@ struct host *host_alloc(u16 listen_port)
host->channels = arena_dry_push(&host->channel_arena, struct host_channel); host->channels = arena_dry_push(&host->channel_arena, struct host_channel);
host->num_channel_lookup_buckets = NUM_CHANNEL_LOOKUP_BUCKETS; host->num_channel_lookup_bins = NUM_CHANNEL_LOOKUP_BINS;
host->channel_lookup_buckets = arena_push_array_zero(&host->arena, struct host_channel_lookup_bucket, host->num_channel_lookup_buckets); host->channel_lookup_bins = arena_push_array_zero(&host->arena, struct host_channel_lookup_bin, host->num_channel_lookup_bins);
host->num_msg_assembler_lookup_buckets = NUM_MSG_ASSEMBLER_LOOKUP_BUCKETS; host->num_msg_assembler_lookup_bins = NUM_MSG_ASSEMBLER_LOOKUP_BINS;
host->msg_assembler_lookup_buckets = arena_push_array_zero(&host->arena, struct host_msg_assembler_lookup_bucket, host->num_msg_assembler_lookup_buckets); host->msg_assembler_lookup_bins = arena_push_array_zero(&host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins);
host->sock = sock_alloc(listen_port, MEGABYTE(2), MEGABYTE(2)); host->sock = sock_alloc(listen_port, MEGABYTE(2), MEGABYTE(2));
@ -234,8 +234,8 @@ INTERNAL u64 hash_from_address(struct sock_address address)
INTERNAL struct host_channel *host_channel_from_address(struct host *host, struct sock_address address) INTERNAL struct host_channel *host_channel_from_address(struct host *host, struct sock_address address)
{ {
u64 hash = hash_from_address(address); u64 hash = hash_from_address(address);
struct host_channel_lookup_bucket *bucket = &host->channel_lookup_buckets[hash % host->num_channel_lookup_buckets]; struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins];
for (struct host_channel *channel = bucket->first; channel; channel = channel->next_address_hash) { for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) {
if (channel->address_hash == hash && sock_address_eq(channel->address, address)) { if (channel->address_hash == hash && sock_address_eq(channel->address, address)) {
return channel; return channel;
} }
@ -307,15 +307,15 @@ INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sock_
u64 address_hash = hash_from_address(address); u64 address_hash = hash_from_address(address);
channel->address_hash = address_hash; channel->address_hash = address_hash;
u64 bucket_index = address_hash % host->num_channel_lookup_buckets; u64 bin_index = address_hash % host->num_channel_lookup_bins;
struct host_channel_lookup_bucket *bucket = &host->channel_lookup_buckets[bucket_index]; struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[bin_index];
if (bucket->last) { if (bin->last) {
channel->prev_address_hash = bucket->last; channel->prev_address_hash = bin->last;
bucket->last->next_address_hash = channel; bin->last->next_address_hash = channel;
} else { } else {
bucket->first = channel; bin->first = channel;
} }
bucket->last = channel; bin->last = channel;
return channel; return channel;
} }
@ -326,18 +326,18 @@ INTERNAL void host_channel_release(struct host_channel *channel)
/* Release from lookup table */ /* Release from lookup table */
{ {
struct host_channel_lookup_bucket *bucket = &host->channel_lookup_buckets[channel->address_hash % host->num_channel_lookup_buckets]; struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[channel->address_hash % host->num_channel_lookup_bins];
struct host_channel *prev = channel->prev_address_hash; struct host_channel *prev = channel->prev_address_hash;
struct host_channel *next = channel->next_address_hash; struct host_channel *next = channel->next_address_hash;
if (prev) { if (prev) {
prev->next_address_hash = next; prev->next_address_hash = next;
} else { } else {
bucket->first = next; bin->first = next;
} }
if (next) { if (next) {
next->prev_address_hash = prev; next->prev_address_hash = prev;
} else { } else {
bucket->last = prev; bin->last = prev;
} }
} }
@ -379,8 +379,8 @@ INTERNAL u64 hash_from_channel_msg(struct host_channel_id channel_id, u64 msg_id
INTERNAL struct host_msg_assembler *host_get_msg_assembler(struct host *host, struct host_channel_id channel_id, u64 msg_id) INTERNAL struct host_msg_assembler *host_get_msg_assembler(struct host *host, struct host_channel_id channel_id, u64 msg_id)
{ {
u64 hash = hash_from_channel_msg(channel_id, msg_id); u64 hash = hash_from_channel_msg(channel_id, msg_id);
struct host_msg_assembler_lookup_bucket *bucket = &host->msg_assembler_lookup_buckets[hash % host->num_msg_assembler_lookup_buckets]; struct host_msg_assembler_lookup_bin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins];
for (struct host_msg_assembler *ma = bucket->first; ma; ma = ma->next_hash) { for (struct host_msg_assembler *ma = bin->first; ma; ma = ma->next_hash) {
if (ma->hash == hash && host_channel_id_eq(ma->channel->id, channel_id) && ma->msg_id == msg_id) { if (ma->hash == hash && host_channel_id_eq(ma->channel->id, channel_id) && ma->msg_id == msg_id) {
return ma; return ma;
} }
@ -435,14 +435,14 @@ INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel
/* Insert into lookup table */ /* Insert into lookup table */
u64 hash = hash_from_channel_msg(channel->id, msg_id); u64 hash = hash_from_channel_msg(channel->id, msg_id);
ma->hash = hash; ma->hash = hash;
struct host_msg_assembler_lookup_bucket *bucket = &host->msg_assembler_lookup_buckets[hash % host->num_msg_assembler_lookup_buckets]; struct host_msg_assembler_lookup_bin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins];
if (bucket->last) { if (bin->last) {
bucket->last->next_hash = ma; bin->last->next_hash = ma;
ma->prev_hash = bucket->last; ma->prev_hash = bin->last;
} else { } else {
bucket->first = ma; bin->first = ma;
} }
bucket->last = ma; bin->last = ma;
return ma; return ma;
} }
@ -470,19 +470,19 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
} }
/* Release from lookup table */ /* Release from lookup table */
struct host_msg_assembler_lookup_bucket *bucket = &host->msg_assembler_lookup_buckets[ma->hash % host->num_msg_assembler_lookup_buckets]; struct host_msg_assembler_lookup_bin *bin = &host->msg_assembler_lookup_bins[ma->hash % host->num_msg_assembler_lookup_bins];
{ {
struct host_msg_assembler *prev = ma->prev_hash; struct host_msg_assembler *prev = ma->prev_hash;
struct host_msg_assembler *next = ma->next_hash; struct host_msg_assembler *next = ma->next_hash;
if (prev) { if (prev) {
prev->next_hash = next; prev->next_hash = next;
} else { } else {
bucket->first = next; bin->first = next;
} }
if (next) { if (next) {
next->prev_hash = prev; next->prev_hash = prev;
} else { } else {
bucket->last = prev; bin->last = prev;
} }
} }

View File

@ -9,7 +9,7 @@
struct buddy_ctx; struct buddy_ctx;
struct host_snd_packet; struct host_snd_packet;
struct host_channel_lookup_bucket; struct host_channel_lookup_bin;
struct host_rcv_buffer; struct host_rcv_buffer;
enum host_cmd_kind { enum host_cmd_kind {
@ -81,11 +81,11 @@ struct host {
struct host_snd_packet *first_free_packet; /* Allocated in `arena` */ struct host_snd_packet *first_free_packet; /* Allocated in `arena` */
struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */ struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */
struct host_channel_lookup_bucket *channel_lookup_buckets; /* Allocated in `arena` */ struct host_channel_lookup_bin *channel_lookup_bins; /* Allocated in `arena` */
u64 num_channel_lookup_buckets; u64 num_channel_lookup_bins;
struct host_msg_assembler_lookup_bucket *msg_assembler_lookup_buckets; /* Allocated in `arena` */ struct host_msg_assembler_lookup_bin *msg_assembler_lookup_bins; /* Allocated in `arena` */
u64 num_msg_assembler_lookup_buckets; u64 num_msg_assembler_lookup_bins;
/* Double buffer for incoming data */ /* Double buffer for incoming data */
struct sys_mutex rcv_buffer_write_mutex; struct sys_mutex rcv_buffer_write_mutex;

156
src/sim.c
View File

@ -23,9 +23,9 @@
* An ent is the smallest unit of simulation state. * An ent is the smallest unit of simulation state.
*/ */
#define CLIENT_LOOKUP_BUCKETS 127 #define CLIENT_LOOKUP_BINS 127
#define TICK_LOOKUP_BUCKETS 127 #define TICK_LOOKUP_BINS 127
#define ID_LOOKUP_BUCKETS 4096 #define ID_LOOKUP_BINS 4096
/* ========================== * /* ========================== *
* Startup * Startup
@ -102,8 +102,8 @@ struct sim_client_store *sim_client_store_alloc(void)
store->arena = arena; store->arena = arena;
} }
store->valid = true; store->valid = true;
store->num_client_lookup_buckets = CLIENT_LOOKUP_BUCKETS; store->num_client_lookup_bins = CLIENT_LOOKUP_BINS;
store->client_lookup_buckets = arena_push_array_zero(&store->arena, struct sim_client_lookup_bucket, store->num_client_lookup_buckets); store->client_lookup_bins = arena_push_array_zero(&store->arena, struct sim_client_lookup_bin, store->num_client_lookup_bins);
store->clients_arena = arena_alloc(GIGABYTE(64)); store->clients_arena = arena_alloc(GIGABYTE(64));
store->clients = arena_dry_push(&store->clients_arena, struct sim_client); store->clients = arena_dry_push(&store->clients_arena, struct sim_client);
return store; return store;
@ -148,8 +148,8 @@ struct sim_client *sim_client_alloc(struct sim_client_store *store)
client->handle = handle; client->handle = handle;
client->snapshots_arena = arena_alloc(GIGABYTE(8)); client->snapshots_arena = arena_alloc(GIGABYTE(8));
client->num_snapshot_lookup_buckets = TICK_LOOKUP_BUCKETS; client->num_snapshot_lookup_bins = TICK_LOOKUP_BINS;
client->snapshot_lookup_buckets = arena_push_array_zero(&client->snapshots_arena, struct sim_snapshot_lookup_bucket, client->num_snapshot_lookup_buckets); client->snapshot_lookup_bins = arena_push_array_zero(&client->snapshots_arena, struct sim_snapshot_lookup_bin, client->num_snapshot_lookup_bins);
return client; return client;
} }
@ -157,11 +157,11 @@ struct sim_client *sim_client_alloc(struct sim_client_store *store)
void sim_client_release(struct sim_client *client) void sim_client_release(struct sim_client *client)
{ {
/* Release internal snapshot memory */ /* Release internal snapshot memory */
for (u64 i = 0; i < client->num_snapshot_lookup_buckets; ++i) { for (u64 i = 0; i < client->num_snapshot_lookup_bins; ++i) {
struct sim_snapshot_lookup_bucket *bucket = &client->snapshot_lookup_buckets[i]; struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[i];
struct sim_snapshot *ss = bucket->first; struct sim_snapshot *ss = bin->first;
while (ss) { while (ss) {
struct sim_snapshot *next = ss->next_in_bucket; struct sim_snapshot *next = ss->next_in_bin;
arena_release(&ss->ents_arena); arena_release(&ss->ents_arena);
arena_release(&ss->arena); arena_release(&ss->arena);
ss = next; ss = next;
@ -197,19 +197,19 @@ void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id
/* Remove old channel id from channel lookup */ /* Remove old channel id from channel lookup */
if (!host_channel_id_is_nil(old_channel_id)) { if (!host_channel_id_is_nil(old_channel_id)) {
u64 bucket_index = client->channel_hash % store->num_client_lookup_buckets; u64 bin_index = client->channel_hash % store->num_client_lookup_bins;
struct sim_client_lookup_bucket *bucket = &store->client_lookup_buckets[bucket_index]; struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
struct sim_client *prev = sim_client_from_handle(store, client->prev_in_bucket); struct sim_client *prev = sim_client_from_handle(store, client->prev_in_bin);
struct sim_client *next = sim_client_from_handle(store, client->next_in_bucket); struct sim_client *next = sim_client_from_handle(store, client->next_in_bin);
if (prev->valid) { if (prev->valid) {
prev->next_in_bucket = next->handle; prev->next_in_bin = next->handle;
} else { } else {
bucket->first = next->handle; bin->first = next->handle;
} }
if (next->valid) { if (next->valid) {
next->prev_in_bucket = prev->handle; next->prev_in_bin = prev->handle;
} else { } else {
bucket->last = prev->handle; bin->last = prev->handle;
} }
} }
@ -219,17 +219,17 @@ void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id
client->channel_id = channel_id; client->channel_id = channel_id;
client->channel_hash = channel_hash; client->channel_hash = channel_hash;
if (!host_channel_id_is_nil(channel_id)) { if (!host_channel_id_is_nil(channel_id)) {
u64 bucket_index = channel_hash % store->num_client_lookup_buckets; u64 bin_index = channel_hash % store->num_client_lookup_bins;
struct sim_client_lookup_bucket *bucket = &store->client_lookup_buckets[bucket_index]; struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
{ {
struct sim_client *prev_in_bucket = sim_client_from_handle(store, bucket->last); struct sim_client *prev_in_bin = sim_client_from_handle(store, bin->last);
if (prev_in_bucket->valid) { if (prev_in_bin->valid) {
prev_in_bucket->next_in_bucket = client->handle; prev_in_bin->next_in_bin = client->handle;
client->prev_in_bucket = prev_in_bucket->handle; client->prev_in_bin = prev_in_bin->handle;
} else { } else {
bucket->first = client->handle; bin->first = client->handle;
} }
bucket->last = client->handle; bin->last = client->handle;
} }
} }
} }
@ -238,9 +238,9 @@ struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, st
{ {
struct sim_client *res = sim_client_nil(); struct sim_client *res = sim_client_nil();
u64 channel_hash = hash_from_channel_id(channel_id); u64 channel_hash = hash_from_channel_id(channel_id);
u64 bucket_index = channel_hash % store->num_client_lookup_buckets; u64 bin_index = channel_hash % store->num_client_lookup_bins;
struct sim_client_lookup_bucket *bucket = &store->client_lookup_buckets[bucket_index]; struct sim_client_lookup_bin *bin = &store->client_lookup_bins[bin_index];
for (struct sim_client *client = sim_client_from_handle(store, bucket->first); client->valid; client = sim_client_from_handle(store, client->next_in_bucket)) { for (struct sim_client *client = sim_client_from_handle(store, bin->first); client->valid; client = sim_client_from_handle(store, client->next_in_bin)) {
if (client->channel_hash == channel_hash) { if (client->channel_hash == channel_hash) {
res = client; res = client;
break; break;
@ -308,15 +308,15 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
ss->local_client_ent = src->local_client_ent; ss->local_client_ent = src->local_client_ent;
ss->phys_iteration = src->phys_iteration; ss->phys_iteration = src->phys_iteration;
/* Copy id lookup buckets */ /* Copy id lookup bins */
ss->num_id_buckets = src->num_id_buckets > 0 ? src->num_id_buckets : ID_LOOKUP_BUCKETS; ss->num_id_bins = src->num_id_bins > 0 ? src->num_id_bins : ID_LOOKUP_BINS;
ss->id_buckets = arena_push_array(&ss->arena, struct sim_ent_bucket, ss->num_id_buckets); ss->id_bins = arena_push_array(&ss->arena, struct sim_ent_bin, ss->num_id_bins);
if (src->num_id_buckets > 0) { if (src->num_id_bins > 0) {
for (u64 i = 0; i < src->num_id_buckets; ++i) { for (u64 i = 0; i < src->num_id_bins; ++i) {
ss->id_buckets[i] = src->id_buckets[i]; ss->id_bins[i] = src->id_bins[i];
} }
} else { } else {
MEMZERO(ss->id_buckets, sizeof(*ss->id_buckets) * ss->num_id_buckets); MEMZERO(ss->id_bins, sizeof(*ss->id_bins) * ss->num_id_bins);
} }
/* Copy entities */ /* Copy entities */
@ -398,15 +398,15 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
/* Insert into lookup */ /* Insert into lookup */
{ {
u64 bucket_index = tick % client->num_snapshot_lookup_buckets; u64 bin_index = tick % client->num_snapshot_lookup_bins;
struct sim_snapshot_lookup_bucket *bucket = &client->snapshot_lookup_buckets[bucket_index]; struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
if (bucket->last) { if (bin->last) {
bucket->last->next_in_bucket = ss; bin->last->next_in_bin = ss;
ss->prev_in_bucket = bucket->last; ss->prev_in_bin = bin->last;
} else { } else {
bucket->first = ss; bin->first = ss;
} }
bucket->last = ss; bin->last = ss;
} }
return ss; return ss;
@ -418,19 +418,19 @@ void sim_snapshot_release(struct sim_snapshot *ss)
/* Remove from lookup */ /* Remove from lookup */
{ {
u64 bucket_index = ss->tick % client->num_snapshot_lookup_buckets; u64 bin_index = ss->tick % client->num_snapshot_lookup_bins;
struct sim_snapshot_lookup_bucket *bucket = &client->snapshot_lookup_buckets[bucket_index]; struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
struct sim_snapshot *prev = ss->prev_in_bucket; struct sim_snapshot *prev = ss->prev_in_bin;
struct sim_snapshot *next = ss->next_in_bucket; struct sim_snapshot *next = ss->next_in_bin;
if (prev) { if (prev) {
prev->next_in_bucket = next; prev->next_in_bin = next;
} else { } else {
bucket->first = next; bin->first = next;
} }
if (next) { if (next) {
next->prev_in_bucket = prev; next->prev_in_bin = prev;
} else { } else {
bucket->last = prev; bin->last = prev;
} }
} }
@ -488,9 +488,9 @@ struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick)
{ {
struct sim_snapshot *ss = sim_snapshot_nil(); struct sim_snapshot *ss = sim_snapshot_nil();
if (tick > 0) { if (tick > 0) {
u64 bucket_index = tick % client->num_snapshot_lookup_buckets; u64 bin_index = tick % client->num_snapshot_lookup_bins;
struct sim_snapshot_lookup_bucket *bucket = &client->snapshot_lookup_buckets[bucket_index]; struct sim_snapshot_lookup_bin *bin = &client->snapshot_lookup_bins[bin_index];
for (struct sim_snapshot *search = bucket->first; search; search = search->next_in_bucket) { for (struct sim_snapshot *search = bin->first; search; search = search->next_in_bin) {
if (search->tick == tick) { if (search->tick == tick) {
ss = search; ss = search;
break; break;
@ -652,33 +652,33 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
bw_write_uid(bw, receiver->ent_id.uid); bw_write_uid(bw, receiver->ent_id.uid);
/* Id buckets */ /* Id bins */
/* TODO: Don't encode these */ /* TODO: Don't encode these */
for (u64 i = 0; i < ss1->num_id_buckets; ++i) { for (u64 i = 0; i < ss1->num_id_bins; ++i) {
u32 old_first = 0; u32 old_first = 0;
u32 old_last = 0; u32 old_last = 0;
if (i < ss0->num_id_buckets) { if (i < ss0->num_id_bins) {
struct sim_ent_bucket *old_bucket = &ss0->id_buckets[i]; struct sim_ent_bin *old_bin = &ss0->id_bins[i];
old_first = old_bucket->first; old_first = old_bin->first;
old_last = old_bucket->last; old_last = old_bin->last;
} }
struct sim_ent_bucket *bucket = &ss1->id_buckets[i]; struct sim_ent_bin *bin = &ss1->id_bins[i];
u32 new_first = bucket->first; u32 new_first = bin->first;
u32 new_last = bucket->last; u32 new_last = bin->last;
if (new_first != old_first || new_last != old_last) { if (new_first != old_first || new_last != old_last) {
bw_write_bit(bw, 1); bw_write_bit(bw, 1);
bw_write_uv(bw, i); bw_write_uv(bw, i);
if (old_first == bucket->first) { if (old_first == bin->first) {
bw_write_bit(bw, 0); bw_write_bit(bw, 0);
} else { } else {
bw_write_bit(bw, 1); bw_write_bit(bw, 1);
bw_write_uv(bw, bucket->first); bw_write_uv(bw, bin->first);
} }
if (old_last == bucket->last) { if (old_last == bin->last) {
bw_write_bit(bw, 0); bw_write_bit(bw, 0);
} else { } else {
bw_write_bit(bw, 1); bw_write_bit(bw, 1);
bw_write_uv(bw, bucket->last); bw_write_uv(bw, bin->last);
} }
} }
} }
@ -723,26 +723,26 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
ss->local_client_ent = (struct sim_ent_id) { .uid = br_read_uid(br) }; ss->local_client_ent = (struct sim_ent_id) { .uid = br_read_uid(br) };
/* Id buckets */ /* Id bins */
/* TODO: Don't decode these, determine them implicitly from decoded ents */ /* TODO: Don't decode these, determine them implicitly from decoded ents */
{ {
b32 bucket_changed = br_read_bit(br); b32 bin_changed = br_read_bit(br);
while (bucket_changed) { while (bin_changed) {
u32 bucket_index = br_read_uv(br); u32 bin_index = br_read_uv(br);
if (bucket_index < ss->num_id_buckets) { if (bin_index < ss->num_id_bins) {
struct sim_ent_bucket *bucket = &ss->id_buckets[bucket_index]; struct sim_ent_bin *bin = &ss->id_bins[bin_index];
if (br_read_bit(br)) { if (br_read_bit(br)) {
bucket->first = br_read_uv(br); bin->first = br_read_uv(br);
} }
if (br_read_bit(br)) { if (br_read_bit(br)) {
bucket->last = br_read_uv(br); bin->last = br_read_uv(br);
} }
} else { } else {
/* Invalid bucket index */ /* Invalid bin index */
ASSERT(false); ASSERT(false);
} }
bucket_changed = br_read_bit(br); bin_changed = br_read_bit(br);
} }
} }

View File

@ -24,7 +24,7 @@ struct sim_startup_receipt sim_startup(void);
* Client store * Client store
* ========================== */ * ========================== */
struct sim_client_lookup_bucket { struct sim_client_lookup_bin {
struct sim_client_handle first; struct sim_client_handle first;
struct sim_client_handle last; struct sim_client_handle last;
}; };
@ -34,8 +34,8 @@ struct sim_client_store {
struct arena arena; struct arena arena;
/* Client lookup */ /* Client lookup */
struct sim_client_lookup_bucket *client_lookup_buckets; struct sim_client_lookup_bin *client_lookup_bins;
u64 num_client_lookup_buckets; u64 num_client_lookup_bins;
/* Clients */ /* Clients */
struct arena clients_arena; struct arena clients_arena;
@ -60,7 +60,7 @@ void sim_client_store_release(struct sim_client_store *store);
struct sim_snapshot; struct sim_snapshot;
struct sim_snapshot_lookup_bucket { struct sim_snapshot_lookup_bin {
struct sim_snapshot *first; struct sim_snapshot *first;
struct sim_snapshot *last; struct sim_snapshot *last;
}; };
@ -76,8 +76,8 @@ struct sim_client {
u64 channel_hash; u64 channel_hash;
struct sim_client_handle next_free; struct sim_client_handle next_free;
struct sim_client_handle next_in_bucket; struct sim_client_handle next_in_bin;
struct sim_client_handle prev_in_bucket; struct sim_client_handle prev_in_bin;
/* The client entity's id in the master sim (if relevant) */ /* The client entity's id in the master sim (if relevant) */
struct sim_ent_id ent_id; struct sim_ent_id ent_id;
@ -100,8 +100,8 @@ struct sim_client {
struct sim_snapshot *first_free_snapshot; struct sim_snapshot *first_free_snapshot;
/* Tick -> snapshot lookup */ /* Tick -> snapshot lookup */
u64 num_snapshot_lookup_buckets; u64 num_snapshot_lookup_bins;
struct sim_snapshot_lookup_bucket *snapshot_lookup_buckets; struct sim_snapshot_lookup_bin *snapshot_lookup_bins;
}; };
INLINE struct sim_client *sim_client_nil(void) INLINE struct sim_client *sim_client_nil(void)
@ -143,15 +143,15 @@ struct sim_control {
u32 flags; u32 flags;
}; };
struct sim_ent_bucket; struct sim_ent_bin;
struct sim_snapshot { struct sim_snapshot {
b32 valid; b32 valid;
u64 tick; u64 tick;
struct sim_client *client; struct sim_client *client;
struct sim_snapshot *next_free; struct sim_snapshot *next_free;
struct sim_snapshot *next_in_bucket; struct sim_snapshot *next_in_bin;
struct sim_snapshot *prev_in_bucket; struct sim_snapshot *prev_in_bin;
u64 prev_tick; u64 prev_tick;
u64 next_tick; u64 next_tick;
@ -174,8 +174,8 @@ struct sim_snapshot {
struct sim_ent_id local_client_ent; /* The id of the receiver's client ent */ struct sim_ent_id local_client_ent; /* The id of the receiver's client ent */
/* Id lookup */ /* Id lookup */
struct sim_ent_bucket *id_buckets; struct sim_ent_bin *id_bins;
u64 num_id_buckets; u64 num_id_bins;
/* Entities */ /* Entities */
struct arena ents_arena; struct arena ents_arena;

View File

@ -174,9 +174,9 @@ void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
* Ent id * Ent id
* ========================== */ * ========================== */
INTERNAL struct sim_ent_bucket *bucket_from_id(struct sim_snapshot *ss, struct sim_ent_id id) INTERNAL struct sim_ent_bin *bin_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
{ {
return &ss->id_buckets[id.uid.lo % ss->num_id_buckets]; return &ss->id_bins[id.uid.lo % ss->num_id_bins];
} }
/* NOTE: This should only really happen during ent allocation (it doesn't make sense for an allocated ent's id to change) */ /* NOTE: This should only really happen during ent allocation (it doesn't make sense for an allocated ent's id to change) */
@ -187,15 +187,15 @@ void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id)
if (!sim_ent_id_eq(old_id, id)) { if (!sim_ent_id_eq(old_id, id)) {
/* Release old from lookup */ /* Release old from lookup */
if (!sim_ent_id_eq(old_id, SIM_ENT_NIL_ID)) { if (!sim_ent_id_eq(old_id, SIM_ENT_NIL_ID)) {
struct sim_ent_bucket *bucket = bucket_from_id(ss, old_id); struct sim_ent_bin *bin = bin_from_id(ss, old_id);
u32 prev_index = 0; u32 prev_index = 0;
u32 next_index = 0; u32 next_index = 0;
u32 search_index = bucket->first; u32 search_index = bin->first;
struct sim_ent *prev = sim_ent_nil(); struct sim_ent *prev = sim_ent_nil();
struct sim_ent *next = sim_ent_nil(); struct sim_ent *next = sim_ent_nil();
struct sim_ent *search = ent_from_index(ss, search_index); struct sim_ent *search = ent_from_index(ss, search_index);
while (search->valid) { while (search->valid) {
next_index = search->next_in_id_bucket; next_index = search->next_in_id_bin;
next = ent_from_index(ss, next_index); next = ent_from_index(ss, next_index);
if (sim_ent_id_eq(search->id, old_id)) { if (sim_ent_id_eq(search->id, old_id)) {
break; break;
@ -206,35 +206,35 @@ void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id)
search = next; search = next;
} }
/* Old id not in bucket, this should be impossible. */ /* Old id not in bin, this should be impossible. */
ASSERT(search->valid); ASSERT(search->valid);
if (prev->valid) { if (prev->valid) {
prev->next_in_id_bucket = next_index; prev->next_in_id_bin = next_index;
} else { } else {
bucket->first = next_index; bin->first = next_index;
} }
if (next->valid) { if (next->valid) {
next->prev_in_id_bucket = prev_index; next->prev_in_id_bin = prev_index;
} else { } else {
bucket->last = prev_index; bin->last = prev_index;
} }
} }
/* Insert new id into lookup */ /* Insert new id into lookup */
if (!sim_ent_id_eq(id, SIM_ENT_NIL_ID)) { if (!sim_ent_id_eq(id, SIM_ENT_NIL_ID)) {
struct sim_ent_bucket *bucket = bucket_from_id(ss, id); struct sim_ent_bin *bin = bin_from_id(ss, id);
u32 ent_index = index_from_ent(ss, ent); u32 ent_index = index_from_ent(ss, ent);
struct sim_ent *last = ent_from_index(ss, bucket->last); struct sim_ent *last = ent_from_index(ss, bin->last);
if (last->valid) { if (last->valid) {
last->next_in_id_bucket = ent_index; last->next_in_id_bin = ent_index;
ent->prev_in_id_bucket = bucket->last; ent->prev_in_id_bin = bin->last;
} else { } else {
bucket->first = ent_index; bin->first = ent_index;
ent->prev_in_id_bucket = 0; ent->prev_in_id_bin = 0;
} }
bucket->last = ent_index; bin->last = ent_index;
} }
ent->id = id; ent->id = id;
@ -246,8 +246,8 @@ struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
{ {
struct sim_ent *res = sim_ent_nil(); struct sim_ent *res = sim_ent_nil();
if (!sim_ent_id_eq(id, SIM_ENT_NIL_ID) && ss->valid) { if (!sim_ent_id_eq(id, SIM_ENT_NIL_ID) && ss->valid) {
struct sim_ent_bucket *bucket = bucket_from_id(ss, id); struct sim_ent_bin *bin = bin_from_id(ss, id);
for (struct sim_ent *e = ent_from_index(ss, bucket->first); e->valid; e = ent_from_index(ss, e->next_in_id_bucket)) { for (struct sim_ent *e = ent_from_index(ss, bin->first); e->valid; e = ent_from_index(ss, e->next_in_id_bin)) {
if (sim_ent_id_eq(e->id, id)) { if (sim_ent_id_eq(e->id, id)) {
res = e; res = e;
break; break;
@ -591,8 +591,8 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
local->top = old.top; local->top = old.top;
/* Keep indices */ /* Keep indices */
local->next_in_id_bucket = old.next_in_id_bucket; local->next_in_id_bin = old.next_in_id_bin;
local->prev_in_id_bucket = old.prev_in_id_bucket; local->prev_in_id_bin = old.prev_in_id_bin;
local->next_free = old.next_free; local->next_free = old.next_free;
sim_ent_disable_prop(local, SIM_ENT_PROP_SYNC_SRC); sim_ent_disable_prop(local, SIM_ENT_PROP_SYNC_SRC);

View File

@ -87,8 +87,8 @@ struct sim_ent {
struct sim_ent_id last; struct sim_ent_id last;
/* Lists keyed by index in snapshot ent array */ /* Lists keyed by index in snapshot ent array */
u32 next_in_id_bucket; u32 next_in_id_bin;
u32 prev_in_id_bucket; u32 prev_in_id_bin;
u32 next_free; u32 next_free;
/* ====================================================================== */ /* ====================================================================== */
@ -331,7 +331,7 @@ struct sim_ent_prop_array {
u64 count; u64 count;
}; };
struct sim_ent_bucket { struct sim_ent_bin {
u32 first; u32 first;
u32 last; u32 last;
}; };

View File

@ -18,9 +18,9 @@ READONLY struct space _g_space_nil = { .valid = false };
* ========================== */ * ========================== */
/* NOTE: /* NOTE:
* The number of buckets determines how often tiles will collide in the spatial hash. * The number of bins determines how often tiles will collide in the spatial hash.
* For example, at `num_buckets_sqrt` = 256 (65536 buckets), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */ * For example, at `num_bins_sqrt` = 256 (65536 bins), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */
struct space *space_alloc(f32 cell_size, u32 num_buckets_sqrt) struct space *space_alloc(f32 cell_size, u32 num_bins_sqrt)
{ {
struct space *space; struct space *space;
{ {
@ -34,9 +34,9 @@ struct space *space_alloc(f32 cell_size, u32 num_buckets_sqrt)
space->cell_arena = arena_alloc(GIGABYTE(64)); space->cell_arena = arena_alloc(GIGABYTE(64));
space->cell_size = cell_size; space->cell_size = cell_size;
space->num_buckets = num_buckets_sqrt * num_buckets_sqrt; space->num_bins = num_bins_sqrt * num_bins_sqrt;
space->num_buckets_sqrt = num_buckets_sqrt; space->num_bins_sqrt = num_bins_sqrt;
space->buckets = arena_push_array_zero(&space->cell_arena, struct space_cell_bucket, space->num_buckets); space->bins = arena_push_array_zero(&space->cell_arena, struct space_cell_bin, space->num_bins);
return space; return space;
} }
@ -51,7 +51,7 @@ void space_reset(struct space *space)
{ {
arena_pop_to(&space->entry_arena, (u64)space->entries - (u64)space->entry_arena.base); arena_pop_to(&space->entry_arena, (u64)space->entries - (u64)space->entry_arena.base);
arena_reset(&space->cell_arena); arena_reset(&space->cell_arena);
space->buckets = arena_push_array_zero(&space->cell_arena, struct space_cell_bucket, space->num_buckets);; space->bins = arena_push_array_zero(&space->cell_arena, struct space_cell_bin, space->num_bins);;
space->num_entries_reserved = 0; space->num_entries_reserved = 0;
space->first_free_cell = NULL; space->first_free_cell = NULL;
space->first_free_cell_node = NULL; space->first_free_cell_node = NULL;
@ -83,9 +83,9 @@ INTERNAL struct v2i32 world_to_cell_coords(f32 cell_size, struct v2 world_pos)
return V2I32((i32)x, (i32)y); return V2I32((i32)x, (i32)y);
} }
INTERNAL i32 cell_coords_to_bucket_index(struct space *space, struct v2i32 cell_pos) INTERNAL i32 cell_coords_to_bin_index(struct space *space, struct v2i32 cell_pos)
{ {
i32 num_buckets_sqrt = space->num_buckets_sqrt; i32 num_bins_sqrt = space->num_bins_sqrt;
/* Cell pos of 0 is not valid and will be converted to -1 */ /* Cell pos of 0 is not valid and will be converted to -1 */
ASSERT(cell_pos.x != 0 && cell_pos.y != 0); ASSERT(cell_pos.x != 0 && cell_pos.y != 0);
@ -96,21 +96,21 @@ INTERNAL i32 cell_coords_to_bucket_index(struct space *space, struct v2i32 cell_
index_x -= (index_x >= 0); index_x -= (index_x >= 0);
index_y -= (index_y >= 0); index_y -= (index_y >= 0);
/* Un-mirror coords to prevent collisions between cells near the axes. (e.g. <3, 1> & <3, -1> should not collide) */ /* Un-mirror coords to prevent collisions between cells near the axes. (e.g. <3, 1> & <3, -1> should not collide) */
index_x += (index_x < 0) * (num_buckets_sqrt * ((index_x / -num_buckets_sqrt) + 1)); index_x += (index_x < 0) * (num_bins_sqrt * ((index_x / -num_bins_sqrt) + 1));
index_y += (index_y < 0) * (num_buckets_sqrt * ((index_y / -num_buckets_sqrt) + 1)); index_y += (index_y < 0) * (num_bins_sqrt * ((index_y / -num_bins_sqrt) + 1));
i32 bucket_index = (index_x % num_buckets_sqrt) + (index_y % num_buckets_sqrt) * num_buckets_sqrt; i32 bin_index = (index_x % num_bins_sqrt) + (index_y % num_bins_sqrt) * num_bins_sqrt;
ASSERT(bucket_index >= 0 && bucket_index < (i32)space->num_buckets); ASSERT(bin_index >= 0 && bin_index < (i32)space->num_bins);
return bucket_index; return bin_index;
} }
struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos) struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos)
{ {
i32 bucket_index = cell_coords_to_bucket_index(space, cell_pos); i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
struct space_cell_bucket *bucket = &space->buckets[bucket_index]; struct space_cell_bin *bin = &space->bins[bin_index];
struct space_cell *res = space_cell_nil(); struct space_cell *res = space_cell_nil();
for (struct space_cell *n = bucket->first_cell; n; n = n->next_in_bucket) { for (struct space_cell *n = bin->first_cell; n; n = n->next_in_bin) {
if (v2i32_eq(n->pos, cell_pos)) { if (v2i32_eq(n->pos, cell_pos)) {
res = n; res = n;
break; break;
@ -122,12 +122,12 @@ struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos)
INTERNAL void space_cell_node_alloc(struct v2i32 cell_pos, struct space_entry *entry) INTERNAL void space_cell_node_alloc(struct v2i32 cell_pos, struct space_entry *entry)
{ {
struct space *space = space_from_entry(entry); struct space *space = space_from_entry(entry);
i32 bucket_index = cell_coords_to_bucket_index(space, cell_pos); i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
struct space_cell_bucket *bucket = &space->buckets[bucket_index]; struct space_cell_bin *bin = &space->bins[bin_index];
/* Find existing cell */ /* Find existing cell */
struct space_cell *cell = NULL; struct space_cell *cell = NULL;
for (struct space_cell *n = bucket->first_cell; n; n = n->next_in_bucket) { for (struct space_cell *n = bin->first_cell; n; n = n->next_in_bin) {
if (v2i32_eq(n->pos, cell_pos)) { if (v2i32_eq(n->pos, cell_pos)) {
cell = n; cell = n;
break; break;
@ -143,15 +143,15 @@ INTERNAL void space_cell_node_alloc(struct v2i32 cell_pos, struct space_entry *e
cell = arena_push(&space->cell_arena, struct space_cell); cell = arena_push(&space->cell_arena, struct space_cell);
} }
MEMZERO_STRUCT(cell); MEMZERO_STRUCT(cell);
if (bucket->last_cell) { if (bin->last_cell) {
bucket->last_cell->next_in_bucket = cell; bin->last_cell->next_in_bin = cell;
cell->prev_in_bucket = bucket->last_cell; cell->prev_in_bin = bin->last_cell;
} else { } else {
bucket->first_cell = cell; bin->first_cell = cell;
} }
bucket->last_cell = cell; bin->last_cell = cell;
cell->pos = cell_pos; cell->pos = cell_pos;
cell->bucket = bucket; cell->bin = bin;
cell->valid = true; cell->valid = true;
} }
@ -193,7 +193,7 @@ INTERNAL void space_cell_node_release(struct space_cell_node *n)
struct space_cell *cell = n->cell; struct space_cell *cell = n->cell;
struct space_entry *entry = n->entry; struct space_entry *entry = n->entry;
struct space *space = space_from_entry(entry); struct space *space = space_from_entry(entry);
struct space_cell_bucket *bucket = cell->bucket; struct space_cell_bin *bin = cell->bin;
/* Remove from entry list */ /* Remove from entry list */
{ {
@ -229,18 +229,18 @@ INTERNAL void space_cell_node_release(struct space_cell_node *n)
/* If cell is now empty, release it */ /* If cell is now empty, release it */
if (!cell->first_node && !cell->last_node) { if (!cell->first_node && !cell->last_node) {
/* Remove from bucket */ /* Remove from bin */
struct space_cell *prev = cell->prev_in_bucket; struct space_cell *prev = cell->prev_in_bin;
struct space_cell *next = cell->next_in_bucket; struct space_cell *next = cell->next_in_bin;
if (prev) { if (prev) {
prev->next_in_bucket = next; prev->next_in_bin = next;
} else { } else {
bucket->first_cell = next; bin->first_cell = next;
} }
if (next) { if (next) {
next->prev_in_bucket = prev; next->prev_in_bin = prev;
} else { } else {
bucket->last_cell = prev; bin->last_cell = prev;
} }
cell->valid = false; cell->valid = false;

View File

@ -1,7 +1,7 @@
#ifndef SPACE_H #ifndef SPACE_H
#define SPACE_H #define SPACE_H
struct space_cell_bucket; struct space_cell_bin;
struct space_entry { struct space_entry {
b32 valid; b32 valid;
@ -40,14 +40,14 @@ struct space_cell {
struct space_cell_node *first_node; struct space_cell_node *first_node;
struct space_cell_node *last_node; struct space_cell_node *last_node;
struct space_cell_bucket *bucket; struct space_cell_bin *bin;
struct space_cell *prev_in_bucket; struct space_cell *prev_in_bin;
struct space_cell *next_in_bucket; struct space_cell *next_in_bin;
struct space_cell *next_free; struct space_cell *next_free;
}; };
struct space_cell_bucket { struct space_cell_bin {
struct space_cell *first_cell; struct space_cell *first_cell;
struct space_cell *last_cell; struct space_cell *last_cell;
}; };
@ -57,9 +57,9 @@ struct space {
f32 cell_size; f32 cell_size;
struct arena cell_arena; struct arena cell_arena;
struct space_cell_bucket *buckets; struct space_cell_bin *bins;
i32 num_buckets; i32 num_bins;
i32 num_buckets_sqrt; i32 num_bins_sqrt;
struct space_cell *first_free_cell; struct space_cell *first_free_cell;
struct space_cell_node *first_free_cell_node; struct space_cell_node *first_free_cell_node;
@ -104,7 +104,7 @@ INLINE struct space *space_nil(void)
* Space * Space
* ========================== */ * ========================== */
struct space *space_alloc(f32 cell_size, u32 num_buckets_sqrt); struct space *space_alloc(f32 cell_size, u32 num_bins_sqrt);
void space_release(struct space *space); void space_release(struct space *space);
void space_reset(struct space *space); void space_reset(struct space *space);

View File

@ -14,7 +14,7 @@
#include "math.h" #include "math.h"
#define CACHE_MEMORY_BUDGET (MEGABYTE(256)) #define CACHE_MEMORY_BUDGET (MEGABYTE(256))
#define CACHE_BUCKETS_COUNT 1024 #define CACHE_BINS_COUNT 1024
#define MAX_LOADER_THREADS 4 #define MAX_LOADER_THREADS 4
@ -30,8 +30,8 @@
#define TEXTURE_ARENA_RESERVE MEGABYTE(1) #define TEXTURE_ARENA_RESERVE MEGABYTE(1)
#define SHEET_ARENA_RESERVE MEGABYTE(64) #define SHEET_ARENA_RESERVE MEGABYTE(64)
#define SHEET_SPAN_LOOKUP_TABLE_BUCKET_RATIO 2.0 #define SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO 2.0
#define SHEET_SLICE_LOOKUP_TABLE_BUCKET_RATIO 2.0 #define SHEET_SLICE_LOOKUP_TABLE_BIN_RATIO 2.0
/* ========================== * /* ========================== *
* Loader cmd structs * Loader cmd structs
@ -96,7 +96,7 @@ struct cache_node {
#endif #endif
}; };
struct cache_bucket { struct cache_bin {
struct sys_mutex mutex; struct sys_mutex mutex;
struct cache_node *first; struct cache_node *first;
}; };
@ -104,7 +104,7 @@ struct cache_bucket {
struct cache { struct cache {
struct atomic_u64 memory_usage; struct atomic_u64 memory_usage;
struct arena arena; struct arena arena;
struct cache_bucket *buckets; struct cache_bin *bins;
struct sys_mutex node_pool_mutex; struct sys_mutex node_pool_mutex;
struct cache_node *node_pool_first_free; struct cache_node *node_pool_first_free;
}; };
@ -248,9 +248,9 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re
G.cache.node_pool_mutex = sys_mutex_alloc(); G.cache.node_pool_mutex = sys_mutex_alloc();
G.cache.arena = arena_alloc(GIGABYTE(64)); G.cache.arena = arena_alloc(GIGABYTE(64));
G.cache.buckets = arena_push_array_zero(&G.cache.arena, struct cache_bucket, CACHE_BUCKETS_COUNT); G.cache.bins = arena_push_array_zero(&G.cache.arena, struct cache_bin, CACHE_BINS_COUNT);
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) { for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
G.cache.buckets[i].mutex = sys_mutex_alloc(); G.cache.bins[i].mutex = sys_mutex_alloc();
} }
G.load_cmds_arena = arena_alloc(GIGABYTE(64)); G.load_cmds_arena = arena_alloc(GIGABYTE(64));
@ -430,7 +430,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
if (ase.num_spans > 0) { if (ase.num_spans > 0) {
__profscope(init_spans); __profscope(init_spans);
sheet.spans = arena_push_array_zero(arena, struct sprite_sheet_span, sheet.spans_count); sheet.spans = arena_push_array_zero(arena, struct sprite_sheet_span, sheet.spans_count);
sheet.spans_dict = fixed_dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BUCKET_RATIO)); sheet.spans_dict = fixed_dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
u64 index = 0; u64 index = 0;
for (struct ase_span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) { for (struct ase_span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) {
struct string name = string_copy(arena, ase_span->name); struct string name = string_copy(arena, ase_span->name);
@ -498,7 +498,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
/* Allocate slice groups & fill originals in 2d array */ /* Allocate slice groups & fill originals in 2d array */
sheet.slice_groups_count = num_temp_slice_group_nodes; sheet.slice_groups_count = num_temp_slice_group_nodes;
sheet.slice_groups = arena_push_array_zero(arena, struct sprite_sheet_slice_group, sheet.slice_groups_count); sheet.slice_groups = arena_push_array_zero(arena, struct sprite_sheet_slice_group, sheet.slice_groups_count);
sheet.slice_groups_dict = fixed_dict_init(arena, (u64)(num_temp_slice_group_nodes * SHEET_SLICE_LOOKUP_TABLE_BUCKET_RATIO)); sheet.slice_groups_dict = fixed_dict_init(arena, (u64)(num_temp_slice_group_nodes * SHEET_SLICE_LOOKUP_TABLE_BIN_RATIO));
u64 index = 0; u64 index = 0;
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) { for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
@ -700,10 +700,10 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag)
* Scope * Scope
* ========================== */ * ========================== */
INTERNAL void scope_ensure_reference(struct sprite_scope *scope, struct cache_node *cache_node, u64 cache_bucket_index) INTERNAL void scope_ensure_reference(struct sprite_scope *scope, struct cache_node *cache_node, u64 cache_bin_index)
{ {
__prof; __prof;
struct sprite_scope_reference **ref_next = &scope->reference_buckets[cache_bucket_index]; struct sprite_scope_reference **ref_next = &scope->reference_bins[cache_bin_index];
struct sprite_scope_reference *ref = *ref_next; struct sprite_scope_reference *ref = *ref_next;
while (ref) { while (ref) {
if (ref->cache_node == cache_node) { if (ref->cache_node == cache_node) {
@ -740,13 +740,13 @@ struct sprite_scope *sprite_scope_begin(void)
if (tctx->first_free_scope) { if (tctx->first_free_scope) {
res = tctx->first_free_scope; res = tctx->first_free_scope;
tctx->first_free_scope = res->next_free; tctx->first_free_scope = res->next_free;
MEMZERO(res->reference_buckets, sizeof(*res->reference_buckets) * CACHE_BUCKETS_COUNT); MEMZERO(res->reference_bins, sizeof(*res->reference_bins) * CACHE_BINS_COUNT);
*res = (struct sprite_scope) { *res = (struct sprite_scope) {
.reference_buckets = res->reference_buckets .reference_bins = res->reference_bins
}; };
} else { } else {
res = arena_push_zero(&tctx->arena, struct sprite_scope); res = arena_push_zero(&tctx->arena, struct sprite_scope);
res->reference_buckets = arena_push_array_zero(&tctx->arena, struct sprite_scope_reference *, CACHE_BUCKETS_COUNT); res->reference_bins = arena_push_array_zero(&tctx->arena, struct sprite_scope_reference *, CACHE_BINS_COUNT);
} }
return res; return res;
@ -755,8 +755,8 @@ struct sprite_scope *sprite_scope_begin(void)
void sprite_scope_end(struct sprite_scope *scope) void sprite_scope_end(struct sprite_scope *scope)
{ {
struct sprite_tctx *tctx = thread_local_var_eval(&tl_sprite_tctx); struct sprite_tctx *tctx = thread_local_var_eval(&tl_sprite_tctx);
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) { for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
struct sprite_scope_reference *ref = scope->reference_buckets[i]; struct sprite_scope_reference *ref = scope->reference_bins[i];
while (ref) { while (ref) {
/* Decrement refcount */ /* Decrement refcount */
node_refcount_add(ref->cache_node, -1); node_refcount_add(ref->cache_node, -1);
@ -783,18 +783,18 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
struct cache_node **nonmatching_next = NULL; struct cache_node **nonmatching_next = NULL;
struct cache_node_hash hash = cache_node_hash_from_tag_hash(tag.hash, kind); struct cache_node_hash hash = cache_node_hash_from_tag_hash(tag.hash, kind);
u64 cache_bucket_index = hash.v % CACHE_BUCKETS_COUNT; u64 cache_bin_index = hash.v % CACHE_BINS_COUNT;
struct cache_bucket *bucket = &G.cache.buckets[cache_bucket_index]; struct cache_bin *bin = &G.cache.bins[cache_bin_index];
/* Lookup */ /* Lookup */
/* TODO: Spinlock */ /* TODO: Spinlock */
{ {
struct sys_lock lock = sys_mutex_lock_s(&bucket->mutex); struct sys_lock lock = sys_mutex_lock_s(&bin->mutex);
nonmatching_next = &bucket->first; nonmatching_next = &bin->first;
n = *nonmatching_next; n = *nonmatching_next;
while (n) { while (n) {
if (n->hash.v == hash.v) { if (n->hash.v == hash.v) {
scope_ensure_reference(scope, n, cache_bucket_index); scope_ensure_reference(scope, n, cache_bin_index);
break; break;
} else { } else {
nonmatching = n; nonmatching = n;
@ -808,7 +808,7 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
/* Allocate new node if necessary */ /* Allocate new node if necessary */
if (!n) { if (!n) {
__profscope(node_lookup_allocate); __profscope(node_lookup_allocate);
struct sys_lock bucket_lock = sys_mutex_lock_e(&bucket->mutex); struct sys_lock bin_lock = sys_mutex_lock_e(&bin->mutex);
{ {
/* Alloc node */ /* Alloc node */
{ {
@ -822,8 +822,8 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
} }
sys_mutex_unlock(&pool_lock); sys_mutex_unlock(&pool_lock);
} }
/* Init node and add to bucket */ /* Init node and add to bin */
scope_ensure_reference(scope, n, cache_bucket_index); scope_ensure_reference(scope, n, cache_bin_index);
*nonmatching_next = n; *nonmatching_next = n;
if (nonmatching) { if (nonmatching) {
nonmatching->next_hash = n; nonmatching->next_hash = n;
@ -834,7 +834,7 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
n->texture = G.nil_texture; n->texture = G.nil_texture;
n->sheet = G.nil_sheet; n->sheet = G.nil_sheet;
} }
sys_mutex_unlock(&bucket_lock); sys_mutex_unlock(&bin_lock);
} }
return n; return n;
@ -1039,7 +1039,7 @@ struct evict_node {
b32 force_evict; b32 force_evict;
struct cache_node_refcount refcount; struct cache_node_refcount refcount;
struct cache_node *cache_node; struct cache_node *cache_node;
struct cache_bucket *cache_bucket; struct cache_bin *cache_bin;
struct evict_node *next_consider; struct evict_node *next_consider;
struct evict_node *next_consider_lru; struct evict_node *next_consider_lru;
struct evict_node *next_evicted; struct evict_node *next_evicted;
@ -1063,11 +1063,11 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
b32 cache_over_budget = atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET; b32 cache_over_budget = atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET;
if (cache_over_budget || RESOURCE_RELOADING) { if (cache_over_budget || RESOURCE_RELOADING) {
__profscope(eviction_scan); __profscope(eviction_scan);
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) { for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
struct cache_bucket *bucket = &G.cache.buckets[i]; struct cache_bin *bin = &G.cache.bins[i];
struct sys_lock bucket_lock = sys_mutex_lock_s(&bucket->mutex); struct sys_lock bin_lock = sys_mutex_lock_s(&bin->mutex);
{ {
struct cache_node *n = bucket->first; struct cache_node *n = bin->first;
while (n) { while (n) {
b32 consider_for_eviction = false; b32 consider_for_eviction = false;
b32 force_evict = false; b32 force_evict = false;
@ -1122,7 +1122,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
if (consider_for_eviction) { if (consider_for_eviction) {
struct evict_node *evict_node = arena_push_zero(scratch.arena, struct evict_node); struct evict_node *evict_node = arena_push_zero(scratch.arena, struct evict_node);
evict_node->cache_node = n; evict_node->cache_node = n;
evict_node->cache_bucket = bucket; evict_node->cache_bin = bin;
evict_node->refcount = refcount; evict_node->refcount = refcount;
evict_node->force_evict = force_evict; evict_node->force_evict = force_evict;
evict_node->next_consider = head_consider; evict_node->next_consider = head_consider;
@ -1132,7 +1132,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
n = n->next_hash; n = n->next_hash;
} }
} }
sys_mutex_unlock(&bucket_lock); sys_mutex_unlock(&bin_lock);
} }
} }
@ -1162,19 +1162,19 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
__profscope(eviction_cache_removal); __profscope(eviction_cache_removal);
b32 stop_evicting = false; b32 stop_evicting = false;
for (struct evict_node *en = head_consider_lru; en && !stop_evicting; en = en->next_consider_lru) { for (struct evict_node *en = head_consider_lru; en && !stop_evicting; en = en->next_consider_lru) {
struct cache_bucket *bucket = en->cache_bucket; struct cache_bin *bin = en->cache_bin;
struct cache_node *n = en->cache_node; struct cache_node *n = en->cache_node;
struct sys_lock bucket_lock = sys_mutex_lock_e(&bucket->mutex); struct sys_lock bin_lock = sys_mutex_lock_e(&bin->mutex);
{ {
struct cache_node_refcount refcount = *(struct cache_node_refcount *)atomic_u64_raw(&n->refcount_struct); struct cache_node_refcount refcount = *(struct cache_node_refcount *)atomic_u64_raw(&n->refcount_struct);
if (refcount.count > 0 || ((refcount.last_modified_cycle != en->refcount.last_modified_cycle) && !en->force_evict)) { if (refcount.count > 0 || ((refcount.last_modified_cycle != en->refcount.last_modified_cycle) && !en->force_evict)) {
/* Cache node has been referenced since scan, skip eviction. */ /* Cache node has been referenced since scan, skip eviction. */
} else if (en->force_evict || atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET) { } else if (en->force_evict || atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET) {
/* Remove from cache bucket */ /* Remove from cache bin */
if (n->prev_hash) { if (n->prev_hash) {
n->prev_hash->next_hash = n->next_hash; n->prev_hash->next_hash = n->next_hash;
} else { } else {
bucket->first = n->next_hash; bin->first = n->next_hash;
} }
if (n->next_hash) { if (n->next_hash) {
n->next_hash->prev_hash = n->prev_hash; n->next_hash->prev_hash = n->prev_hash;
@ -1188,7 +1188,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
stop_evicting = true; stop_evicting = true;
} }
} }
sys_mutex_unlock(&bucket_lock); sys_mutex_unlock(&bin_lock);
} }
} }

View File

@ -32,7 +32,7 @@ b32 sprite_tag_eq(struct sprite_tag t1, struct sprite_tag t2);
* ========================== */ * ========================== */
struct sprite_scope { struct sprite_scope {
struct sprite_scope_reference **reference_buckets; struct sprite_scope_reference **reference_bins;
struct sprite_scope *next_free; struct sprite_scope *next_free;
}; };

View File

@ -119,7 +119,7 @@ INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_
/* ========================== * /* ========================== *
* Fixed Dict * Fixed Dict
* *
* Simple fixed bucket-count string->value chaining dict for generic use * Simple fixed bin-count string->value chaining dict for generic use
* ========================== */ * ========================== */
struct fixed_dict_entry { struct fixed_dict_entry {
@ -129,22 +129,22 @@ struct fixed_dict_entry {
struct fixed_dict_entry *next; struct fixed_dict_entry *next;
}; };
struct fixed_dict_bucket { struct fixed_dict_bin {
struct fixed_dict_entry *entry_head; struct fixed_dict_entry *entry_head;
}; };
struct fixed_dict { struct fixed_dict {
u64 buckets_count; u64 bins_count;
struct fixed_dict_bucket *buckets; struct fixed_dict_bin *bins;
}; };
INLINE struct fixed_dict fixed_dict_init(struct arena *arena, u64 buckets_count) INLINE struct fixed_dict fixed_dict_init(struct arena *arena, u64 bins_count)
{ {
__prof; __prof;
struct fixed_dict dict = ZI; struct fixed_dict dict = ZI;
buckets_count = max_u64(buckets_count, 1); /* Ensure at least 1 bucket */ bins_count = max_u64(bins_count, 1); /* Ensure at least 1 bin */
dict.buckets_count = buckets_count; dict.bins_count = bins_count;
dict.buckets = arena_push_array_zero(arena, struct fixed_dict_bucket, buckets_count); dict.bins = arena_push_array_zero(arena, struct fixed_dict_bin, bins_count);
return dict; return dict;
} }
@ -154,10 +154,10 @@ INLINE void fixed_dict_set(struct arena *arena, struct fixed_dict *dict, struct
__prof; __prof;
u64 hash = hash_fnv64(HASH_FNV64_BASIS, key); u64 hash = hash_fnv64(HASH_FNV64_BASIS, key);
u64 index = hash % dict->buckets_count; u64 index = hash % dict->bins_count;
struct fixed_dict_bucket *bucket = &dict->buckets[index]; struct fixed_dict_bin *bin = &dict->bins[index];
struct fixed_dict_entry *entry = bucket->entry_head; struct fixed_dict_entry *entry = bin->entry_head;
while (entry) { while (entry) {
if (hash == entry->hash) { if (hash == entry->hash) {
/* Existing match found, replace its contents */ /* Existing match found, replace its contents */
@ -173,9 +173,9 @@ INLINE void fixed_dict_set(struct arena *arena, struct fixed_dict *dict, struct
entry->key = key; entry->key = key;
entry->value = value; entry->value = value;
entry->hash = hash; entry->hash = hash;
entry->next = bucket->entry_head; entry->next = bin->entry_head;
bucket->entry_head = entry; bin->entry_head = entry;
} }
INLINE void *fixed_dict_get(const struct fixed_dict *dict, struct string key) INLINE void *fixed_dict_get(const struct fixed_dict *dict, struct string key)
@ -183,10 +183,10 @@ INLINE void *fixed_dict_get(const struct fixed_dict *dict, struct string key)
__prof; __prof;
u64 hash = hash_fnv64(HASH_FNV64_BASIS, key); u64 hash = hash_fnv64(HASH_FNV64_BASIS, key);
u64 index = hash % dict->buckets_count; u64 index = hash % dict->bins_count;
struct fixed_dict_bucket *bucket = &dict->buckets[index]; struct fixed_dict_bin *bin = &dict->bins[index];
for (struct fixed_dict_entry *entry = bucket->entry_head; entry; entry = entry->next) { for (struct fixed_dict_entry *entry = bin->entry_head; entry; entry = entry->next) {
if (hash == entry->hash) { if (hash == entry->hash) {
/* Match found */ /* Match found */
return entry->value; return entry->value;