-changes in EntityAlocator

* renamed to BlockAllocator
 * now it's template with compile time assingable block_size and block_in_allocation variables
-WIP Event management
 * probably working sendSelfEvent()
 * registerEvent()
-added win_dll.d as Windows DLL require functionality
This commit is contained in:
Mergul 2018-09-19 17:50:05 +02:00
parent d0fcdba6cd
commit 4ad81fe116
6 changed files with 264 additions and 57 deletions

View file

@ -15,7 +15,10 @@
{ {
"name" : "tests", "name" : "tests",
"sourcePaths" : ["source\/","tests\/"], "sourcePaths" : ["source\/","tests\/"],
"targetType" : "executable" "targetType" : "executable",
"excludedSourceFiles":[
"source\/win_dll.d"
]
}, },
{ {
"name" : "dynlib", "name" : "dynlib",

View file

@ -1,11 +1,11 @@
module ecs.entity_allocator; module ecs.block_allocator;
import ecs.manager; import ecs.manager;
import std.experimental.allocator; import std.experimental.allocator;
import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator; import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
struct EntityAllocator struct BlockAllocator(uint block_size, uint blocks_in_allocation)
{ {
void* next_block; void* next_block;
@ -18,17 +18,23 @@ struct EntityAllocator
return ret; return ret;
} }
void freeBlock(void* block)
{
*cast(void**)block = next_block;
next_block = block;
}
private void allocBlock() private void allocBlock()
{ {
next_block = cast(void*) AlignedMallocator.instance.alignedAllocate( next_block = cast(void*) AlignedMallocator.instance.alignedAllocate(
EntityManager.page_size * EntityManager.pages_in_block, EntityManager.page_size); block_size * blocks_in_allocation, block_size);
foreach (i; 0 .. EntityManager.pages_in_block - 1) foreach (i; 0 .. blocks_in_allocation - 1)
{ {
void** pointer = cast(void**)(next_block + i * EntityManager.page_size); void** pointer = cast(void**)(next_block + i * block_size);
*pointer = next_block + (i + 1) * EntityManager.page_size; *pointer = next_block + (i + 1) * block_size;
} }
void** pointer = cast(void**)( void** pointer = cast(void**)(
next_block + (EntityManager.pages_in_block - 1) * EntityManager.page_size); next_block + (blocks_in_allocation - 1) * block_size);
*pointer = null; *pointer = null;
} }
} }

View file

@ -1,11 +1,125 @@
module ecs.events; module ecs.events;
import ecs.manager;
import ecs.block_allocator;
import ecs.entity;
import std.algorithm.comparison : max;
/*
struct Event struct Event
{ {
uint type; uint type;
} }*/
class EventManager mixin template EventManagerCode()
{ {
//@disable this();
this(EntityManager m)
{
manager = m;
}
void sendSelfEvent(Ev)(EntityID id, Ev event)
{
ushort size = cast(ushort)(Ev.sizeof); // + EntityID.sizeof + ushort.sizeof);
ushort alignment = cast(ushort)(Ev.alignof);
EventList* list = &process_events;
if (list.current_block is null)
{
list.current_block = cast(EventBlock*) allocator.getBlock();
list.first_block = list.current_block;
list.current_block.index = cast(ushort)((void*).sizeof + ushort.sizeof);
}
ushort index = cast(ushort)(
list.current_block.index + ushort.sizeof + EntityID.sizeof + ushort.sizeof);
ushort aligned_index = index; //cast(ushort)(list.current_block.index);
alignNum(aligned_index, alignment);
if (aligned_index + Ev.sizeof > events_block_size)
{
list.current_block.next = cast(EventBlock*) allocator.getBlock();
list.current_block = list.current_block.next;
list.current_block.index = cast(ushort)((void*).sizeof + ushort.sizeof);
index = cast(ushort)((void*)
.sizeof + ushort.sizeof + ushort.sizeof + EntityID.sizeof + ushort.sizeof); // + EntityID.sizeof + ushort.sizeof;
aligned_index = index;
alignNum(aligned_index, alignment);
/*if(alignment > EntityID.sizeof + uint.sizeof)aligned_index = alignment;
else aligned_index = uint.sizeof * 4;*/
}
EventBlock* block = list.current_block;
ushort align_ = cast(ushort)(aligned_index - index);
*cast(ushort*)&block.data[block.index] = align_;
index = cast(ushort)(aligned_index - (EntityID.sizeof + ushort.sizeof));
*cast(ushort*)&block.data[index] = Ev.event_id;
*cast(EntityID*)&block.data[index + 2] = id;
*cast(Ev*)&block.data[aligned_index] = event;
block.index = cast(ushort)(aligned_index + Ev.sizeof);
}
void clearEvents()
{
EventList tmp = current_events;
current_events = process_events;
process_events = tmp;
EventBlock* block = process_events.first_block;
/*if(block)
{
import std.stdio;
writeln(block.data);
}*/
while (block)
{
EventBlock* free = block;
block = block.next;
allocator.freeBlock(free);
}
process_events.first_block = null;
process_events.current_block = null;
}
///Single page size. Must be power of two.
enum events_block_size = 1 << 12;
///Number of pages in block.
enum events_blocks_in_allocation = 128;
struct EventBlock
{
union
{
struct
{
EventBlock* next;
ushort index = 2;
}
ubyte[events_block_size] data;
}
}
struct EventList
{
EventBlock* first_block;
EventBlock* current_block;
}
EventList current_events;
EventList process_events;
BlockAllocator!(events_block_size, events_blocks_in_allocation) allocator;
EntityManager manager;
} }

View file

@ -10,11 +10,12 @@ import core.stdc.stdlib;
import core.stdc.string; import core.stdc.string;
import ecs.entity; import ecs.entity;
import ecs.entity_allocator; import ecs.block_allocator;
import ecs.hash_map; import ecs.hash_map;
import ecs.id_manager; import ecs.id_manager;
import ecs.system; import ecs.system;
import ecs.vector; import ecs.vector;
import ecs.events;
alias gEM = EntityManager.instance; alias gEM = EntityManager.instance;
alias SerializeVector = ecs.vector.Vector!ubyte; alias SerializeVector = ecs.vector.Vector!ubyte;
@ -24,11 +25,14 @@ class EntityManager
export static void initialize() export static void initialize()
{ {
if (instance is null)
instance = Mallocator.instance.make!EntityManager; instance = Mallocator.instance.make!EntityManager;
} }
export static void destroy() export static void destroy()
{ {
if (instance is null)
return;
foreach (ref system; instance.systems) foreach (ref system; instance.systems)
{ {
@ -45,6 +49,12 @@ class EntityManager
instance = null; instance = null;
} }
this()
{
//event_manager = EventManager(this);
//event_manager.manager = this;
}
void registerSystem(Sys)(int priority) void registerSystem(Sys)(int priority)
{ {
alias types = Parameters!(Sys.update); alias types = Parameters!(Sys.update);
@ -205,14 +215,14 @@ class EntityManager
mixin(genCompList()); mixin(genCompList());
ushort sys_id = systems_map.get(Sys.stringof, ushort.max); ushort sys_id = systems_map.get(Sys.stringof, ushort.max);
if(sys_id < systems.length) if (sys_id < systems.length)
{ {
system.enable(); system.enable();
systems[sys_id] = system; systems[sys_id] = system;
} }
else else
{ {
systems_map.add(Sys.stringof,cast(ushort)systems.length); systems_map.add(Sys.stringof, cast(ushort) systems.length);
systems.add(system); systems.add(system);
@ -232,7 +242,6 @@ class EntityManager
void registerComponent(Comp)() void registerComponent(Comp)()
{ {
ComponentInfo info; ComponentInfo info;
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort)) static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
@ -253,12 +262,12 @@ class EntityManager
} }
info.size = Comp.sizeof; info.size = Comp.sizeof;
info.aligment = Comp.alignof; //8; info.alignment = Comp.alignof; //8;
info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof); info.init_data = Mallocator.instance.makeArray!ubyte(Comp.sizeof);
*cast(Comp*) info.init_data.ptr = Comp.init; // = Comp(); *cast(Comp*) info.init_data.ptr = Comp.init; // = Comp();
ushort comp_id = components_map.get(Comp.stringof, ushort.max); ushort comp_id = components_map.get(Comp.stringof, ushort.max);
if(comp_id < components.length) if (comp_id < components.length)
{ {
Comp.component_id = comp_id; Comp.component_id = comp_id;
} }
@ -270,6 +279,42 @@ class EntityManager
} }
} }
void registerEvent(Ev)()
{
EventInfo info;
static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort))
{
static assert(0, "Event should have \"__gshared ushort event_id");
}
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
&& is(ReturnType!(Ev.onDestroy) == void) && Parameters!(Ev.onDestroy).length == 0)
{
static void callDestroy(void* pointer)
{
(cast(Ev*) pointer).onDestroy();
}
info.destroy_callback = &callDestroy;
}
info.size = Ev.sizeof;
info.alignment = Ev.alignof;
ushort event_id = events_map.get(Ev.stringof, ushort.max);
if (event_id < events.length)
{
Ev.event_id = event_id;
}
else
{
events.add(info);
Ev.event_id = cast(ushort)(events.length - 1);
events_map.add(Ev.stringof, cast(ushort)(events.length - 1));
}
}
export void update() export void update()
{ {
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
@ -282,9 +327,9 @@ class EntityManager
} }
} }
static void alignNum(ref ushort num, ushort aligment) static void alignNum(ref ushort num, ushort alignment)
{ {
num = cast(ushort)((num + aligment - 1) & (-cast(int) aligment)); //num += aligment - (num & (aligment - 1)); num = cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); //num += alignment - (num & (alignment - 1));
} }
extern (C) static int compareUShorts(const void* a, const void* b) extern (C) static int compareUShorts(const void* a, const void* b)
@ -352,8 +397,8 @@ class EntityManager
foreach (i, id; ids) foreach (i, id; ids)
{ {
info.alignment = max(info.alignment, components[id].aligment); info.alignment = max(info.alignment, components[id].alignment);
alignNum(info.size, components[id].aligment); alignNum(info.size, components[id].alignment);
info.deltas[id] = info.size; info.deltas[id] = info.size;
info.size += components[id].size; info.size += components[id].size;
} }
@ -874,16 +919,25 @@ class EntityManager
updateBlocks(); updateBlocks();
changeEntites(); changeEntites();
removeEntities(); removeEntities();
clearEvents();
} }
struct ComponentInfo struct ComponentInfo
{ {
ushort size; ushort size;
ushort aligment; ushort alignment;
ubyte[] init_data; ubyte[] init_data;
void function(void* pointer) destroy_callback; void function(void* pointer) destroy_callback;
} }
struct EventInfo
{
ushort size;
ushort alignment;
void function(void* pointer) destroy_callback;
}
/************************************************************************************************************************ /************************************************************************************************************************
*Entity type info. *Entity type info.
*/ */
@ -893,7 +947,7 @@ class EntityManager
ushort[] components; ushort[] components;
///deltas in memory for components ///deltas in memory for components
ushort[] deltas; ushort[] deltas;
///aligment of whole entity ///alignment of whole entity
ushort alignment; ushort alignment;
///size of entity (with alignment respect) ///size of entity (with alignment respect)
ushort size; ushort size;
@ -956,13 +1010,20 @@ class EntityManager
alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity); alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity);
//alias sendSelfEvent = instance.event_manager.sendSelfEvent;
//alias event_manager this;
///Single page size. Must be power of two. ///Single page size. Must be power of two.
enum page_size = 4096; enum page_size = 4096;
///Number of pages in block. ///Number of pages in block.
enum pages_in_block = 128; enum pages_in_block = 128;
IDManager id_manager; IDManager id_manager;
EntityAllocator allocator; BlockAllocator!(page_size, pages_in_block) allocator;
//EventManager event_manager;
mixin EventManagerCode;
Vector!EntityID entities_to_remove; Vector!EntityID entities_to_remove;
Vector!(EntitiesBlock*) blocks_to_update; Vector!(EntitiesBlock*) blocks_to_update;
@ -971,37 +1032,13 @@ class EntityManager
HashMap!(ushort[], EntityInfo*) entities_infos; HashMap!(ushort[], EntityInfo*) entities_infos;
HashMap!(string, ushort) systems_map; HashMap!(string, ushort) systems_map;
HashMap!(string, ushort) components_map; HashMap!(string, ushort) components_map;
HashMap!(string, ushort) events_map;
Vector!System systems; Vector!System systems;
Vector!ComponentInfo components; Vector!ComponentInfo components;
__gshared EntityManager instance; Vector!EventInfo events;
__gshared EntityManager instance = null;
} }
version(Windows)
extern(Windows) bool DllMain(void* hInstance, uint ulReason, void*) {
import core.sys.windows.windows;
import core.sys.windows.dll;
switch (ulReason)
{
default: assert(0);
case DLL_PROCESS_ATTACH:
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
}
return true;
}
/* /*
static ulong defaultHashFunc(T)(auto ref T t) static ulong defaultHashFunc(T)(auto ref T t)
{ {

30
source/win_dll.d Normal file
View file

@ -0,0 +1,30 @@
module win_dll;
version(Windows):
import core.sys.windows.dll;
import core.sys.windows.windows;
extern(Windows) bool DllMain(void* hInstance, uint ulReason, void*)
{
switch (ulReason)
{
default: assert(0);
case DLL_PROCESS_ATTACH:
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
}
return true;
}

View file

@ -10,6 +10,19 @@ import std.stdio;
int main() int main()
{ {
struct TestEvent
{
__gshared ushort event_id;
int a;
}
struct TestEvent2
{
__gshared ushort event_id;
float a;
}
struct TestComp struct TestComp
{ {
__gshared ushort component_id; __gshared ushort component_id;
@ -124,7 +137,7 @@ int main()
test3.gg = 200; test3.gg = 200;
} }
void handleEvent(Event event, ref TestComp comp) void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
{ {
} }
@ -145,10 +158,10 @@ int main()
//writeln("High priority tekst! "); //writeln("High priority tekst! ");
} }
void handleEvent(Event event, ref TestComp comp) /*void handleEvent(Event event, ref TestComp comp)
{ {
} }*/
} }
struct TestSystem2 struct TestSystem2
@ -177,12 +190,13 @@ int main()
{ {
//writeln("TestSystem2 update"); //writeln("TestSystem2 update");
test.gg += 14; test.gg += 14;
gEM.sendSelfEvent!(TestEvent)(entity.id, TestEvent());
} }
void handleEvent(Event event, ref TestComp comp) /*void handleEvent(Event event, ref TestComp comp)
{ {
} }*/
} }
EntityManager.initialize(); EntityManager.initialize();
@ -195,6 +209,9 @@ int main()
gEM.registerComponent!TestComp; gEM.registerComponent!TestComp;
gEM.registerComponent!TestComp3; gEM.registerComponent!TestComp3;
gEM.registerEvent!TestEvent;
gEM.registerEvent!TestEvent2;
ulong dur = (MonoTime.currTime - time).total!"usecs"; ulong dur = (MonoTime.currTime - time).total!"usecs";
writeln("Components register: ", dur, " usecs"); writeln("Components register: ", dur, " usecs");
@ -288,7 +305,7 @@ int main()
writeln((cast(uint*) pp)[0 .. 14], " ", pp); writeln((cast(uint*) pp)[0 .. 14], " ", pp);
gEM.removeComponents!(TestComp)(entity.id); //gEM.removeComponents!(TestComp)(entity.id);
gEM.begin(); gEM.begin();
gEM.update(); gEM.update();