Ahh, no one needs a dll and taking money for something this trivial brings bad karma (imo)

Here you go, a working version. It calls add_buffer() on the mainthread, so no need to fear anything. Just save it into a file and include it. Done.
Code:
#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;
}



There are some error checkings left and I there is no way to purge the files (well they can be purged, but not recreated). Its trivial to add these things, so I let you do this. Here is a small test scrip which uses the models from the shadertest folder:
Code:
#include <acknex.h>
#include "async.c"

ENTITY *stone, *marine;

action rotate()
{
	while(1)
	{
		my.pan += 12 * time_step;
		my.tilt += 9 * time_step;
		
		wait(1);
	}
}

void main()
{
	level_load(NULL);
	wait(1);
	
	entA_init(); // DON'T forget!
	
	
	stone = entA_create("stones.mdl", vector(1024, 0, 0), NULL);
	marine = entA_create("marine.mdl", vector(1024, 0, 0), rotate);
	
	int i;
	for(i=0; i<10; i++)
		entA_create("box.mdl", vector(1024, -290 + (i * 120), -35), NULL);
}



Last edited by JustSid; 05/20/11 12:19.

Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com