#include <windows.h>
#include <stdio.h>
typedef struct entA_state
{
char loaded; // 0 = not begun loading, 1 = loading, 2 = loaded, 3 = Added, 200 = Fuckup
void *buffer;
long size;
char *file;
char *filepath;
struct entA_state *next;
} entA_state;
HANDLE entA_mutex;
entA_state *entA_firstState;
DWORD entA_worker(void *unused);
int entA_init()
{
entA_firstState = NULL;
entA_mutex = CreateMutex(NULL, FALSE, NULL);
if(entA_mutex == NULL)
{
return 0;
}
DWORD threadID;
// TODO: Error checking
CreateThread(NULL, 0, entA_worker, NULL, 0, &threadID);
SetThreadPriority(threadID, THREAD_PRIORITY_LOWEST);
return 1;
}
DWORD entA_loadObject(entA_state *state)
{
FILE *file = fopen(state->filepath, "rb");
if(!file)
{
// BAD BAD BAD
WaitForSingleObject(entA_mutex, INFINITE);
state->loaded = 200;
ReleaseMutex(entA_mutex);
return 1;
}
// Get the size of the file
fseek(file, 0, SEEK_END);
state->size = ftell(file);
rewind(file);
// TODO: Error checking
state->buffer = (void *)malloc(state->size);
fread(state->buffer, 1, state->size, file);
fclose(file);
WaitForSingleObject(entA_mutex, INFINITE);
state->loaded = 2; // We are done, hooray!
ReleaseMutex(entA_mutex);
return 1;
}
DWORD entA_worker(void *unused)
{
while(1)
{
WaitForSingleObject(entA_mutex, INFINITE);
entA_state *state = entA_firstState;
while(state)
{
if(state->loaded == 0)
{
state->loaded = 1;
CreateThread(NULL, 0, entA_loadObject, state, 0, NULL);
}
state = state->next;
}
ReleaseMutex(entA_mutex);
}
return 1;
}
entA_state *entA_stateForFile(char *file, char *filepath)
{
entA_state *state = entA_firstState;
while(state)
{
if(strcmp(file, state->file) == 0)
{
return state;
}
state = state->next;
}
state = (entA_state *)malloc(sizeof(entA_state));
if(state)
{
state->file = (char *)malloc((strlen(file) + 1) * sizeof(char));
state->filepath = (char *)malloc((strlen(filepath) + 1) * sizeof(char));
strcpy(state->file, file);
strcpy(state->filepath, filepath);
state->loaded = 0;
state->buffer = NULL;
state->next = NULL;
state->next = entA_firstState;
entA_firstState = state;
}
return state;
}
ENTITY *entA_create(STRING *file, VECTOR *pos, EVENT entAction)
{
STRING *filepath;
ENTITY *ent = NULL;
entA_state *state;
int initiatedLoading = 0;
filepath = str_create(work_dir);
str_cat(filepath, "\\");
str_cat(filepath, file);
WaitForSingleObject(entA_mutex, INFINITE);
state = entA_stateForFile(_chr(file), _chr(filepath));
if(state->loaded == 3)
{
// The file is already cached, so we can safely create the entity right away
ReleaseMutex(entA_mutex);
ptr_remove(filepath);
return ent_create(file, pos, entAction);
}
else if(state->loaded == 0)
{
// We have kicked of the loading, so its our responsibility to add the buffer later on
initiatedLoading = 1;
}
ReleaseMutex(entA_mutex);
int ready = 0;
while(ready == 0)
{
wait(1);
WaitForSingleObject(entA_mutex, INFINITE);
switch(state->loaded)
{
case 2:
{
if(initiatedLoading == 1)
{
add_buffer(state->file, state->buffer, state->size);
state->loaded = 3;
ready = 1;
}
}
break;
case 3:
{
ready = 1;
}
break;
case 200:
{
printf("Could not load file \"%s\"", state->file);
ReleaseMutex(entA_mutex);
ptr_remove(filepath);
return NULL;
}
break;
default:
break;
}
ReleaseMutex(entA_mutex);
}
ent = ent_create(file, pos, entAction);
ptr_remove(filepath);
return ent;
}