Flecs v3.2
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
os_api.h
Go to the documentation of this file.
1
13#ifndef FLECS_OS_API_H
14#define FLECS_OS_API_H
15
24#include <stdarg.h>
25#include <errno.h>
26#include <stdio.h>
27
28#if defined(ECS_TARGET_WINDOWS)
29#include <malloc.h>
30#elif defined(ECS_TARGET_FREEBSD)
31#include <stdlib.h>
32#else
33#include <alloca.h>
34#endif
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40typedef struct ecs_time_t {
41 uint32_t sec;
42 uint32_t nanosec;
44
45/* Allocation counters */
46extern int64_t ecs_os_api_malloc_count;
47extern int64_t ecs_os_api_realloc_count;
48extern int64_t ecs_os_api_calloc_count;
49extern int64_t ecs_os_api_free_count;
50
51/* Use handle types that _at least_ can store pointers */
52typedef uintptr_t ecs_os_thread_t;
53typedef uintptr_t ecs_os_cond_t;
54typedef uintptr_t ecs_os_mutex_t;
55typedef uintptr_t ecs_os_dl_t;
56typedef uintptr_t ecs_os_sock_t;
57
58/* 64 bit thread id */
59typedef uint64_t ecs_os_thread_id_t;
60
61/* Generic function pointer type */
62typedef void (*ecs_os_proc_t)(void);
63
64/* OS API init */
65typedef
66void (*ecs_os_api_init_t)(void);
67
68/* OS API deinit */
69typedef
70void (*ecs_os_api_fini_t)(void);
71
72/* Memory management */
73typedef
74void* (*ecs_os_api_malloc_t)(
75 ecs_size_t size);
76
77typedef
78void (*ecs_os_api_free_t)(
79 void *ptr);
80
81typedef
82void* (*ecs_os_api_realloc_t)(
83 void *ptr,
84 ecs_size_t size);
85
86typedef
87void* (*ecs_os_api_calloc_t)(
88 ecs_size_t size);
89
90typedef
91char* (*ecs_os_api_strdup_t)(
92 const char *str);
93
94/* Threads */
95typedef
96void* (*ecs_os_thread_callback_t)(
97 void*);
98
99typedef
100ecs_os_thread_t (*ecs_os_api_thread_new_t)(
101 ecs_os_thread_callback_t callback,
102 void *param);
103
104typedef
105void* (*ecs_os_api_thread_join_t)(
106 ecs_os_thread_t thread);
107
108typedef
109ecs_os_thread_id_t (*ecs_os_api_thread_self_t)(void);
110
111/* Tasks */
112typedef
113ecs_os_thread_t (*ecs_os_api_task_new_t)(
114 ecs_os_thread_callback_t callback,
115 void *param);
116
117typedef
118void* (*ecs_os_api_task_join_t)(
119 ecs_os_thread_t thread);
120
121/* Atomic increment / decrement */
122typedef
123int32_t (*ecs_os_api_ainc_t)(
124 int32_t *value);
125
126typedef
127int64_t (*ecs_os_api_lainc_t)(
128 int64_t *value);
129
130/* Mutex */
131typedef
132ecs_os_mutex_t (*ecs_os_api_mutex_new_t)(
133 void);
134
135typedef
136void (*ecs_os_api_mutex_lock_t)(
137 ecs_os_mutex_t mutex);
138
139typedef
140void (*ecs_os_api_mutex_unlock_t)(
141 ecs_os_mutex_t mutex);
142
143typedef
144void (*ecs_os_api_mutex_free_t)(
145 ecs_os_mutex_t mutex);
146
147/* Condition variable */
148typedef
149ecs_os_cond_t (*ecs_os_api_cond_new_t)(
150 void);
151
152typedef
153void (*ecs_os_api_cond_free_t)(
154 ecs_os_cond_t cond);
155
156typedef
157void (*ecs_os_api_cond_signal_t)(
158 ecs_os_cond_t cond);
159
160typedef
161void (*ecs_os_api_cond_broadcast_t)(
162 ecs_os_cond_t cond);
163
164typedef
165void (*ecs_os_api_cond_wait_t)(
166 ecs_os_cond_t cond,
167 ecs_os_mutex_t mutex);
168
169typedef
170void (*ecs_os_api_sleep_t)(
171 int32_t sec,
172 int32_t nanosec);
173
174typedef
175void (*ecs_os_api_enable_high_timer_resolution_t)(
176 bool enable);
177
178typedef
179void (*ecs_os_api_get_time_t)(
180 ecs_time_t *time_out);
181
182typedef
183uint64_t (*ecs_os_api_now_t)(void);
184
185/* Logging */
186typedef
187void (*ecs_os_api_log_t)(
188 int32_t level, /* Logging level */
189 const char *file, /* File where message was logged */
190 int32_t line, /* Line it was logged */
191 const char *msg);
192
193/* Application termination */
194typedef
195void (*ecs_os_api_abort_t)(
196 void);
197
198/* Dynamic libraries */
199typedef
200ecs_os_dl_t (*ecs_os_api_dlopen_t)(
201 const char *libname);
202
203typedef
204ecs_os_proc_t (*ecs_os_api_dlproc_t)(
205 ecs_os_dl_t lib,
206 const char *procname);
207
208typedef
209void (*ecs_os_api_dlclose_t)(
210 ecs_os_dl_t lib);
211
212typedef
213char* (*ecs_os_api_module_to_path_t)(
214 const char *module_id);
215
216/* Prefix members of struct with 'ecs_' as some system headers may define
217 * macros for functions like "strdup", "log" or "_free" */
218
219typedef struct ecs_os_api_t {
220 /* API init / deinit */
221 ecs_os_api_init_t init_;
222 ecs_os_api_fini_t fini_;
223
224 /* Memory management */
225 ecs_os_api_malloc_t malloc_;
226 ecs_os_api_realloc_t realloc_;
227 ecs_os_api_calloc_t calloc_;
228 ecs_os_api_free_t free_;
229
230 /* Strings */
231 ecs_os_api_strdup_t strdup_;
232
233 /* Threads */
234 ecs_os_api_thread_new_t thread_new_;
235 ecs_os_api_thread_join_t thread_join_;
236 ecs_os_api_thread_self_t thread_self_;
237
238 /* Tasks */
239 ecs_os_api_thread_new_t task_new_;
240 ecs_os_api_thread_join_t task_join_;
241
242 /* Atomic increment / decrement */
243 ecs_os_api_ainc_t ainc_;
244 ecs_os_api_ainc_t adec_;
245 ecs_os_api_lainc_t lainc_;
246 ecs_os_api_lainc_t ladec_;
247
248 /* Mutex */
249 ecs_os_api_mutex_new_t mutex_new_;
250 ecs_os_api_mutex_free_t mutex_free_;
251 ecs_os_api_mutex_lock_t mutex_lock_;
252 ecs_os_api_mutex_lock_t mutex_unlock_;
253
254 /* Condition variable */
255 ecs_os_api_cond_new_t cond_new_;
256 ecs_os_api_cond_free_t cond_free_;
257 ecs_os_api_cond_signal_t cond_signal_;
258 ecs_os_api_cond_broadcast_t cond_broadcast_;
259 ecs_os_api_cond_wait_t cond_wait_;
260
261 /* Time */
262 ecs_os_api_sleep_t sleep_;
263 ecs_os_api_now_t now_;
264 ecs_os_api_get_time_t get_time_;
265
266 /* Logging */
267 ecs_os_api_log_t log_; /* Logging function. The level should be interpreted as: */
268 /* >0: Debug tracing. Only enabled in debug builds. */
269 /* 0: Tracing. Enabled in debug/release builds. */
270 /* -2: Warning. An issue occurred, but operation was successful. */
271 /* -3: Error. An issue occurred, and operation was unsuccessful. */
272 /* -4: Fatal. An issue occurred, and application must quit. */
273
274 /* Application termination */
275 ecs_os_api_abort_t abort_;
276
277 /* Dynamic library loading */
278 ecs_os_api_dlopen_t dlopen_;
279 ecs_os_api_dlproc_t dlproc_;
280 ecs_os_api_dlclose_t dlclose_;
281
282 /* Overridable function that translates from a logical module id to a
283 * shared library filename */
284 ecs_os_api_module_to_path_t module_to_dl_;
285
286 /* Overridable function that translates from a logical module id to a
287 * path that contains module-specif resources or assets */
288 ecs_os_api_module_to_path_t module_to_etc_;
289
290 /* Trace level */
291 int32_t log_level_;
292
293 /* Trace indentation */
294 int32_t log_indent_;
295
296 /* Last error code */
297 int32_t log_last_error_;
298
299 /* Last recorded timestamp */
300 int64_t log_last_timestamp_;
301
302 /* OS API flags */
303 ecs_flags32_t flags_;
304
305 /* File used for logging output (hint, log_ decides where to write) */
306 FILE *log_out_;
308
309FLECS_API
310extern ecs_os_api_t ecs_os_api;
311
312FLECS_API
313void ecs_os_init(void);
314
315FLECS_API
316void ecs_os_fini(void);
317
318FLECS_API
319void ecs_os_set_api(
320 ecs_os_api_t *os_api);
321
322FLECS_API
323ecs_os_api_t ecs_os_get_api(void);
324
325FLECS_API
326void ecs_os_set_api_defaults(void);
327
328/* Memory management */
329#ifndef ecs_os_malloc
330#define ecs_os_malloc(size) ecs_os_api.malloc_(size)
331#endif
332#ifndef ecs_os_free
333#define ecs_os_free(ptr) ecs_os_api.free_(ptr)
334#endif
335#ifndef ecs_os_realloc
336#define ecs_os_realloc(ptr, size) ecs_os_api.realloc_(ptr, size)
337#endif
338#ifndef ecs_os_calloc
339#define ecs_os_calloc(size) ecs_os_api.calloc_(size)
340#endif
341#if defined(ECS_TARGET_WINDOWS)
342#define ecs_os_alloca(size) _alloca((size_t)(size))
343#else
344#define ecs_os_alloca(size) alloca((size_t)(size))
345#endif
346
347#define ecs_os_malloc_t(T) ECS_CAST(T*, ecs_os_malloc(ECS_SIZEOF(T)))
348#define ecs_os_malloc_n(T, count) ECS_CAST(T*, ecs_os_malloc(ECS_SIZEOF(T) * (count)))
349#define ecs_os_calloc_t(T) ECS_CAST(T*, ecs_os_calloc(ECS_SIZEOF(T)))
350#define ecs_os_calloc_n(T, count) ECS_CAST(T*, ecs_os_calloc(ECS_SIZEOF(T) * (count)))
351
352#define ecs_os_realloc_t(ptr, T) ECS_CAST(T*, ecs_os_realloc(ptr, ECS_SIZEOF(T)))
353#define ecs_os_realloc_n(ptr, T, count) ECS_CAST(T*, ecs_os_realloc(ptr, ECS_SIZEOF(T) * (count)))
354#define ecs_os_alloca_t(T) ECS_CAST(T*, ecs_os_alloca(ECS_SIZEOF(T)))
355#define ecs_os_alloca_n(T, count) ECS_CAST(T*, ecs_os_alloca(ECS_SIZEOF(T) * (count)))
356
357/* Strings */
358#ifndef ecs_os_strdup
359#define ecs_os_strdup(str) ecs_os_api.strdup_(str)
360#endif
361
362#ifdef __cplusplus
363#define ecs_os_strlen(str) static_cast<ecs_size_t>(strlen(str))
364#define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, static_cast<size_t>(num))
365#define ecs_os_memcmp(ptr1, ptr2, num) memcmp(ptr1, ptr2, static_cast<size_t>(num))
366#define ecs_os_memcpy(ptr1, ptr2, num) memcpy(ptr1, ptr2, static_cast<size_t>(num))
367#define ecs_os_memset(ptr, value, num) memset(ptr, value, static_cast<size_t>(num))
368#define ecs_os_memmove(dst, src, size) memmove(dst, src, static_cast<size_t>(size))
369#else
370#define ecs_os_strlen(str) (ecs_size_t)strlen(str)
371#define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, (size_t)(num))
372#define ecs_os_memcmp(ptr1, ptr2, num) memcmp(ptr1, ptr2, (size_t)(num))
373#define ecs_os_memcpy(ptr1, ptr2, num) memcpy(ptr1, ptr2, (size_t)(num))
374#define ecs_os_memset(ptr, value, num) memset(ptr, value, (size_t)(num))
375#define ecs_os_memmove(dst, src, size) memmove(dst, src, (size_t)(size))
376#endif
377
378#define ecs_os_memcpy_t(ptr1, ptr2, T) ecs_os_memcpy(ptr1, ptr2, ECS_SIZEOF(T))
379#define ecs_os_memcpy_n(ptr1, ptr2, T, count) ecs_os_memcpy(ptr1, ptr2, ECS_SIZEOF(T) * count)
380#define ecs_os_memcmp_t(ptr1, ptr2, T) ecs_os_memcmp(ptr1, ptr2, ECS_SIZEOF(T))
381
382#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))
383#define ecs_os_memmove_n(ptr1, ptr2, T, count) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T) * count)
384#define ecs_os_memmove_t(ptr1, ptr2, T) ecs_os_memmove(ptr1, ptr2, ECS_SIZEOF(T))
385
386#define ecs_os_strcmp(str1, str2) strcmp(str1, str2)
387#define ecs_os_memset_t(ptr, value, T) ecs_os_memset(ptr, value, ECS_SIZEOF(T))
388#define ecs_os_memset_n(ptr, value, T, count) ecs_os_memset(ptr, value, ECS_SIZEOF(T) * count)
389#define ecs_os_zeromem(ptr) ecs_os_memset(ptr, 0, ECS_SIZEOF(*ptr))
390
391#define ecs_os_memdup_t(ptr, T) ecs_os_memdup(ptr, ECS_SIZEOF(T))
392#define ecs_os_memdup_n(ptr, T, count) ecs_os_memdup(ptr, ECS_SIZEOF(T) * count)
393
394#define ecs_offset(ptr, T, index)\
395 ECS_CAST(T*, ECS_OFFSET(ptr, ECS_SIZEOF(T) * index))
396
397#if !defined(ECS_TARGET_POSIX) && !defined(ECS_TARGET_MINGW)
398#define ecs_os_strcat(str1, str2) strcat_s(str1, INT_MAX, str2)
399#define ecs_os_sprintf(ptr, ...) sprintf_s(ptr, INT_MAX, __VA_ARGS__)
400#define ecs_os_snprintf(ptr, len, ...) sprintf_s(ptr, len, __VA_ARGS__)
401#define ecs_os_vsprintf(ptr, fmt, args) vsprintf_s(ptr, INT_MAX, fmt, args)
402#define ecs_os_strcpy(str1, str2) strcpy_s(str1, INT_MAX, str2)
403#ifdef __cplusplus
404#define ecs_os_strncpy(str1, str2, num) strncpy_s(str1, INT_MAX, str2, static_cast<size_t>(num))
405#else
406#define ecs_os_strncpy(str1, str2, num) strncpy_s(str1, INT_MAX, str2, (size_t)(num))
407#endif
408#else
409#define ecs_os_strcat(str1, str2) strcat(str1, str2)
410#define ecs_os_sprintf(ptr, ...) sprintf(ptr, __VA_ARGS__)
411#define ecs_os_snprintf(ptr, len, ...) snprintf(ptr, len, __VA_ARGS__)
412#define ecs_os_vsprintf(ptr, fmt, args) vsprintf(ptr, fmt, args)
413#define ecs_os_strcpy(str1, str2) strcpy(str1, str2)
414#ifdef __cplusplus
415#define ecs_os_strncpy(str1, str2, num) strncpy(str1, str2, static_cast<size_t>(num))
416#else
417#define ecs_os_strncpy(str1, str2, num) strncpy(str1, str2, (size_t)(num))
418#endif
419#endif
420
421/* Files */
422#ifndef ECS_TARGET_POSIX
423#define ecs_os_fopen(result, file, mode) fopen_s(result, file, mode)
424#else
425#define ecs_os_fopen(result, file, mode) (*(result)) = fopen(file, mode)
426#endif
427
428/* Threads */
429#define ecs_os_thread_new(callback, param) ecs_os_api.thread_new_(callback, param)
430#define ecs_os_thread_join(thread) ecs_os_api.thread_join_(thread)
431#define ecs_os_thread_self() ecs_os_api.thread_self_()
432
433/* Tasks */
434#define ecs_os_task_new(callback, param) ecs_os_api.task_new_(callback, param)
435#define ecs_os_task_join(thread) ecs_os_api.task_join_(thread)
436
437/* Atomic increment / decrement */
438#define ecs_os_ainc(value) ecs_os_api.ainc_(value)
439#define ecs_os_adec(value) ecs_os_api.adec_(value)
440#define ecs_os_lainc(value) ecs_os_api.lainc_(value)
441#define ecs_os_ladec(value) ecs_os_api.ladec_(value)
442
443/* Mutex */
444#define ecs_os_mutex_new() ecs_os_api.mutex_new_()
445#define ecs_os_mutex_free(mutex) ecs_os_api.mutex_free_(mutex)
446#define ecs_os_mutex_lock(mutex) ecs_os_api.mutex_lock_(mutex)
447#define ecs_os_mutex_unlock(mutex) ecs_os_api.mutex_unlock_(mutex)
448
449/* Condition variable */
450#define ecs_os_cond_new() ecs_os_api.cond_new_()
451#define ecs_os_cond_free(cond) ecs_os_api.cond_free_(cond)
452#define ecs_os_cond_signal(cond) ecs_os_api.cond_signal_(cond)
453#define ecs_os_cond_broadcast(cond) ecs_os_api.cond_broadcast_(cond)
454#define ecs_os_cond_wait(cond, mutex) ecs_os_api.cond_wait_(cond, mutex)
455
456/* Time */
457#define ecs_os_sleep(sec, nanosec) ecs_os_api.sleep_(sec, nanosec)
458#define ecs_os_now() ecs_os_api.now_()
459#define ecs_os_get_time(time_out) ecs_os_api.get_time_(time_out)
460
461/* Logging */
462FLECS_API
463void ecs_os_dbg(const char *file, int32_t line, const char *msg);
464
465FLECS_API
466void ecs_os_trace(const char *file, int32_t line, const char *msg);
467
468FLECS_API
469void ecs_os_warn(const char *file, int32_t line, const char *msg);
470
471FLECS_API
472void ecs_os_err(const char *file, int32_t line, const char *msg);
473
474FLECS_API
475void ecs_os_fatal(const char *file, int32_t line, const char *msg);
476
477FLECS_API
478const char* ecs_os_strerror(int err);
479
480FLECS_API
481void ecs_os_strset(char **str, const char *value);
482
483#ifdef FLECS_ACCURATE_COUNTERS
484#define ecs_os_inc(v) (ecs_os_ainc(v))
485#define ecs_os_linc(v) (ecs_os_lainc(v))
486#define ecs_os_dec(v) (ecs_os_adec(v))
487#define ecs_os_ldec(v) (ecs_os_ladec(v))
488#else
489#define ecs_os_inc(v) (++(*v))
490#define ecs_os_linc(v) (++(*v))
491#define ecs_os_dec(v) (--(*v))
492#define ecs_os_ldec(v) (--(*v))
493#endif
494
495#ifdef ECS_TARGET_MINGW
496/* mingw bug: without this a conversion error is thrown, but isnan/isinf should
497 * accept float, double and long double. */
498#define ecs_os_isnan(val) (isnan((float)val))
499#define ecs_os_isinf(val) (isinf((float)val))
500#else
501#define ecs_os_isnan(val) (isnan(val))
502#define ecs_os_isinf(val) (isinf(val))
503#endif
504
505/* Application termination */
506#define ecs_os_abort() ecs_os_api.abort_()
507
508/* Dynamic libraries */
509#define ecs_os_dlopen(libname) ecs_os_api.dlopen_(libname)
510#define ecs_os_dlproc(lib, procname) ecs_os_api.dlproc_(lib, procname)
511#define ecs_os_dlclose(lib) ecs_os_api.dlclose_(lib)
512
513/* Module id translation */
514#define ecs_os_module_to_dl(lib) ecs_os_api.module_to_dl_(lib)
515#define ecs_os_module_to_etc(lib) ecs_os_api.module_to_etc_(lib)
516
517/* Sleep with floating point time */
518FLECS_API
519void ecs_sleepf(
520 double t);
521
522/* Measure time since provided timestamp */
523FLECS_API
524double ecs_time_measure(
525 ecs_time_t *start);
526
527/* Calculate difference between two timestamps */
528FLECS_API
529ecs_time_t ecs_time_sub(
530 ecs_time_t t1,
531 ecs_time_t t2);
532
533/* Convert time value to a double */
534FLECS_API
535double ecs_time_to_double(
536 ecs_time_t t);
537
538FLECS_API
539void* ecs_os_memdup(
540 const void *src,
541 ecs_size_t size);
542
544FLECS_API
546
548FLECS_API
550
552FLECS_API
554
556FLECS_API
558
560FLECS_API
562
564FLECS_API
565bool ecs_os_has_dl(void);
566
568FLECS_API
570
571#ifdef __cplusplus
572}
573#endif
574
577#endif
FLECS_API bool ecs_os_has_time(void)
Are time functions available?
FLECS_API bool ecs_os_has_dl(void)
Are dynamic library functions available?
FLECS_API bool ecs_os_has_logging(void)
Are logging functions available?
FLECS_API bool ecs_os_has_modules(void)
Are module path functions available?
FLECS_API bool ecs_os_has_task_support(void)
Are task functions available?
FLECS_API bool ecs_os_has_threading(void)
Are threading functions available?
FLECS_API bool ecs_os_has_heap(void)
Are heap functions available?