132 lines
5.8 KiB
D
132 lines
5.8 KiB
D
/************************************************************************************************************************
|
|
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.
|
|
|
|
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
|
|
License: BSD 3-clause, see LICENSE file in project root folder.
|
|
*/
|
|
module bubel.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;
|
|
}
|