Skip to content

Instantly share code, notes, and snippets.

@mrtrizer
Last active October 19, 2020 07:27
Show Gist options
  • Save mrtrizer/ad98f848aab0c21f9c1ec913430d0ff4 to your computer and use it in GitHub Desktop.
Save mrtrizer/ad98f848aab0c21f9c1ec913430d0ff4 to your computer and use it in GitHub Desktop.
C language cache-friendly ECS
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <assert.h>
#include <stdbool.h>
typedef uint32_t EId;
typedef struct
{
EId* eIds;
uint8_t* data;
size_t itemSize;
size_t length;
size_t reserve;
size_t i;
size_t removedN;
void (*deinit)(void*);
void* (*realloc)(void *, size_t);
} ECDict;
size_t getCDataIndex(ECDict* dict, EId eId)
{
for (size_t i = dict->i; i < dict->length; i++)
if (dict->eIds[i] == eId)
return i;
for (size_t i = 0; i < dict->i; i++)
if (dict->eIds[i] == eId)
return i;
return SIZE_MAX;
}
void* getCData(ECDict* dict, EId eId)
{
size_t i = getCDataIndex(dict, eId);
if (i != SIZE_MAX)
{
dict->i = i;
return dict->data + i * dict->itemSize;
}
return NULL;
}
void* addC(ECDict* dict, EId eId)
{
if (dict->removedN > 0)
{
size_t i = getCDataIndex(dict, 0);
assert(i != SIZE_MAX);
dict->eIds[i] = eId;
dict->removedN--;
return dict->data + i * dict->itemSize;
}
else
{
if (dict->length == dict->reserve)
{
dict->reserve += 1000;
dict->data = dict->realloc(dict->data, dict->reserve * dict->itemSize);
dict->eIds = dict->realloc(dict->eIds, dict->reserve * sizeof(*dict->eIds));
}
dict->eIds[dict->length] = eId;
return dict->data + dict->itemSize * dict->length++;
}
}
bool removeC(ECDict* dict, EId eId)
{
size_t i = getCDataIndex(dict, eId);
if (i != SIZE_MAX)
{
dict->eIds[i] = 0;
if (dict->deinit)
dict->deinit(dict->data + dict->itemSize * i);
dict->removedN++;
return true;
}
return false;
}
typedef struct
{
int x;
int y;
} TestComponent;
void initTestComponent(void* ref, int x, int y)
{
TestComponent* c = ref;
c->x = x;
c->y = y;
}
void deinitTestComponent(void* ref)
{
TestComponent* c = ref;
c->x = c->y = 0;
}
int main(void)
{
ECDict test = { .itemSize = sizeof(TestComponent), .realloc = realloc, .deinit = deinitTestComponent };
initTestComponent(addC(&test, 1), 10, 20);
initTestComponent(addC(&test, 2), 11, 21);
assert(test.length == 2);
assert(test.reserve == 1000);
removeC(&test, 1);
initTestComponent(addC(&test, 3), 12, 22);
initTestComponent(addC(&test, 4), 13, 23);
assert(test.length == 3);
for (EId* id = test.eIds; id != test.eIds + test.length; id++)
{
TestComponent* c = getCData(&test, *id);
printf("%lu ( %u ) %d %d\n", id - test.eIds, *id, c->x, c->y);
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment