Platform and OS stability stuff
[vg.git] / src / vg / vg_platform.h
1 #ifndef VG_PLATFORM_H
2 #define VG_PLATFORM_H
3
4 #include "vg.h"
5 #include "vg_stdint.h"
6
7 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
8
9 typedef unsigned int uint;
10
11 typedef int v2i[2];
12 typedef int v3i[3];
13 typedef int v4i[4];
14 typedef float v2f[2];
15 typedef float v3f[3];
16 typedef float v4f[4];
17 typedef v2f m2x2f[2];
18 typedef v3f m3x3f[3];
19 typedef v3f m4x3f[4];
20 typedef v4f m4x4f[4];
21 typedef v3f boxf[2];
22
23 // Resource types
24 typedef struct vg_tex2d vg_tex2d;
25
26 struct vg_achievement
27 {
28 int is_set;
29 const char *name;
30 };
31
32 #define vg_static_assert _Static_assert
33 #define vg_list_size( A ) (sizeof(A)/sizeof(A[0]))
34 #define VG_MUST_USE_RESULT __attribute__((warn_unused_result))
35
36 #ifdef _WIN32_NO
37 #include <windows.h>
38
39 #ifdef I_THINK_THIS_IS_WHAT_MSCV_WANTS_BUT_HAVNT_TESTED_IT_YET
40
41 #define VG_DEPRECATED __declspec(deprecated)
42 #define VG_THREAD_LOCAL __declspec( thread )
43
44 #else /* MINGW-64 */
45
46 #define VG_THREAD_LOCAL __thread
47 #define VG_DEPRECATED __attribute__((deprecated))
48
49 #endif
50
51 typedef HANDLE vg_semaphore;
52 typedef HANDLE vg_mutex;
53 typedef u64 vg_timespec;
54
55 #else
56 #include <pthread.h>
57 #include <semaphore.h>
58
59 #define VG_DEPRECATED __attribute__((deprecated))
60 #define VG_THREAD_LOCAL __thread
61
62 typedef sem_t vg_semaphore;
63 typedef pthread_mutex_t vg_mutex;
64 typedef struct timespec vg_timespec;
65
66 #endif
67
68 #include <stdlib.h>
69
70 static void vg_fatal_exit_loop( const char *error );
71 static void *vg_alloc( size_t size )
72 {
73 void *ptr = malloc( size );
74
75 if( !ptr )
76 vg_fatal_exit_loop( "Out of memory" );
77
78 return ptr;
79 }
80
81 static void *vg_realloc( void *orig, size_t size )
82 {
83 void *ptr = realloc( orig, size );
84
85 if( !ptr )
86 vg_fatal_exit_loop( "Out of memory" );
87
88 return ptr;
89 }
90
91 /* seems to be a GCC bug when inlining this, its low priority anyway */
92 __attribute__ ((noinline))
93 static void vg_free( void *ptr )
94 {
95 free( ptr );
96 }
97
98 static void vg_required( void *ptr, const char *path )
99 {
100 if( !ptr )
101 {
102 vg_fatal_exit_loop( path );
103 }
104 }
105
106 #define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \
107 TYPE DECL = FN( PATH,##__VA_ARGS__ ); \
108 vg_required( DECL, "Resource is required but failed to load: '" PATH "'" );
109
110 VG_DEPRECATED
111 void *malloc( size_t size );
112
113 VG_DEPRECATED
114 void *realloc( void *orig, size_t size );
115
116 VG_DEPRECATED
117 void free( void *ptr );
118
119 #include <stdio.h>
120 #include <dirent.h>
121 #include <string.h>
122 #include <stdarg.h>
123 #include <ctype.h>
124 #include <math.h>
125 #include <assert.h>
126
127 static int vg_thread_run( void *pfunc, void *data );
128 static void vg_thread_exit(void);
129 static void vg_set_thread_name( const char *name );
130 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
131 static int vg_semaphore_trywait( vg_semaphore *sem );
132 static int vg_semaphore_wait( vg_semaphore *sem );
133 static int vg_semaphore_post( vg_semaphore *sem );
134 static void vg_semaphore_free( vg_semaphore *sem );
135 static int vg_mutex_init( vg_mutex *mutex );
136 static int vg_mutex_lock( vg_mutex *mutex );
137 static int vg_mutex_unlock( vg_mutex *mutex );
138 static void vg_mutex_free( vg_mutex *mutex );
139 static void vg_sleep_ms( long msec );
140 static double vg_time_diff( vg_timespec start, vg_timespec end );
141
142 #ifdef _WIN32_NO
143
144 static int vg_thread_run( void *pfunc, void *data )
145 {
146 HANDLE hThread = CreateThread
147 (
148 NULL, /* Thread attributes */
149 0, /* Stack size (0 = use default) */
150 pfunc, /* Thread start address */
151 data, /* Parameter to pass to the thread */
152 0, /* Creation flags */
153 NULL /* Thread id */
154 );
155
156 if ( hThread == NULL )
157 {
158 /*
159 * Thread creation failed.
160 * More details can be retrieved by calling GetLastError()
161 */
162 return 1;
163 }
164 else
165 {
166 CloseHandle( hThread );
167 return 0;
168 }
169 }
170
171 static void vg_thread_exit(void)
172 {
173 ExitThread(0);
174 }
175
176 static void vg_set_thread_name( const char *name )
177 {
178 /* I believe this is a meaningless concept in windows */
179 }
180
181 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
182 static int vg_semaphore_trywait( vg_semaphore *sem );
183 static int vg_semaphore_wait( vg_semaphore *sem );
184 static int vg_semaphore_post( vg_semaphore *sem );
185 static void vg_semaphore_free( vg_semaphore *sem );
186 static int vg_mutex_init( vg_mutex *mutex );
187 static int vg_mutex_lock( vg_mutex *mutex );
188 static int vg_mutex_unlock( vg_mutex *mutex );
189 static void vg_mutex_free( vg_mutex *mutex );
190 static void vg_sleep_ms( long msec );
191 static double vg_time_diff( vg_timespec start, vg_timespec end );
192
193 #else
194
195 static int vg_thread_run( void *pfunc, void *data )
196 {
197 pthread_t hThread;
198 if( pthread_create( &hThread, NULL, pfunc, data ) )
199 {
200 return 1;
201 }
202 else
203 {
204 pthread_detach( hThread );
205 return 0;
206 }
207 }
208
209
210 static void vg_thread_exit(void)
211 {
212 pthread_exit(NULL);
213 }
214
215 static void vg_set_thread_name( const char *name )
216 {
217 /* not defined but links?? */
218 #if 0
219 pthread_setname_np(pthread_self());
220 #endif
221 }
222
223 static int vg_semaphore_init( vg_semaphore *sem, u32 value )
224 {
225 return !sem_init( sem, 0, value );
226 }
227
228 static int vg_semaphore_trywait( vg_semaphore *sem )
229 {
230 return !sem_trywait( sem );
231 }
232
233 static int vg_semaphore_wait( vg_semaphore *sem )
234 {
235 return !sem_wait( sem );
236 }
237
238 static int vg_semaphore_post( vg_semaphore *sem )
239 {
240 return !sem_post( sem );
241 }
242
243 static void vg_semaphore_free( vg_semaphore *sem )
244 {
245 sem_destroy( sem );
246 }
247
248 static int vg_mutex_init( vg_mutex *mutex )
249 {
250 memset( mutex, 0, sizeof(vg_mutex) );
251 return 1;
252 }
253
254 static int vg_mutex_lock( vg_mutex *mutex )
255 {
256 if( !pthread_mutex_lock( mutex ) )
257 return 1;
258 else
259 return 0;
260 }
261
262 static int vg_mutex_unlock( vg_mutex *mutex )
263 {
264 if( !pthread_mutex_unlock( mutex ) )
265 return 1;
266 else
267 return 0;
268 }
269
270 static void vg_mutex_free( vg_mutex *mutex )
271 {
272
273 }
274
275 static void vg_sleep_ms( long msec )
276 {
277 struct timespec ts;
278
279 ts.tv_sec = msec / 1000;
280 ts.tv_nsec = (msec % 1000) * 1000000;
281 nanosleep( &ts, &ts );
282 }
283
284 /* diff two timespecs in MS */
285 static double vg_time_diff( struct timespec start, struct timespec end )
286 {
287 double elapsed = 1000.0*end.tv_sec + 1e-6*end.tv_nsec
288 - (1000.0*start.tv_sec + 1e-6*start.tv_nsec);
289
290 return elapsed;
291 }
292
293 #endif
294
295 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
296 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
297
298 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
299 size_t emsize )
300 {
301 if( count+amount > *cap )
302 {
303 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
304 return vg_realloc( buffer, (*cap) * emsize );
305 }
306
307 return buffer;
308 }
309
310 static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize )
311 {
312 *cap = count;
313 return vg_realloc( buffer, (*cap) * emsize );
314 }
315
316 #endif