Memory management tweaks

There are no memory leaks,
yet, I discover, with my steady course,
thru my small valgrind peeks,
that nvidia are a bunch of stupid a-holes.
This commit is contained in:
Marcel Plch 2024-11-11 17:42:57 +01:00
parent 68d3d4b692
commit c2b9dfdd29
Signed by: dormouse
GPG key ID: 2CA77596BC4BDFFE
6 changed files with 113 additions and 30 deletions

View file

@ -32,6 +32,7 @@ typedef struct _cx_gl_ctx {
GLFWwindow *window;
ModelRegistry *mr;
GLuint *VertexArrayIDs;
void (*free)(void *self);
size_t VertexArray_count;
size_t VertexArray_size;
GLuint *programIDs;
@ -43,6 +44,7 @@ typedef struct _cx_nn_ctx {
Neural_Network *nn;
float *input_buffer;
float *output_buffer;
void (*free)(void *self);
} CX_NN_CTX;
typedef struct _cx_ctx {
@ -55,7 +57,7 @@ typedef struct _cx_ctx {
CX_Context *cx_context_new(void);
int cx_glinit(GLFWwindow **);
int cx_glinit(CX_GL_CTX **);
int cx_nninit(Neural_Network **);
int cx_init(CX_Context **);

View file

@ -14,6 +14,7 @@ typedef struct _cx_thrgr {
} CX_ThreadGroup;
CX_ThreadGroup *cx_threadGroup_new(void *(*)(void *), void *);
void cx_threadGroup_free(CX_ThreadGroup *);
#endif

View file

@ -26,6 +26,7 @@ typedef struct _neural_data {
} Neural_Data;
Neural_Network *neural_new(size_t, size_t, size_t);
void neural_free(Neural_Network *);
void neural_randomize(Neural_Network *);
float *neural_process(Neural_Network *, float *);
Neural_Data *neural_getData(Neural_Network *, size_t);

View file

@ -80,13 +80,58 @@ cx_loadShaders(GLuint *VertexArrayID, GLuint *programID) {
return 0;
}
void
gl_ctx_free(void *self) {
CX_GL_CTX *gl_ctx;
gl_ctx = self;
if (gl_ctx) {
free(gl_ctx->VertexArrayIDs);
free(gl_ctx->programIDs);
modelRegistry_free(gl_ctx->mr);
}
free(gl_ctx);
}
void
nn_ctx_free(void *self) {
CX_NN_CTX *nn_ctx;
nn_ctx = self;
if (nn_ctx) {
free(nn_ctx->input_buffer);
free(nn_ctx->output_buffer);
neural_free(nn_ctx->nn);
}
free(nn_ctx);
}
int
cx_glinit(GLFWwindow **window) {
cx_glinit(CX_GL_CTX **gl_ctx) {
// Initialize OpenGL context
(*gl_ctx)->VertexArrayIDs = calloc(1, sizeof(GLuint));
if (!(*gl_ctx)->VertexArrayIDs) {
goto err;
}
(*gl_ctx)->VertexArray_count = 0;
(*gl_ctx)->VertexArray_size = 1;
(*gl_ctx)->programIDs = calloc(1, sizeof(GLuint));
if (!(*gl_ctx)->programIDs) {
goto err;
}
(*gl_ctx)->ProgramID_count = 0;
(*gl_ctx)->ProgramID_size = 1;
(*gl_ctx)->free = &gl_ctx_free;
// Initialise GLFW
printf("Initializing OpenGL.\n");
if(!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
goto err;
}
glfwWindowHint(GLFW_SAMPLES, 4);
@ -98,30 +143,33 @@ cx_glinit(GLFWwindow **window) {
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Open a window and create its OpenGL context
*window = glfwCreateWindow(1280, 720, "C-X", NULL, NULL);
if (*window == NULL) {
(*gl_ctx)->window = glfwCreateWindow(1280, 720, "C-X", NULL, NULL);
if ((*gl_ctx)->window == NULL) {
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return -1;
goto err;
}
printf("Window created.\n");
glfwMakeContextCurrent(*window);
glfwMakeContextCurrent((*gl_ctx)->window);
// Initialize GLEW
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
glfwTerminate();
return -1;
goto err;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(*window, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetInputMode((*gl_ctx)->window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark grey background
glClearColor(0.15f, 0.15f, 0.15f, 0.0f);
return 0;
err:
return -1;
}
int
@ -147,27 +195,11 @@ cx_init(CX_Context **cx_ctx) {
printf("Initializing CX.\n");
gl_ctx = calloc(1, sizeof(CX_GL_CTX));
gl_ctx->VertexArrayIDs = calloc(1, sizeof(GLuint));
if (!gl_ctx->VertexArrayIDs) {
goto err;
}
gl_ctx->VertexArray_count = 0;
gl_ctx->VertexArray_size = 1;
gl_ctx->programIDs = calloc(1, sizeof(GLuint));
if (!gl_ctx->programIDs) {
goto err;
}
gl_ctx->ProgramID_count = 0;
gl_ctx->ProgramID_size = 1;
// Establish a model registry
gl_ctx->mr = modelRegistry_new();
nn_ctx = calloc(1, sizeof(CX_NN_CTX));
nn_ctx->free = &nn_ctx_free;
*cx_ctx = calloc(1, sizeof(CX_Context));
gl_ctx = calloc(1, sizeof(CX_GL_CTX));
(*cx_ctx)->gl_ctx = gl_ctx;
(*cx_ctx)->nn_ctx = nn_ctx;
@ -228,7 +260,7 @@ cx_glthread(void *self) {
CX_Thread *self_t = self;
CX_GL_CTX *gl_ctx = self_t->ctx;
cx_glinit(&gl_ctx->window);
cx_glinit(&gl_ctx);
if (cx_loadShaders(gl_ctx->VertexArrayIDs, gl_ctx->programIDs)) {
return NULL;
@ -253,6 +285,9 @@ int
cx_run(CX_Context *ctx) {
CX_ThreadGroup *tg[2];
// Establish a model registry
ctx->gl_ctx->mr = modelRegistry_new();
tg[1] = cx_threadGroup_new(&cx_nnthread, ctx->nn_ctx);
pthread_join(tg[1]->group_manager->thread, NULL);
@ -263,7 +298,12 @@ cx_run(CX_Context *ctx) {
pthread_join(tg[0]->group_manager->thread, NULL);
modelRegistry_free(ctx->gl_ctx->mr);
cx_threadGroup_free(tg[0]);
cx_threadGroup_free(tg[1]);
free(ctx->threads);
free(ctx);
return 0;
}

View file

@ -23,6 +23,20 @@ err:
return NULL;
}
void
cx_thread_free(CX_Thread *self) {
if (self) {
/* TODO */
/* This is naive in its current form and will shatter
* sooner or later.
* Fix the context structures so that this call
* is guaranteed not to touch invalid memory.
*/
((CX_GL_CTX *)self->ctx)->free(self->ctx);
}
free(self);
}
CX_ThreadGroup *
cx_threadGroup_new(void *(*target)(void *),
void *ctx) {
@ -39,3 +53,12 @@ cx_threadGroup_new(void *(*target)(void *),
return self;
}
void
cx_threadGroup_free(CX_ThreadGroup *self) {
if (self) {
cx_thread_free(self->group_manager);
free(self->workers);
}
free(self);
}

View file

@ -17,7 +17,12 @@ nl_new(size_t layer_size, size_t layer_size_next) {
static void
nl_free(Neural_Layer *self) {
free(self->neurons);
if (self) {
for (int i = 0; i < self->layer_size; i++) {
free(self->neurons[i].synapses);
}
free(self->neurons);
}
free(self);
}
@ -51,6 +56,17 @@ neural_new(size_t input_size, size_t output_size, size_t layer_count) {
return self;
}
void
neural_free(Neural_Network *self) {
if (self) {
for (int i = 0; i < self->layer_count; i++) {
nl_free(self->layers[i]);
}
free(self->layers);
}
free(self);
}
void
neural_randomize(Neural_Network *self) {
FILE *f;