module ecs.std; //import core.stdc.stdlib : malloc, free, realloc; //import core.stdc.string : memcpy; import std.traits; version(WebAssembly) { extern(C) void free(void*) @nogc nothrow @system; extern(C) void* malloc(size_t size) @nogc nothrow @system; extern(C) void* realloc(void*, size_t size) @nogc nothrow @system; extern(C) void* memcpy(return void*, scope const void*, size_t size) @nogc nothrow @system; extern(C) void* memset(void*, int val, size_t size) @nogc nothrow @system; extern(C) void qsort(void* base, size_t num, size_t size, int function(const void*,const void*) compar) @nogc nothrow @system; } else { public import core.stdc.stdlib : malloc, free, realloc; public import core.stdc.string : memcpy, memset; public import core.stdc.stdlib : qsort; } version (Windows) { import core.sys.windows.windows; extern(Windows) void* _aligned_malloc(size_t size,size_t alignment) @nogc nothrow @system; extern(Windows) void _aligned_free(void* ptr) @nogc nothrow @system; version(LDC) { /*extern(Windows) void* __alloca(size_t size) @nogc nothrow @system; alias alloca = __alloca;*/ extern(Windows) void ___chkstk_ms() @nogc nothrow @system; extern(Windows) void __chkstk() { ___chkstk_ms(); } } } else version (Posix) { import core.sys.posix.pthread; import core.sys.posix.stdlib; } version(D_betterC) { private const uint max_alloca = 10000; private char[max_alloca] alloca_array; private uint alloca_pos = 0; void* alloca(size_t length) @nogc nothrow { if(alloca_pos + length > max_alloca)alloca_pos = 0; void* ret = &alloca_array[alloca_pos]; alloca_pos += length; return ret; } } else version(WebAssembly) { private const uint max_alloca = 10000; private char[max_alloca] alloca_array; private uint alloca_pos = 0; void* alloca(size_t length) @nogc nothrow { if(alloca_pos + length > max_alloca)alloca_pos = 0; void* ret = &alloca_array[alloca_pos]; alloca_pos += length; return ret; } } else public import core.stdc.stdlib : alloca; static struct Mallocator { static T[] makeArray(T)(size_t length) nothrow @nogc { T[] ret = (cast(T*)malloc(T.sizeof * length))[0 .. length]; static if(__traits(isPOD, T)) { static immutable T init = T.init; foreach(i;0..ret.length) { memcpy(&ret[i], &init, T.sizeof); } } else { static import std.conv; foreach(i;0..ret.length) { std.conv.emplace(&ret[i]); } } return ret; } static T[] makeArray(T)(size_t length, T initializer) nothrow @nogc { T[] ret = (cast(T*)malloc(T.sizeof * length))[0 .. length]; foreach(ref v; ret)v = initializer; return ret; } static T[] expandArray(T)(T[] array, size_t length) nothrow @nogc { size_t new_length = array.length + length; return (cast(T*)realloc(array.ptr, T.sizeof * new_length))[0 .. new_length]; } static T[] makeArray(T)(T[] array) nothrow @nogc { T[] ret = (cast(T*)malloc(T.sizeof * array.length))[0 .. array.length];//Mallocator.makeArray!(T)(array.length); foreach(i, ref v;ret)v = array[i]; return ret; } static T* make(T, Args...)(Args args) { T* ret = cast(T*)malloc(T.sizeof); static import std.conv; static if(__traits(isPOD, T)) { static immutable T init = T.init; memcpy(ret, &init, T.sizeof); } else static if(is(T == struct))std.conv.emplace(ret, args); return ret; } static void* alignAlloc(size_t length, size_t alignment) nothrow @nogc { void* ret; version(Posix)posix_memalign(&ret, alignment, length);//ret = aligned_alloc(alignment, length); else version(Windows)ret = _aligned_malloc(length, alignment); else version(WebAssembly)ret = malloc(length); else static assert(0, "Unimplemented platform!"); return ret; } static void dispose(T)(T object) nothrow @nogc { static if(__traits(hasMember, T, "__dtor"))object.__dtor(); free(cast(void*)object); } static void alignDispose(T)(T object) { static if(__traits(hasMember, T, "__dtor"))object.__dtor(); version(Posix)free(cast(void*)object); else version(Windows)_aligned_free(cast(void*)object); else version(WebAssembly)free(cast(void*)object); else static assert(0, "Unimplemented platform!"); } } struct Mutex { version (Windows) { void initialize() nothrow @nogc { InitializeCriticalSection(cast(CRITICAL_SECTION*) &m_handle); } void destroy() nothrow @nogc { DeleteCriticalSection(&m_handle); } void lock() nothrow @nogc { EnterCriticalSection(&m_handle); } void unlock() nothrow @nogc { LeaveCriticalSection(&m_handle); } int tryLock() nothrow @nogc { return TryEnterCriticalSection(&m_handle) != 0; } CRITICAL_SECTION m_handle; } else version (Posix) { void initialize() nothrow @nogc { pthread_mutexattr_t attr = void; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(cast(pthread_mutex_t*) &m_handle, &attr); pthread_mutexattr_destroy(&attr); } void destroy() nothrow @nogc { pthread_mutex_destroy(&m_handle); } void lock() nothrow @nogc { pthread_mutex_lock(&m_handle); } void unlock() nothrow @nogc { pthread_mutex_unlock(&m_handle); } int tryLock() nothrow @nogc { return pthread_mutex_trylock(&m_handle) == 0; } private pthread_mutex_t m_handle; } else version(WebAssembly) { void initialize() nothrow @nogc { /*pthread_mutexattr_t attr = void; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(cast(pthread_mutex_t*) &m_handle, &attr); pthread_mutexattr_destroy(&attr);*/ } void destroy() nothrow @nogc { //pthread_mutex_destroy(&m_handle); } void lock() nothrow @nogc { //pthread_mutex_lock(&m_handle); } void unlock() nothrow @nogc { //pthread_mutex_unlock(&m_handle); } int tryLock() nothrow @nogc { return 0;//return pthread_mutex_trylock(&m_handle) == 0; } private int m_handle; } else static assert(0, "unsupported platform!"); }