build system revision
[vg.git] / vg_async.h
index b3c8a0af09fecd21c28f505c7bdc4d46e05c0426..e0a252806b6dbdf02bf583e10d6cfce151f173ab 100644 (file)
@@ -1,18 +1,15 @@
-/* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved 
+/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved 
  *
  * primateves that you use when you need to run something from another thread 
  * back in the main loop of vg, at the start of each frame
  */
 
-#ifndef VG_ASYNC_H
-#define VG_ASYNC_H
+#pragma once
+#include "vg_engine.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;
-
 struct vg_async_item{
    vg_async_item *next;
 
@@ -22,7 +19,8 @@ struct vg_async_item{
    void (*fn_runner)( void *payload, u32 size );
 };
 
-struct vg_async{
+struct vg_async
+{
    void *buffer;
    
    vg_async_item *start, *end;
@@ -30,157 +28,23 @@ struct vg_async{
    SDL_sem *sem_wait_for_flush;
    SDL_SpinLock sl_index;
 }
-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
- */
-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)),
-       remaining        = vg_linear_remaining( vg_async.buffer ),
-       capacity         = vg_linear_get_capacity( vg_async.buffer );
-
-   if( total_allocation > capacity ){
-      SDL_AtomicUnlock( &vg_async.sl_index );
-      vg_error( "Requested: %umb. Buffer size: %umb\n",
-                  (total_allocation/1024)/1024,
-                  (capacity/1024)/1024 );
-
-      vg_fatal_error( "async alloc invalid size\n" );
-   }
-
-   if( total_allocation > remaining ){
-      SDL_AtomicUnlock( &vg_async.sl_index );
-      SDL_SemWait( vg_async.sem_wait_for_flush );
-      SDL_AtomicLock( &vg_async.sl_index );
+extern vg_async;
 
-      remaining = vg_linear_remaining( vg_async.buffer );
-      capacity = vg_linear_get_capacity( vg_async.buffer );
+/* TODO: Docu */
 
-      assert( remaining == capacity );
-      assert( vg_async.start == NULL );
-      assert( vg_async.end   == NULL );
-   }
-
-   void *block = vg_linear_alloc( vg_async.buffer, total_allocation );
-
-   vg_async_item *entry = block;
-   entry->next = NULL;
-
-   if( size ) entry->payload = ((u8*)block) + vg_align8(sizeof(vg_async_item)); 
-   else entry->payload = NULL;
-
-   entry->size = size;
-   entry->fn_runner = NULL;
-
-   if( vg_async.end ){
-      vg_async.end->next = entry;
-      vg_async.end = entry;
-   }else{
-      vg_async.start = entry;
-      vg_async.end = entry;
-   }
-
-   SDL_AtomicUnlock( &vg_async.sl_index );
-
-   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);
-#if 0
-   vg_info( "async_stall: %d\n", SDL_SemValue( vg_async.sem_wait_for_flush ) );
-#endif
-   SDL_SemWait( vg_async.sem_wait_for_flush );
-}
+void vg_async_call( void (*runner)( void *payload, u32 size ), 
+                    void *payload, u32 size );
+void vg_run_async_checked(void);
+void vg_async_init(void);
 
+vg_async_item *vg_async_alloc( u32 size );
 /*
  * Mark the call as being filled and ready to go
  */
-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 );
-}
+void vg_async_dispatch( vg_async_item *item, 
+                        void (*runner)( void *payload, u32 size ) );
 
 /*
- * Run as much of the async buffer as possible
+ * Wait until the current stack of async calls is completely flushed out 
  */
-static void vg_run_async_checked(void)
-{
-   SDL_AtomicLock( &vg_async.sl_index );
-
-   while( vg_async.start ){
-      vg_async_item *entry = vg_async.start;
-
-      if( entry->fn_runner ){
-         entry->fn_runner( entry->payload, entry->size );
-         vg_async.start = entry->next;
-
-         if( vg_async.start == NULL ){
-            vg_async.end = NULL;
-
-            vg_linear_clear( vg_async.buffer );
-
-            if( !SDL_SemValue( vg_async.sem_wait_for_flush ) ){
-               SDL_SemPost( vg_async.sem_wait_for_flush );
-            }
-         }
-      }
-      else{
-         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 );
-}
-
-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_SYSTEM );
-}
-
-#endif /* VG_ASYNC_H */
+void vg_async_stall(void);