X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_async.h;h=7537aae1e839e5a99aa08f445d9b5efbf54aab81;hb=76d234b7dc5e6500e8a54009b367e7620f11ef97;hp=366f448108221c18b0a910f1d8d66a84d31c117d;hpb=5324992ccec2857770963843fcdb6e44ce2c1a37;p=vg.git diff --git a/vg_async.h b/vg_async.h index 366f448..7537aae 100644 --- a/vg_async.h +++ b/vg_async.h @@ -7,7 +7,9 @@ #ifndef VG_ASYNC_H #define VG_ASYNC_H +#define VG_GAME #include "vg/vg.h" +static void vg_assert_thread( enum vg_thread_purpose required ); typedef struct vg_async_item vg_async_item; @@ -30,11 +32,20 @@ struct vg_async{ } static vg_async; +static enum vg_thread_purpose vg_thread_purpose(void); +static enum engine_status _vg_engine_status(void); + /* * Allocate an asynchronous call with a bit of memory */ -VG_STATIC vg_async_item *vg_async_alloc( u32 size ) +static vg_async_item *vg_async_alloc( u32 size ) { + /* ditch out here if engine crashed. this serves as the 'quit checking' */ + if( _vg_engine_status() == k_engine_status_crashed ){ + assert( vg_thread_purpose() == k_thread_purpose_loader ); + longjmp( vg.env_loader_exit, 1 ); + } + SDL_AtomicLock( &vg_async.sl_index ); u32 total_allocation = vg_align8(size) + vg_align8(sizeof(vg_async_item)), @@ -46,7 +57,8 @@ VG_STATIC vg_async_item *vg_async_alloc( u32 size ) vg_error( "Requested: %umb. Buffer size: %umb\n", (total_allocation/1024)/1024, (capacity/1024)/1024 ); - vg_fatal_exit_loop( "async alloc invalid size\n" ); + + vg_fatal_error( "async alloc invalid size\n" ); } if( total_allocation > remaining ){ @@ -66,7 +78,10 @@ VG_STATIC vg_async_item *vg_async_alloc( u32 size ) vg_async_item *entry = block; entry->next = NULL; - entry->payload = ((u8*)block) + vg_align8(sizeof(vg_async_item)); + + if( size ) entry->payload = ((u8*)block) + vg_align8(sizeof(vg_async_item)); + else entry->payload = NULL; + entry->size = size; entry->fn_runner = NULL; @@ -83,21 +98,48 @@ VG_STATIC vg_async_item *vg_async_alloc( u32 size ) return entry; } +/* + * Wait until the current stack of async calls is completely flushed out + */ +static void vg_async_stall(void) +{ + vg_assert_thread(k_thread_purpose_loader); + vg_info( "async_stall: %d\n", SDL_SemValue( vg_async.sem_wait_for_flush ) ); + SDL_SemWait( vg_async.sem_wait_for_flush ); +} + /* * Mark the call as being filled and ready to go */ -VG_STATIC void vg_async_dispatch( vg_async_item *item, +static void vg_async_dispatch( vg_async_item *item, void (*runner)( void *payload, u32 size ) ) { + vg_assert_thread(k_thread_purpose_loader); + if( SDL_SemValue(vg_async.sem_wait_for_flush) ) + SDL_SemWait(vg_async.sem_wait_for_flush); + SDL_AtomicLock( &vg_async.sl_index ); item->fn_runner = runner; SDL_AtomicUnlock( &vg_async.sl_index ); } +/* + * Make a simple async call without allocating extra. + */ +static void vg_async_call( void (*runner)( void *payload, u32 size ), + void *payload, u32 size ) +{ + vg_assert_thread(k_thread_purpose_loader); + vg_async_item *call = vg_async_alloc(0); + call->payload = payload; + call->size = size; + vg_async_dispatch( call, runner ); +} + /* * Run as much of the async buffer as possible */ -VG_STATIC void vg_run_async_checked(void) +static void vg_run_async_checked(void) { SDL_AtomicLock( &vg_async.sl_index ); @@ -119,20 +161,25 @@ VG_STATIC void vg_run_async_checked(void) } } else{ - break; + SDL_AtomicUnlock( &vg_async.sl_index ); + return; } /* TODO: if exceed max frametime.... */ } + if( !SDL_SemValue( vg_async.sem_wait_for_flush ) ){ + SDL_SemPost( vg_async.sem_wait_for_flush ); + } + SDL_AtomicUnlock( &vg_async.sl_index ); } -VG_STATIC void vg_async_init(void) +static void vg_async_init(void) { vg_async.sem_wait_for_flush = SDL_CreateSemaphore(0); vg_async.buffer = vg_create_linear_allocator( NULL, 50*1024*1024, - VG_MEMORY_REALTIME ); + VG_MEMORY_SYSTEM ); } #endif /* VG_ASYNC_H */