-// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
+#ifndef VG_PLATFORM_H
+#define VG_PLATFORM_H
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-typedef int8_t i8;
-typedef int16_t i16;
-typedef int32_t i32;
-typedef int64_t i64;
+#include "vg.h"
+#include "vg_stdint.h"
+
+/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
typedef unsigned int uint;
typedef v2f m2x2f[2];
typedef v3f m3x3f[3];
typedef v3f m4x3f[4];
+typedef v4f m4x4f[4];
typedef v3f boxf[2];
// Resource types
const char *name;
};
-#define vg_static_assert _Static_assert
+#ifndef VG_STATIC
+#define VG_STATIC static
+#endif
+#define vg_static_assert _Static_assert
#define vg_list_size( A ) (sizeof(A)/sizeof(A[0]))
+#define VG_MUST_USE_RESULT __attribute__((warn_unused_result))
-// THREADING
-// ==================================================================================================================
-
-// Pthred emulation for windows
-#ifdef _WIN32
+#ifdef _WIN32_NO
#include <windows.h>
- #define MUTEX_TYPE HANDLE
- #define MUTEX_INITIALIZER NULL
- #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
- #define MUTEX_CLEANUP(x) (CloseHandle(x)) //TODO: Why is this defined but never used?
- #define MUTEX_LOCK(x) emulate_pthread_mutex_lock(&(x))
- #define MUTEX_UNLOCK(x) (ReleaseMutex(x))
-
- int emulate_pthread_mutex_lock( volatile MUTEX_TYPE *mx )
- {
- if( *mx == NULL ) /* static initializer? */
- {
- HANDLE p = CreateMutex( NULL, FALSE, NULL );
- if( InterlockedCompareExchangePointer( (PVOID*)mx, (PVOID)p, NULL ) != NULL )
- CloseHandle(p);
- }
-
- return WaitForSingleObject( *mx, INFINITE ) == WAIT_FAILED;
- }
+
+#ifdef I_THINK_THIS_IS_WHAT_MSCV_WANTS_BUT_HAVNT_TESTED_IT_YET
+
+ #define VG_DEPRECATED __declspec(deprecated)
+ #define VG_THREAD_LOCAL __declspec( thread )
+
+#else /* MINGW-64 */
+
+ #define VG_THREAD_LOCAL __thread
+ #define VG_DEPRECATED __attribute__((deprecated))
+
+#endif
+
+ typedef HANDLE vg_semaphore;
+ typedef HANDLE vg_mutex;
+ typedef u64 vg_timespec;
+
#else
#include <pthread.h>
- #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
- #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
- #define MUTEX_TYPE pthread_mutex_t
- #define MUTEX_INITIALIZER {0}
+ #include <semaphore.h>
+
+ #define VG_DEPRECATED __attribute__((deprecated))
+ #define VG_THREAD_LOCAL __thread
+
+ typedef sem_t vg_semaphore;
+ typedef pthread_mutex_t vg_mutex;
+ typedef struct timespec vg_timespec;
+
#endif
+VG_STATIC void vg_strncpy( const char *src, char *dst, u32 len )
+{
+ for( u32 i=0; i<len; i++ )
+ {
+ dst[i] = src[i];
+
+ if( !src[i] )
+ break;
+ }
+}
-int vg_thread_run( void *pfunc, void *data )
+VG_STATIC void vg_fatal_exit_loop( const char *error );
+VG_STATIC void vg_required( void *ptr, const char *path )
+{
+ if( !ptr )
+ {
+ vg_fatal_exit_loop( path );
+ }
+}
+
+#define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \
+ TYPE DECL = FN( PATH,##__VA_ARGS__ ); \
+ vg_required( DECL, "Resource is required but failed to load: '" PATH "'" );
+
+#if 0
+VG_DEPRECATED
+char *strcpy(char* destination, const char* source);
+VG_DEPRECATED
+char *strncpy(char *restrict dest, const char *restrict src, size_t n);
+VG_DEPRECATED
+char *strcat(char *restrict dest, const char *restrict src);
+VG_DEPRECATED
+char *strncat(char *restrict dest, const char *restrict src, size_t n);
+#endif
+
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <math.h>
+#include <assert.h>
+
+VG_STATIC int vg_thread_run( void *pfunc, void *data );
+VG_STATIC void vg_thread_exit(void);
+VG_STATIC void vg_set_thread_name( const char *name );
+VG_STATIC int vg_semaphore_init( vg_semaphore *sem, u32 value );
+VG_STATIC int vg_semaphore_trywait( vg_semaphore *sem );
+VG_STATIC int vg_semaphore_wait( vg_semaphore *sem );
+VG_STATIC int vg_semaphore_post( vg_semaphore *sem );
+VG_STATIC void vg_semaphore_free( vg_semaphore *sem );
+VG_STATIC int vg_mutex_init( vg_mutex *mutex );
+VG_STATIC int vg_mutex_lock( vg_mutex *mutex );
+VG_STATIC int vg_mutex_unlock( vg_mutex *mutex );
+VG_STATIC void vg_mutex_free( vg_mutex *mutex );
+VG_STATIC void vg_sleep_ms( long msec );
+VG_STATIC double vg_time_diff( vg_timespec start, vg_timespec end );
+
+#ifdef _WIN32_NO
+
+VG_STATIC int vg_thread_run( void *pfunc, void *data )
{
-#ifdef _WIN32
-
HANDLE hThread = CreateThread
(
- NULL, // Thread attributes
- 0, // Stack size (0 = use default)
- pfunc, // Thread start address
- data, // Parameter to pass to the thread
- 0, // Creation flags
- NULL // Thread id
+ NULL, /* Thread attributes */
+ 0, /* Stack size (0 = use default) */
+ pfunc, /* Thread start address */
+ data, /* Parameter to pass to the thread */
+ 0, /* Creation flags */
+ NULL /* Thread id */
);
if ( hThread == NULL )
{
- // Thread creation failed.
- // More details can be retrieved by calling GetLastError()
+ /*
+ * Thread creation failed.
+ * More details can be retrieved by calling GetLastError()
+ */
return 1;
}
else
CloseHandle( hThread );
return 0;
}
-
+}
+
+VG_STATIC void vg_thread_exit(void)
+{
+ ExitThread(0);
+}
+
+VG_STATIC void vg_set_thread_name( const char *name )
+{
+ /* I believe this is a meaningless concept in windows */
+}
+
+VG_STATIC int vg_semaphore_init( vg_semaphore *sem, u32 value );
+VG_STATIC int vg_semaphore_trywait( vg_semaphore *sem );
+VG_STATIC int vg_semaphore_wait( vg_semaphore *sem );
+VG_STATIC int vg_semaphore_post( vg_semaphore *sem );
+VG_STATIC void vg_semaphore_free( vg_semaphore *sem );
+VG_STATIC int vg_mutex_init( vg_mutex *mutex );
+VG_STATIC int vg_mutex_lock( vg_mutex *mutex );
+VG_STATIC int vg_mutex_unlock( vg_mutex *mutex );
+VG_STATIC void vg_mutex_free( vg_mutex *mutex );
+VG_STATIC void vg_sleep_ms( long msec );
+VG_STATIC double vg_time_diff( vg_timespec start, vg_timespec end );
+
#else
+VG_STATIC int vg_thread_run( void *pfunc, void *data )
+{
pthread_t hThread;
if( pthread_create( &hThread, NULL, pfunc, data ) )
{
pthread_detach( hThread );
return 0;
}
+}
+
+VG_STATIC void vg_thread_exit(void)
+{
+ pthread_exit(NULL);
+}
+
+VG_STATIC void vg_set_thread_name( const char *name )
+{
+ /* not defined but links?? */
+#if 0
+ pthread_setname_np(pthread_self());
#endif
}
+
+VG_STATIC int vg_semaphore_init( vg_semaphore *sem, u32 value )
+{
+ return !sem_init( sem, 0, value );
+}
+
+VG_STATIC int vg_semaphore_trywait( vg_semaphore *sem )
+{
+ return !sem_trywait( sem );
+}
+
+VG_STATIC int vg_semaphore_wait( vg_semaphore *sem )
+{
+ return !sem_wait( sem );
+}
+
+VG_STATIC int vg_semaphore_post( vg_semaphore *sem )
+{
+ return !sem_post( sem );
+}
+
+VG_STATIC void vg_semaphore_free( vg_semaphore *sem )
+{
+ sem_destroy( sem );
+}
+
+VG_STATIC int vg_mutex_init( vg_mutex *mutex )
+{
+ memset( mutex, 0, sizeof(vg_mutex) );
+ return 1;
+}
+
+VG_STATIC int vg_mutex_lock( vg_mutex *mutex )
+{
+ if( !pthread_mutex_lock( mutex ) )
+ return 1;
+ else
+ return 0;
+}
+
+VG_STATIC int vg_mutex_unlock( vg_mutex *mutex )
+{
+ if( !pthread_mutex_unlock( mutex ) )
+ return 1;
+ else
+ return 0;
+}
+
+VG_STATIC void vg_mutex_free( vg_mutex *mutex )
+{
+
+}
+
+VG_STATIC void vg_sleep_ms( long msec )
+{
+ struct timespec ts;
+
+ ts.tv_sec = msec / 1000;
+ ts.tv_nsec = (msec % 1000) * 1000000;
+ nanosleep( &ts, &ts );
+}
+
+/* diff two timespecs in MS */
+VG_STATIC double vg_time_diff( struct timespec start, struct timespec end )
+{
+ double elapsed = 1000.0*end.tv_sec + 1e-6*end.tv_nsec
+ - (1000.0*start.tv_sec + 1e-6*start.tv_nsec);
+
+ return elapsed;
+}
+
+#endif
+
+#define VG_MIN( A, B ) ((A)<(B)?(A):(B))
+#define VG_MAX( A, B ) ((A)>(B)?(A):(B))
+
+#endif