/************************************************************************************************************************ *It's internal code. Can be used for atomics if emscripten backend will be used. * *This module contain atomic operations which include support for emscripten atomics functions. *Emscripten functions are contained in API similar to druntime. */ module ecs.atomic; version(Emscripten)version = ECSEmscripten; version(ECSEmscripten) { import std.traits; enum MemoryOrder { acq, acq_rel, raw, rel, seq } extern(C) ubyte emscripten_atomic_cas_u8(void *addr, ubyte oldVal, ubyte newVal) @nogc nothrow pure; extern(C) ushort emscripten_atomic_cas_u16(void *addr, ushort oldVal, ushort newVal) @nogc nothrow pure; extern(C) uint emscripten_atomic_cas_u32(void *addr, uint oldVal, uint newVal) @nogc nothrow pure; extern(C) ubyte emscripten_atomic_load_u8(const void *addr) @nogc nothrow pure; extern(C) ushort emscripten_atomic_load_u16(const void *addr) @nogc nothrow pure; extern(C) uint emscripten_atomic_load_u32(const void *addr) @nogc nothrow pure; extern(C) ubyte emscripten_atomic_store_u8(void *addr, ubyte val) @nogc nothrow pure; extern(C) ushort emscripten_atomic_store_u16(void *addr, ushort val) @nogc nothrow pure; extern(C) uint emscripten_atomic_store_u32(void *addr, uint val) @nogc nothrow pure; extern(C) ubyte emscripten_atomic_add_u8(void *addr, ubyte val) @nogc nothrow pure; extern(C) ushort emscripten_atomic_add_u16(void *addr, ushort val) @nogc nothrow pure; extern(C) uint emscripten_atomic_add_u32(void *addr, uint val) @nogc nothrow pure; extern(C) ubyte emscripten_atomic_sub_u8(void *addr, ubyte val) @nogc nothrow pure; extern(C) ushort emscripten_atomic_sub_u16(void *addr, ushort val) @nogc nothrow pure; extern(C) uint emscripten_atomic_sub_u32(void *addr, uint val) @nogc nothrow pure; public pure nothrow @nogc Unqual!T atomicOp(string op, T, V1)(ref shared T val, V1 mod) { static if(op == "+=") { static if(is(T == byte) || is(T == ubyte))return cast(Unqual!T)(emscripten_atomic_add_u8(cast(void*)&val, cast(Unqual!T)mod) + 1); else static if(is(T == short) || is(T == ushort))return cast(Unqual!T)(emscripten_atomic_add_u16(cast(void*)&val, cast(Unqual!T)mod) + 1); else static if(is(T == int) || is(T == uint))return cast(Unqual!T)(emscripten_atomic_add_u32(cast(void*)&val, cast(Unqual!T)mod) + 1); else static assert(0); } else static if(op == "-=") { static if(is(T == byte) || is(T == ubyte))return cast(Unqual!T)(emscripten_atomic_sub_u8(cast(void*)&val, cast(Unqual!T)mod) - 1); else static if(is(T == short) || is(T == ushort))return cast(Unqual!T)(emscripten_atomic_sub_u16(cast(void*)&val, cast(Unqual!T)mod) - 1); else static if(is(T == int) || is(T == uint))return cast(Unqual!T)(emscripten_atomic_sub_u32(cast(void*)&val, cast(Unqual!T)mod) - 1); else static assert(0); } } public pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval) { alias UT = Unqual!T; static if(is(UT == bool) || is(UT == byte) || is(UT == ubyte))emscripten_atomic_store_u8(cast(void*)&val, cast(UT)newval); else static if(is(UT == short) || is(UT == ushort))emscripten_atomic_store_u16(cast(void*)&val, cast(UT)newval); else static if(is(UT == int) || is(UT == uint))emscripten_atomic_store_u32(cast(void*)&val, cast(UT)newval); else static assert(0); } public pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref const T val) { alias UT = Unqual!T; static if(is(UT == bool))return emscripten_atomic_load_u8(cast(const void*)&val) != 0; else static if(is(UT == byte) || is(UT == ubyte))return emscripten_atomic_load_u8(cast(const void*)&val); else static if(is(UT == short) || is(UT == ushort))return emscripten_atomic_load_u16(cast(const void*)&val); else static if(is(UT == int) || is(UT == uint))return emscripten_atomic_load_u32(cast(const void*)&val); else static assert(0); } public pure nothrow @nogc @trusted bool cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis) { alias UT = Unqual!T; static if(is(UT == bool))return emscripten_atomic_cas_u8(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis; else static if(is(UT == byte) || is(UT == ubyte))return emscripten_atomic_cas_u8(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis; else static if(is(UT == short) || is(UT == ushort))return emscripten_atomic_cas_u16(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis; else static if(is(UT == int) || is(UT == uint))return emscripten_atomic_cas_u32(cast(void*)here, cast(Unqual!T)ifThis, cast(Unqual!T)writeThis) == ifThis; else static assert(0); } } else { public import core.atomic; }