From 6a600d22c812a879b5991329067cb2f7c42debfd Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 27 Apr 2023 23:08:27 +0200 Subject: [PATCH 1/6] Refactored fullName template New fullName implementation gives same result as fullyQualifiedName for normal types and templated ones, and still works in BetterC --- source/bubel/ecs/traits.d | 37 +++++++++++-------------------------- tests/basic.d | 16 ++++++++++++++++ tests/bugs.d | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/source/bubel/ecs/traits.d b/source/bubel/ecs/traits.d index 79901db..e18f656 100644 --- a/source/bubel/ecs/traits.d +++ b/source/bubel/ecs/traits.d @@ -63,34 +63,19 @@ static long getIndexOfTypeInEntitiesData(EntitiesData, Type)() return index; } -static string attachParentName(alias T, string str)() +template fullName(alias T : X!A, alias X, A...) { - alias parent = __traits(parent, T); - enum parent_str = parent.stringof; - static if(parent_str[0..7] == "module ") - { - static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str[7 .. $] ~ '.' ~ str); - } - else return parent_str[7 .. $] ~ '.' ~ str; - } - else static if(parent_str[0..8] == "package ") - { - static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str[8 .. $] ~ '.' ~ str); - } - else return parent_str[8 .. $] ~ '.' ~ str; - } - else static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str ~ '.' ~ str); - } - else return parent_str ~ '.' ~ str; + alias parent = __traits(parent, X); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, X) ~ "!(" ~ fullName!A ~ ")"; } -static string fullName(T)() +template fullName(alias T) { - return attachParentName!(T, T.stringof); + static if(__traits(compiles, __traits(parent, T))) + { + alias parent = __traits(parent, T); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, T); + } + else static if(__traits(compiles, __traits(identifier, T)))enum fullName = __traits(identifier, T); + else enum fullName = T.stringof; } \ No newline at end of file diff --git a/tests/basic.d b/tests/basic.d index ea54382..e353549 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -160,6 +160,22 @@ void afterEveryTest() gEntityManager.destroy(); } +@("RegisteredNames") +unittest +{ + import bubel.ecs.traits; + + gEntityManager.beginRegister(); + gEntityManager.registerSystem!EmptySystem(0); + gEntityManager.registerSystem!EntityCounterSystem(0); + gEntityManager.endRegister(); + + System* empty_system = gEntityManager.getSystem(becsID!EmptySystem); + System* counter_system = gEntityManager.getSystem(becsID!EntityCounterSystem); + assert(empty_system.name == "tests.basic.EmptySystem", fullName!EmptySystem); + assert(counter_system.name == "tests.basic.EntityCounterSystem", fullName!EntityCounterSystem); +} + @("EntityMeta") unittest { diff --git a/tests/bugs.d b/tests/bugs.d index 10a3c62..9b59973 100644 --- a/tests/bugs.d +++ b/tests/bugs.d @@ -172,4 +172,35 @@ unittest gEntityManager.commit(); gEntityManager.destroy(); -} \ No newline at end of file +} + +@("3-template-system-compilation-file") +unittest +{ + struct TemplateSystem(T) + { + struct EntitiesData + { + uint length; + } + + uint a; + uint b; + } + + struct TempalteComponent(T) + { + T parameter; + } + + gEntityManager.initialize(0); + + gEntityManager.beginRegister(); + + gEntityManager.registerComponent!CInt; + gEntityManager.registerComponent!(TempalteComponent!uint); + gEntityManager.registerSystem!(TemplateSystem!CInt)(0); + + gEntityManager.endRegister(); + +} From 1a5452d6cc5ac0261b21b70fd45722d142ac06c4 Mon Sep 17 00:00:00 2001 From: Mergul Date: Wed, 24 May 2023 22:15:05 +0200 Subject: [PATCH 2/6] Improve fullName template fullName now support multi-pararmeter templates --- source/bubel/ecs/manager.d | 14 ++++++++++---- source/bubel/ecs/traits.d | 11 +++++++++++ tests/bugs.d | 24 ++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d index d6fae94..26db180 100644 --- a/source/bubel/ecs/manager.d +++ b/source/bubel/ecs/manager.d @@ -386,6 +386,7 @@ export struct EntityManager else assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); + // enum SystemName = __traits(fullyQualifiedName,Sys); // enum SystemName = fullyQualifiedName!Sys; enum SystemName = fullName!Sys; //enum SystemName = Sys.stringof; @@ -427,7 +428,8 @@ export struct EntityManager { alias EventParamType = Params[1]; enum EventName = fullName!(Unqual!(EventParamType)); - // enum EventName = fullyQualifiedName!(Unqual!(EventParamType));//.stringof; + // enum EventName = __traits(fullyQualifiedName,Unqual!(EventParamType)); + // enum EventName = fullyQualifiedName!(Unqual!(EventParamType)); ushort evt = events_map.get(cast(char[]) EventName, ushort.max); assert(evt != ushort.max, "Can't register system \"" ~ SystemName @@ -489,8 +491,10 @@ export struct EntityManager string name; static if (isArray!MemberType) { // Workaround. This code is never called with: not an array type, but compiler prints an error - // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));//.stringof; - name = fullName!(Unqual!(typeof(MemberType.init[0]))); + // name = __traits(fullyQualifiedName,Unqual!(ForeachType!MemberType)); + // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType)); + // name = fullName!(Unqual!(typeof(MemberType.init[0]))); + name = fullName!(Unqual!(Unqual!(ForeachType!MemberType))); } bool is_optional; @@ -715,8 +719,9 @@ export struct EntityManager string name; static if (isArray!MemberType) { // Workaround. This code is never called with: not an array type, but compiler prints an error + // name = __traits(fullyQualifiedName,Unqual!(ForeachType!MemberType)); // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType)); - name = fullName!(Unqual!(typeof(MemberType.init[0]))); + name = fullName!(Unqual!(ForeachType!MemberType)); //name = Unqual!(ForeachType!MemberType).stringof; } @@ -1296,6 +1301,7 @@ export struct EntityManager { ComponentInfo info; + // enum ComponentName = __traits(fullyQualifiedName,Comp); // enum ComponentName = fullyQualifiedName!Comp; enum ComponentName = fullName!Comp; // enum ComponentName = Comp.stringof; diff --git a/source/bubel/ecs/traits.d b/source/bubel/ecs/traits.d index e18f656..24bc698 100644 --- a/source/bubel/ecs/traits.d +++ b/source/bubel/ecs/traits.d @@ -69,6 +69,17 @@ template fullName(alias T : X!A, alias X, A...) enum fullName = fullName!parent ~ '.' ~ __traits(identifier, X) ~ "!(" ~ fullName!A ~ ")"; } +template fullName(T...) +{ + static if(__traits(compiles, __traits(parent, T[0]))) + { + alias parent = __traits(parent, T[0]); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, T[0]) ~ ", " ~ fullName!(T[1 .. $]); + } + else static if(__traits(compiles, __traits(identifier, T[0])))enum fullName = __traits(identifier, T[0]) ~ ", " ~ fullName!(T[1 .. $]); + else enum fullName = T[0].stringof ~ ", " ~ fullName!(T[1 .. $]); +} + template fullName(alias T) { static if(__traits(compiles, __traits(parent, T))) diff --git a/tests/bugs.d b/tests/bugs.d index 9b59973..5eaa8aa 100644 --- a/tests/bugs.d +++ b/tests/bugs.d @@ -177,6 +177,7 @@ unittest @("3-template-system-compilation-file") unittest { + struct TemplateSystem(T) { struct EntitiesData @@ -184,14 +185,31 @@ unittest uint length; } - uint a; - uint b; + T a; + } + + struct TemplateSystem2(T, T2, T3) + { + struct EntitiesData + { + uint length; + } + + T a; + T2 b; + T3 c; } struct TempalteComponent(T) { T parameter; } + + struct TempalteComponent2(T, T2) + { + T parameter; + T2 parameter2; + } gEntityManager.initialize(0); @@ -199,7 +217,9 @@ unittest gEntityManager.registerComponent!CInt; gEntityManager.registerComponent!(TempalteComponent!uint); + gEntityManager.registerComponent!(TempalteComponent2!(float,int)); gEntityManager.registerSystem!(TemplateSystem!CInt)(0); + gEntityManager.registerSystem!(TemplateSystem2!(CInt, uint, float))(0); gEntityManager.endRegister(); From 9b757720395f9b081ba66c4cb966fa9b763aff2d Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 10 Apr 2025 13:59:21 +0200 Subject: [PATCH 3/6] Add missing export visibility attributes --- source/bubel/ecs/entity.d | 12 ++++++------ source/bubel/ecs/hash_map.d | 2 +- source/bubel/ecs/manager.d | 10 ++++++++++ source/bubel/ecs/system.d | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/source/bubel/ecs/entity.d b/source/bubel/ecs/entity.d index 9b42c31..76a8a2f 100644 --- a/source/bubel/ecs/entity.d +++ b/source/bubel/ecs/entity.d @@ -44,7 +44,7 @@ struct Entity return cast(T*)getComponent(becsID!T); } - void* getComponent(ushort component_id) const + export void* getComponent(ushort component_id) const { EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; @@ -54,7 +54,7 @@ struct Entity return (cast(void*)block + info.deltas[component_id] + block.entityIndex(&this) * gEntityManager.components[component_id].size); } - bool hasComponent(ushort component_id) const + export bool hasComponent(ushort component_id) const { EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; @@ -62,7 +62,7 @@ struct Entity return true; } - EntityMeta getMeta() const + export EntityMeta getMeta() const { EntityMeta meta; meta.block = gEntityManager.getMetaData(&this); @@ -85,7 +85,7 @@ struct EntityMeta return cast(T*)getComponent(becsID!T); } - void* getComponent(ushort component_id) const + export void* getComponent(ushort component_id) const { const (EntityManager.EntityInfo)* info = block.type_info; @@ -95,7 +95,7 @@ struct EntityMeta return (cast(void*)block + info.deltas[component_id] + index * gEntityManager.components[component_id].size); } - bool hasComponent(ushort component_id) const + export bool hasComponent(ushort component_id) const { const EntityManager.EntityInfo* info = block.type_info; if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false; @@ -133,7 +133,7 @@ export struct EntityTemplate /************************************************************************************************************************ Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime. */ - void* getComponent(ushort component_id) const nothrow @nogc + export void* getComponent(ushort component_id) const nothrow @nogc { if(component_id >= info.tmpl_deltas.length || info.tmpl_deltas[component_id] == ushort.max)return null; return cast(void*)(entity_data.ptr + info.tmpl_deltas[component_id]); diff --git a/source/bubel/ecs/hash_map.d b/source/bubel/ecs/hash_map.d index 66a0756..7ba6137 100755 --- a/source/bubel/ecs/hash_map.d +++ b/source/bubel/ecs/hash_map.d @@ -28,7 +28,7 @@ export ulong defaultHashFunc(T)(auto ref T t) nothrow @nogc } } -ulong hash(byte[] array) nothrow @nogc +export ulong hash(byte[] array) nothrow @nogc { ulong hash = 0; diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d index d6fae94..0977786 100644 --- a/source/bubel/ecs/manager.d +++ b/source/bubel/ecs/manager.d @@ -3355,6 +3355,16 @@ export struct EntityManager export ~this() nothrow @nogc { } + + export void opAssign(ComponentInfo c) + { + size = c.size; + alignment = c.alignment; + init_data = c.init_data; + destroy_callback = c.destroy_callback; + create_callback = c.create_callback; + } + ///Component size ushort size; ///Component data alignment diff --git a/source/bubel/ecs/system.d b/source/bubel/ecs/system.d index 24098c0..e6defd9 100644 --- a/source/bubel/ecs/system.d +++ b/source/bubel/ecs/system.d @@ -108,7 +108,7 @@ struct System package: ///destory system. Dispose all data - void destroy() nothrow @nogc + export void destroy() nothrow @nogc { import bubel.ecs.std : Mallocator; From 76a23aa4edffec3db1f233b95a6a52b13567b87f Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 10 Apr 2025 14:00:20 +0200 Subject: [PATCH 4/6] Fix typo --- source/bubel/ecs/system.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/bubel/ecs/system.d b/source/bubel/ecs/system.d index e6defd9..310b53a 100644 --- a/source/bubel/ecs/system.d +++ b/source/bubel/ecs/system.d @@ -13,14 +13,14 @@ import bubel.ecs.manager; System contain data required to proper glue EntityManager with Systems. System callbacks: $(LIST - * void onUpdate(EntitesData); + * void onUpdate(EntitiesData); * void onEnable() - called inside system.enable() function * void onDisable() - called inside system.disable() function * bool onBegin() - called inside manager.begin() * void onEnd() - called inside manager.end() * void onCreate() - called after registration inside registerSystem function * void onDestroy() - called during re-registration and inside manager destructor - * void onAddEntity(EntitesData) - called for every entity which are assigned to system (by adding new entity or changing its components) + * void onAddEntity(EntitiesData) - called for every entity which are assigned to system (by adding new entity or changing its components) * void onRemoveEntity(EntitiesData) - called for every entity removed from system update process * void onChangeEntity(EntitiesData) - called for every entity which components are changed but it was previously assigned to system * void handleEvent(Entity*, Event) - called for every event supported by system From d77317c8163faa6e95f357542f2b771ca32df15a Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 10 Apr 2025 14:00:55 +0200 Subject: [PATCH 5/6] Make it possible to use custom runtime (such as numem) --- source/bubel/ecs/manager.d | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d index 0977786..b5220f4 100644 --- a/source/bubel/ecs/manager.d +++ b/source/bubel/ecs/manager.d @@ -27,6 +27,8 @@ alias SerializeVector = bubel.ecs.vector.Vector!ubyte; ///Global EntityManager used for everything. export __gshared EntityManager* gEntityManager = null; +version(D_BetterC) version = NoDRuntime; + /************************************************************************************************************************ Entity manager is responsible for everything. @@ -359,7 +361,7 @@ export struct EntityManager void registerSystem(Sys)(int priority, const(char)[] pass_name) { ushort pass = passes_map.get(pass_name, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(pass != ushort.max, "Update pass doesn't exist."); else assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist."); @@ -381,7 +383,7 @@ export struct EntityManager assert(register_state, "registerSystem must be called between beginRegister() and endRegister()."); - version (D_BetterC) + version (NoDRuntime) assert(pass < passes.length, "Update pass doesn't exist."); else assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); @@ -390,7 +392,7 @@ export struct EntityManager enum SystemName = fullName!Sys; //enum SystemName = Sys.stringof; - System system; + System system = System(); system.m_pass = pass; // static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) @@ -840,7 +842,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.req) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -852,7 +854,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.excluded) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -864,7 +866,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.optional) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -876,7 +878,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.readonly) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -888,7 +890,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.mutable) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -1198,7 +1200,7 @@ export struct EntityManager { ushort comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing dependency."); @@ -1211,7 +1213,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.writableDeps) { ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max); - version (D_BetterC) + version (NoDRuntime) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing dependency."); From f19bce1a57775c0eb995c8603e5ffec97d6634e8 Mon Sep 17 00:00:00 2001 From: Mergul Date: Wed, 14 May 2025 13:26:10 +0200 Subject: [PATCH 6/6] Remove ECSEmscripten as Emscripten version is now supported in LDC (+fix compile scripts) --- compile_wasm.py | 4 +- demos/compile_wasm.py | 10 ++-- meson.build | 2 +- source/bubel/ecs/atomic.d | 121 +------------------------------------- source/bubel/ecs/std.d | 18 ++---- 5 files changed, 15 insertions(+), 140 deletions(-) diff --git a/compile_wasm.py b/compile_wasm.py index 3bd1afd..7214801 100644 --- a/compile_wasm.py +++ b/compile_wasm.py @@ -13,7 +13,7 @@ def compile(sources, output): if file_extension == '.d' and filename != 'package': files.append(os.path.join(r, file)) - ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' + ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' for path in sources: ldc_cmd += '-I' + path + ' ' @@ -33,7 +33,7 @@ def compile(sources, output): shared_flags = '' clean = 0 emc_flags = '' -ldc_flags = '--d-version=ECSEmscripten ' +ldc_flags = '' import_paths = ['source','tests'] build_tests = 0 diff --git a/demos/compile_wasm.py b/demos/compile_wasm.py index 06d31ac..b178260 100644 --- a/demos/compile_wasm.py +++ b/demos/compile_wasm.py @@ -1,7 +1,6 @@ import os import ntpath import sys -import imp def compile(sources, output): files = [] @@ -14,7 +13,7 @@ def compile(sources, output): if file_extension == '.d' and filename != 'package': files.append(os.path.join(r, file)) - ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' + ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' for path in sources: ldc_cmd += '-I' + path + ' ' @@ -41,7 +40,7 @@ only_bc = 0 multi = 0 sources = ['tests', 'source'] emc_flags = '-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="[\'png\']" ' -ldc_flags = '--d-version=ECSEmscripten --d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS ' +ldc_flags = '--d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS ' import_paths = ['external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source'] for arg in sys.argv[1:]: @@ -121,8 +120,9 @@ emcc_cmd += 'demo.bc ' os.system("mkdir build") -emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten') -pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' +# emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten') +# pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' +pack_cmd = os.path.expandvars('$EMSDK/upstream/emscripten') + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' print('Packafing files: ' + pack_cmd) os.system(pack_cmd) diff --git a/meson.build b/meson.build index 3f261f8..141cb25 100644 --- a/meson.build +++ b/meson.build @@ -58,7 +58,7 @@ threads_dep = dependency('threads') d_versions = [] deps = [] if host_machine.cpu_family() == 'wasm32' - d_versions += 'ECSEmscripten' + else # meson incorectly adds "-s USE_PTHREADS=1" to ldc2 invocation whe pthreads is added as dependency # add it for non wasm builds diff --git a/source/bubel/ecs/atomic.d b/source/bubel/ecs/atomic.d index 40f0aa9..d8995ae 100644 --- a/source/bubel/ecs/atomic.d +++ b/source/bubel/ecs/atomic.d @@ -9,124 +9,5 @@ License: BSD 3-clause, see LICENSE file in project root folder. */ module bubel.ecs.atomic; -version (Emscripten) version = ECSEmscripten; +public import core.atomic; -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; -} diff --git a/source/bubel/ecs/std.d b/source/bubel/ecs/std.d index 8eb0d48..8a3e207 100644 --- a/source/bubel/ecs/std.d +++ b/source/bubel/ecs/std.d @@ -7,11 +7,9 @@ License: BSD 3-clause, see LICENSE file in project root folder. */ module bubel.ecs.std; -version (Emscripten) version = ECSEmscripten; - import std.traits; -version (ECSEmscripten) +version (Emscripten) { extern (C) struct pthread_mutex_t { @@ -29,10 +27,6 @@ version (ECSEmscripten) extern (C) int memcmp(const void* s1, const void* s2, size_t size); extern (C) void exit(int status) nothrow @nogc; - extern (C) void __assert(const(char)* msg, const(char)* file, uint line) - { - exit(-20); - } extern (C) void free(void*) @nogc nothrow @system; extern (C) void* malloc(size_t size) @nogc nothrow @system; @@ -60,7 +54,7 @@ else public import core.stdc.stdlib : qsort; } -version (ECSEmscripten) +version (Emscripten) { } else version (Windows) @@ -89,7 +83,7 @@ else version (Posix) import core.sys.posix.stdlib : posix_memalign; } -version (ECSEmscripten) +version (Emscripten) { private const uint max_alloca = 10000; private __gshared byte[max_alloca] alloca_array; @@ -294,7 +288,7 @@ static struct Mallocator posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length); else version (Windows) ret = _aligned_malloc(length, alignment); - else version (ECSEmscripten) + else version (Emscripten) posix_memalign(&ret, alignment, length); //malloc(length); else static assert(0, "Unimplemented platform!"); @@ -341,7 +335,7 @@ static struct Mallocator free(cast(void*) object); else version (Windows) _aligned_free(cast(void*) object); - else version (ECSEmscripten) + else version (Emscripten) free(cast(void*) object); else static assert(0, "Unimplemented platform!"); @@ -351,7 +345,7 @@ static struct Mallocator struct Mutex { - version (ECSEmscripten) + version (Emscripten) { void initialize() nothrow @nogc {