-BlockAllocator is no longer template

-Multithreaded IDManager.getNewID()
 *use implementation with free IDs stack (instead of classic pool)
-support for multiple UpdatePasses. Passes are added by name, and must be called between begin() end() functions.
-removed mutex from addEntity()
-commit() function added. Used to commit all changes made while update() call. Called automatically by begin() end() functions.
This commit is contained in:
Mergul 2018-10-25 11:46:08 +02:00
parent 430ce8074c
commit d3f7593afc
6 changed files with 406 additions and 189 deletions

View file

@ -5,8 +5,11 @@ 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 BlockAllocator(uint block_size, uint blocks_in_allocation) struct BlockAllocator//(uint block_size, uint blocks_in_allocation)
{ {
private uint block_size;
private uint blocks_in_allocation;
void* next_block = null; void* next_block = null;
void* getBlock() void* getBlock()

View file

@ -17,10 +17,10 @@ mixin template EventManagerCode()
//@disable this(); //@disable this();
this(EntityManager m) /*this(EntityManager m)
{ {
manager = m; manager = m;
} }*/
void sendSelfEvent(Ev)(EntityID id, Ev event) void sendSelfEvent(Ev)(EntityID id, Ev event)
{ {
@ -120,6 +120,6 @@ mixin template EventManagerCode()
EventList current_events; EventList current_events;
EventList process_events; EventList process_events;
BlockAllocator!(events_block_size, events_blocks_in_allocation) allocator; BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator;
EntityManager manager; EntityManager manager;
} }

View file

@ -1,8 +1,15 @@
module ecs.id_manager; module ecs.id_manager;
import std.experimental.allocator;
import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
import ecs.entity; import ecs.entity;
import ecs.vector; import ecs.vector;
import core.atomic;
import core.stdc.string : memcpy;
import core.sync.mutex;
/************************************************************************************************************************ /************************************************************************************************************************
*IDManager is responsible for assignment and removing IDs. IDs are unique throughtout a whole duration of the program. *IDManager is responsible for assignment and removing IDs. IDs are unique throughtout a whole duration of the program.
*/ */
@ -11,19 +18,64 @@ struct IDManager
/************************************************************************************************************************ /************************************************************************************************************************
*Get new ID. *Get new ID.
*/ */
EntityID getNewID() pragma(inline, false) EntityID getNewID()
{ {
if (m_next_id >= m_ids_array.length) //uint current = m_next_id;
m_ids_array.add(Data()); //uint next;// = m_ids_array[m_next_id].next_id;
begin:
//if (current == uint.max)//> m_last_id)
int current = m_stack_top.atomicOp!"-="(1) + 1;
if(current < 0)
{
uint add_id = m_last_id.atomicOp!"+="(1) - 1;
if (add_id >= m_ids_array.length)
{
uint local_id = add_id - cast(uint) m_ids_array.length;
uint block_id = local_id >> 16;
if (block_id >= m_blocks_count)
{
add_mutex.lock();
if(block_id >= m_blocks_count)
{
m_blocks[m_blocks_count].alloc();
m_blocks_count++;
}
add_mutex.unlock();
}
}
EntityID id; EntityID id;
id.id = m_next_id; id.id = add_id;
id.counter = /*++*/m_ids_array[m_next_id].counter; id.counter = 0;
m_next_id = m_ids_array[m_next_id].next_id;
if (m_next_id == uint.max)
m_next_id = cast(uint) m_ids_array.length;
return id; return id;
} }
//current += 1;
uint index = m_free_stack[current];
EntityID id;
id.id = index;
id.counter = m_ids_array[index].counter;
//current = m_ids_array[index].next_id;
return id;
/*next = m_ids_array[current].next_id;
if(cas(&m_next_id,current,next))
{
EntityID id;
id.id = current;
id.counter = m_ids_array[current].counter;
m_next_id = m_ids_array[current].next_id;
return id;
}
else
{
current = next;
goto begin;
}*/
}
/************************************************************************************************************************ /************************************************************************************************************************
*Release ID. *Release ID.
*/ */
@ -33,9 +85,12 @@ struct IDManager
if (data.counter != id.counter) if (data.counter != id.counter)
return; return;
data.counter++; data.counter++;
data.next_id = m_next_id; //data.next_id = m_next_id;
data.entity = null; data.entity = null;
m_next_id = id.id; ///m_next_id = id.id;
m_stack_top.atomicOp!"+="(1);
m_free_stack[m_stack_top] = id.id;
} }
/************************************************************************************************************************ /************************************************************************************************************************
@ -43,7 +98,15 @@ struct IDManager
*/ */
void update(ref Entity entity) void update(ref Entity entity)
{ {
if(entity.id.counter == m_ids_array[entity.id.id].counter)m_ids_array[entity.id.id].entity = &entity; if (entity.id.id >= cast(uint) m_ids_array.length)
{
uint local_id = entity.id.id - cast(uint) m_ids_array.length;
uint block_id = local_id >> 16;
local_id -= block_id << 16;
m_blocks[block_id].data[local_id].entity = &entity;
}
else //if (entity.id.counter == m_ids_array[entity.id.id].counter)
m_ids_array[entity.id.id].entity = &entity;
} }
/************************************************************************************************************************ /************************************************************************************************************************
@ -51,6 +114,19 @@ struct IDManager
*/ */
export Entity* getEntityPointer(EntityID id) export Entity* getEntityPointer(EntityID id)
{ {
if (id.id >= m_ids_array.length)
{
uint local_id = id.id - cast(uint) m_ids_array.length;
uint block_id = local_id >> 16;
assert(block_id < m_blocks_count);
if (block_id >= m_blocks_count)
return null;
local_id -= block_id << 16;
if (m_blocks[block_id].data[local_id].counter != id.counter)
return null;
return m_blocks[block_id].data[local_id].entity;
}
Data* data = &m_ids_array[id.id]; Data* data = &m_ids_array[id.id];
if (data.counter != id.counter) if (data.counter != id.counter)
return null; return null;
@ -67,16 +143,81 @@ struct IDManager
return data.counter == id.counter; return data.counter == id.counter;
} }
void initialize()
{
m_ids_array = Mallocator.instance.makeArray!Data(65536);
m_free_stack = Mallocator.instance.makeArray!uint(65536);
m_blocks = Mallocator.instance.makeArray!Block(64);
m_blocks_count = 1;
m_blocks[0].alloc();
add_mutex = Mallocator.instance.make!Mutex();
}
void optimize()
{
if(m_stack_top < -1)m_stack_top = -1;
if(m_last_id > m_ids_array.length)
{
uint begin = cast(uint)m_ids_array.length;
Data[] new_array = Mallocator.instance.makeArray!Data(begin + (m_blocks_count << 16));
memcpy(new_array.ptr, m_ids_array.ptr, m_ids_array.length * Data.sizeof);
Mallocator.instance.dispose(m_ids_array);
m_ids_array = new_array;
uint[] new_stack = Mallocator.instance.makeArray!uint(m_ids_array.length);
memcpy(new_stack.ptr,m_free_stack.ptr,m_free_stack.length * uint.sizeof);
Mallocator.instance.dispose(m_free_stack);
m_free_stack = new_stack;
foreach(block;m_blocks[0..m_blocks_count-1])
{
memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, block.data.ptr, 65536 * Data.sizeof);
begin += 65536;
}
memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, m_blocks[m_blocks_count-1].data.ptr, (m_last_id - begin) * Data.sizeof);
foreach(block;m_blocks[1..m_blocks_count])block.free();
m_blocks_count = 1;
}
}
private static struct Block
{
void alloc()
{
assert(data is null);
data = Mallocator.instance.makeArray!Data(65536);
}
void free()
{
assert(data !is null);
Mallocator.instance.dispose(data);
}
Data[] data; //65536
}
private static struct Data private static struct Data
{ {
uint counter = 0; uint counter = 0;
uint next_id = uint.max; //uint next_id = uint.max;
Entity* entity = null; Entity* entity = null;
} }
private: private:
uint m_next_id; Mutex add_mutex;
Vector!Data m_ids_array; //shared uint m_next_id = 0;
//shared uint m_last_id = 0;
Data[] m_ids_array = null;
uint m_blocks_count = 0;
Block[] m_blocks;
//shared int m_stack_top = -1;
uint[] m_free_stack = null;
align(64) shared uint m_last_id = 0;
align(64) shared int m_stack_top = -1;
} }
unittest unittest

View file

@ -59,10 +59,30 @@ class EntityManager
threads_count = 0; threads_count = 0;
threads = Mallocator.instance.makeArray!ThreadData(threads_count); threads = Mallocator.instance.makeArray!ThreadData(threads_count);
add_mutex = Mallocator.instance.make!Mutex; id_manager.initialize();
allocator = BlockAllocator(page_size,pages_in_block);
//add_mutex = Mallocator.instance.make!Mutex;
entity_block_alloc_mutex = Mallocator.instance.make!Mutex; entity_block_alloc_mutex = Mallocator.instance.make!Mutex;
//event_manager = EventManager(this); //event_manager = EventManager(this);
//event_manager.manager = this; //event_manager.manager = this;
UpdatePass* pass = Mallocator.instance.make!UpdatePass;
pass.name = Mallocator.instance.makeArray("update");
passes.add(pass);
passes_map.add(cast(string)pass.name, cast(ushort)(passes.length - 1));
}
/************************************************************************************************************************
*Same as "void registerSystem(Sys)(int priority, int pass = 0)" but use pass name instead of id.
*/
void registerSystem(Sys)(int priority, const (char)[] pass_name)
{
ushort pass = passes_map.get(pass_name, ushort.max);
assert(pass != ushort.max);
registerSystem!(Sys)(priority, pass);
} }
/************************************************************************************************************************ /************************************************************************************************************************
@ -73,11 +93,14 @@ class EntityManager
*params: *params:
*priority = system priority. Priority determines order of execution of systems updates. *priority = system priority. Priority determines order of execution of systems updates.
*/ */
void registerSystem(Sys)(int priority) void registerSystem(Sys)(int priority, ushort pass = 0)
{ {
alias STC = ParameterStorageClass; alias STC = ParameterStorageClass;
assert(pass < passes.length);
System system; System system;
system.m_pass = pass;
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{ {
@ -450,10 +473,6 @@ class EntityManager
mixin(genCompList()); mixin(genCompList());
/*if(system.m_components)qsort(system.m_components.ptr, system.m_components.length, ushort.sizeof, &compareUShorts);
if(system.m_optional_components)qsort(system.m_optional_components.ptr, system.m_optional_components.length, ushort.sizeof, &compareUShorts);
if(system.m_absent_components)qsort(system.m_absent_components.ptr, system.m_absent_components.length, ushort.sizeof, &compareUShorts);*/
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)
{ {
@ -492,13 +511,13 @@ class EntityManager
version (UpdateBySystems) version (UpdateBySystems)
{ {
bool added = false; bool added = false;
foreach (i, ref caller; system_callers) foreach (i, ref caller; passes[pass].system_callers)
{ {
if (systems[caller.system_id].priority > priority) if (systems[caller.system_id].priority > priority)
{ {
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller; SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = Sys.system_id; sys_caller.system_id = Sys.system_id;
system_callers.add(sys_caller, i); passes[pass].system_callers.add(sys_caller, i);
added = true; added = true;
break; break;
} }
@ -507,7 +526,7 @@ class EntityManager
{ {
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller; SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
sys_caller.system_id = Sys.system_id; sys_caller.system_id = Sys.system_id;
system_callers.add(sys_caller); passes[pass].system_callers.add(sys_caller);
} }
} }
} }
@ -525,6 +544,15 @@ class EntityManager
return cast(Sys*) systems[Sys.system_id].m_system_pointer; return cast(Sys*) systems[Sys.system_id].m_system_pointer;
} }
ushort registerPass(const (char)[] name)
{
UpdatePass* pass = Mallocator.instance.make!UpdatePass;
pass.name = Mallocator.instance.makeArray(name);
passes.add(pass);
passes_map.add(name,cast(ushort)(passes.length - 1));
return cast(ushort)(passes.length - 1);
}
/************************************************************************************************************************ /************************************************************************************************************************
*Register component into EntityManager. *Register component into EntityManager.
*/ */
@ -564,7 +592,7 @@ class EntityManager
{ {
components.add(info); components.add(info);
Comp.component_id = cast(ushort)(components.length - 1); Comp.component_id = cast(ushort)(components.length - 1);
string name = Mallocator.instance.makeArray(Comp.stringof); const (char)[] name = Mallocator.instance.makeArray(Comp.stringof);
components_map.add(name, cast(ushort)(components.length - 1)); components_map.add(name, cast(ushort)(components.length - 1));
} }
} }
@ -605,14 +633,25 @@ class EntityManager
} }
} }
/************************************************************************************************************************
*Same as "void update(int pass = 0)" but use pass name instead of id.
*/
void update(const (char)[] pass_name)
{
ushort pass = passes_map.get(pass_name, ushort.max);
assert(pass != ushort.max);
update(pass);
}
/************************************************************************************************************************ /************************************************************************************************************************
*Update systems. Should be called only between begin() and end(). *Update systems. Should be called only between begin() and end().
*/ */
export void update() export void update(ushort pass = 0)
{ {
assert(pass < passes.length);
version (UpdateBySystems) version (UpdateBySystems)
{ {
foreach (caller; system_callers) foreach (caller; passes[pass].system_callers)
{ {
System* sys = &systems[caller.system_id]; System* sys = &systems[caller.system_id];
if (sys.enabled) if (sys.enabled)
@ -644,14 +683,25 @@ class EntityManager
} }
} }
void updateMT() /************************************************************************************************************************
*Same as "void updateMT(int pass = 0)" but use pass name instead of id.
*/
void updateMT(const (char)[] pass_name)
{ {
ushort pass = passes_map.get(pass_name, ushort.max);
assert(pass != ushort.max);
updateMT(pass);
}
void updateMT(ushort pass = 0)
{
assert(pass < passes.length);
assert(m_dispatch_jobs, assert(m_dispatch_jobs,
"Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc()."); "Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc().");
Vector!CallData tmp_datas; Vector!CallData tmp_datas;
tmp_datas.reserve(8); tmp_datas.reserve(8);
foreach (caller; system_callers) foreach (caller; passes[pass].system_callers)
{ {
System* sys = &systems[caller.system_id]; System* sys = &systems[caller.system_id];
if (sys.enabled) if (sys.enabled)
@ -766,7 +816,7 @@ class EntityManager
nextJob(); nextJob();
caller.job_group.jobs = sys.jobs[0 .. job_id]; caller.job_group.jobs = sys.jobs[0 .. job_id];
m_dispatch_jobs(caller.job_group);//sys.jobs[0 .. job_id]); m_dispatch_jobs(caller.job_group); //sys.jobs[0 .. job_id]);
} }
} }
} }
@ -978,14 +1028,14 @@ class EntityManager
} }
uint index = 0; uint index = 0;
for (; index < system_callers.length; index++) for (; index < passes[system.m_pass].system_callers.length; index++)
{ {
if (system_callers[index].system_id == system_id) if (passes[system.m_pass].system_callers[index].system_id == system_id)
break; break;
} }
if (index < system_callers.length) if (index < passes[system.m_pass].system_callers.length)
system_callers[index].infos.add(&entity); passes[system.m_pass].system_callers[index].infos.add(&entity);
/*for (; index < entity.callers.length; index++) /*for (; index < entity.callers.length; index++)
{ {
CallData* caller = &entity.callers[index]; CallData* caller = &entity.callers[index];
@ -1137,10 +1187,6 @@ class EntityManager
del_ids[i] = comp.component_id; del_ids[i] = comp.component_id;
} }
/*change_entities_list.add(0);
change_entities_list.add((cast(ubyte*)&entity_id)[0..8]);
change_entities_list.add((cast(ubyte*)&num)[0..4]);
change_entities_list.add(cast(ubyte[])del_ids);*/
removeComponents(entity_id, del_ids); removeComponents(entity_id, del_ids);
} }
@ -1361,9 +1407,9 @@ class EntityManager
threads[thread_id].blocks_to_update.add(block); threads[thread_id].blocks_to_update.add(block);
Entity* entity = cast(Entity*) start; Entity* entity = cast(Entity*) start;
add_mutex.lock_nothrow(); //add_mutex.lock_nothrow();
entity.id = id_manager.getNewID(); entity.id = id_manager.getNewID();
add_mutex.unlock_nothrow(); //add_mutex.unlock_nothrow();
entity.updateID(); entity.updateID();
return *entity; return *entity;
@ -1605,51 +1651,43 @@ class EntityManager
} }
} }
export void commit()
{
id_manager.optimize();
updateBlocks();
removeEntities();
changeEntities();
}
/************************************************************************************************************************ /************************************************************************************************************************
*Begin of update process. Should be called before any update is called. *Begin of update process. Should be called before any update is called.
*/ */
export void begin() export void begin()
{ {
updateBlocks();
removeEntities(); commit();
changeEntities();
m_call_data_allocator.clear(); m_call_data_allocator.clear();
/*version (UpdateBySystems)
{
}
else
{*/
foreach (ref system; instance.systems) foreach (ref system; instance.systems)
{ {
if (system.m_begin) if (system.m_begin)
(cast(void function(void*)) system.m_begin)(system.m_system_pointer); (cast(void function(void*)) system.m_begin)(system.m_system_pointer);
} }
//}
} }
/************************************************************************************************************************ /************************************************************************************************************************
*End of update process. Should be called after every update function. *End of update process. Should be called after every update function.
*/ */
export void end() export void end()
{
/*version (UpdateBySystems)
{ {
}
else
{*/
foreach (ref system; instance.systems) foreach (ref system; instance.systems)
{ {
if (system.m_end) if (system.m_end)
(cast(void function(void*)) system.m_end)(system.m_system_pointer); (cast(void function(void*)) system.m_end)(system.m_system_pointer);
} }
//}
updateBlocks(); commit();
removeEntities();
changeEntities();
//clearEvents(); //clearEvents();
} }
@ -1665,22 +1703,26 @@ class EntityManager
/*private */ /*private */
void generateDependencies() void generateDependencies()
{ {
foreach (caller; system_callers) foreach(pass_id,pass;passes)
{
foreach (caller; pass.system_callers)
{ {
caller.system = &systems[caller.system_id]; caller.system = &systems[caller.system_id];
if(caller.exclusion)Mallocator.instance.dispose(caller.exclusion); if (caller.exclusion)
if(caller.dependencies)Mallocator.instance.dispose(caller.dependencies); Mallocator.instance.dispose(caller.exclusion);
if (caller.dependencies)
Mallocator.instance.dispose(caller.dependencies);
} }
uint index = 0; uint index = 0;
SystemCaller*[] exclusion; SystemCaller*[] exclusion;
exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0 exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0
.. system_callers.length]; .. pass.system_callers.length];
foreach (caller; system_callers) foreach (caller; pass.system_callers)
{ {
index = 0; index = 0;
out_for: foreach (caller2; system_callers) out_for: foreach (caller2; pass.system_callers)
{ {
if (/*caller.system.priority != caller2.system.priority ||*/ caller is caller2) if ( /*caller.system.priority != caller2.system.priority ||*/ caller is caller2)
continue; continue;
foreach (cmp; caller.system.m_read_only_components) foreach (cmp; caller.system.m_read_only_components)
{ {
@ -1714,9 +1756,10 @@ class EntityManager
} }
} }
if (index > 0)
if(index > 0)caller.exclusion = Mallocator.instance.makeArray(exclusion[0..index]); caller.exclusion = Mallocator.instance.makeArray(exclusion[0 .. index]);
else caller.exclusion = null; else
caller.exclusion = null;
/*import std.stdio; /*import std.stdio;
write("Exclusive systems for system ", caller.system.name, ": "); write("Exclusive systems for system ", caller.system.name, ": ");
@ -1744,7 +1787,7 @@ class EntityManager
return 1; return 1;
} }
qsort(system_callers.array.ptr, system_callers.length, (SystemCaller*) qsort(pass.system_callers.array.ptr, pass.system_callers.length, (SystemCaller*)
.sizeof, &compareSystems); .sizeof, &compareSystems);
/*static struct CallerData /*static struct CallerData
@ -1753,21 +1796,22 @@ class EntityManager
//bool //bool
}*/ }*/
/*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0 /*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0
.. system_callers.length];*/ .. pass.system_callers.length];*/
foreach(uint i,caller;system_callers)caller.job_group.id = i; foreach (uint i, caller; pass.system_callers)
caller.job_group.id = i;
int priority = int.min; int priority = int.min;
uint beg = 0; uint beg = 0;
index = 0; index = 0;
foreach(uint i,caller;system_callers) foreach (uint i, caller; pass.system_callers)
{ {
/* /*
if(priority == int.min)priority = caller.system.priority; if(priority == int.min)priority = caller.system.priority;
if(priority != caller.system.priority) if(priority != caller.system.priority)
{ {
foreach(caller2;system_callers[beg..i]) foreach(caller2;pass.system_callers[beg..i])
{ {
} }
@ -1775,24 +1819,26 @@ class EntityManager
beg = i; beg = i;
}*/ }*/
index = 0; index = 0;
foreach(ex;caller.exclusion) foreach (ex; caller.exclusion)
{ {
if(ex.job_group.id > caller.job_group.id)continue; if (ex.job_group.id > caller.job_group.id)
continue;
exclusion[index++] = ex; exclusion[index++] = ex;
} }
if(index > 0) if (index > 0)
{ {
caller.dependencies = Mallocator.instance.makeArray(exclusion[0..index]); caller.dependencies = Mallocator.instance.makeArray(exclusion[0 .. index]);
caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index); caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index);
foreach(j,dep;caller.dependencies) foreach (j, dep; caller.dependencies)
{ {
caller.job_group.dependencies[j] = &dep.job_group; caller.job_group.dependencies[j] = &dep.job_group;
} }
} }
else caller.dependencies = null; else
caller.dependencies = null;
/*import std.stdio; /*import std.stdio;
write("Dependencies for system ", caller.system.name, ": "); write("Dependencies for system ", caller.system.name, ": ");
@ -1801,6 +1847,7 @@ class EntityManager
writeln();*/ writeln();*/
} }
} }
}
/************************************************************************************************************************ /************************************************************************************************************************
*Component info; *Component info;
@ -1963,11 +2010,24 @@ class EntityManager
Vector!(EntitiesBlock*) blocks_to_update; Vector!(EntitiesBlock*) blocks_to_update;
} }
struct UpdatePass
{
~this()
{
assert(name);
if(name)Mallocator.instance.dispose(name);
}
char[] name;
Vector!(SystemCaller*) system_callers;
}
static uint thread_id; static uint thread_id;
ThreadData[] threads; ThreadData[] threads;
Vector!(SystemCaller*) system_callers; Vector!(UpdatePass*) passes;
//Vector!(SystemCaller*) system_callers;
alias SytemFuncType = void function(ref EntityManager.CallData data); alias SytemFuncType = void function(ref EntityManager.CallData data);
@ -1981,7 +2041,7 @@ class EntityManager
enum pages_in_block = 128; enum pages_in_block = 128;
IDManager id_manager; IDManager id_manager;
BlockAllocator!(page_size, pages_in_block) allocator; BlockAllocator/*!(page_size, pages_in_block)*/ allocator;
//EventManager event_manager; //EventManager event_manager;
mixin EventManagerCode; mixin EventManagerCode;
@ -1995,13 +2055,14 @@ class EntityManager
HashMap!(ushort[], EntityInfo*) entities_infos; HashMap!(ushort[], EntityInfo*) entities_infos;
HashMap!(const(char)[], ushort) systems_map; HashMap!(const(char)[], ushort) systems_map;
HashMap!(string, ushort) components_map; HashMap!(const(char)[], ushort) components_map;
HashMap!(string, ushort) events_map; HashMap!(const(char)[], ushort) events_map;
HashMap!(const(char)[], ushort) passes_map;
Vector!System systems; Vector!System systems;
Vector!ComponentInfo components; Vector!ComponentInfo components;
Vector!EventInfo events; Vector!EventInfo events;
Mutex add_mutex; //Mutex add_mutex;
Mutex entity_block_alloc_mutex; Mutex entity_block_alloc_mutex;
CallDataAllocator m_call_data_allocator; CallDataAllocator m_call_data_allocator;

View file

@ -53,6 +53,8 @@ package:
int m_priority; int m_priority;
///pointer to system implementation ///pointer to system implementation
void* m_system_pointer; void* m_system_pointer;
///system pass index
int m_pass;
///system name ///system name
const (char)[] name; const (char)[] name;
@ -66,7 +68,7 @@ package:
EntityManager.Job[] jobs; EntityManager.Job[] jobs;
System*[] m_dependencies; //System*[] m_dependencies;
ushort[] m_read_only_components; ushort[] m_read_only_components;
ushort[] m_modified_components; ushort[] m_modified_components;

View file

@ -175,7 +175,7 @@ int main()
void initialize(ref Entity entity, ref TestComp comp) void initialize(ref Entity entity, ref TestComp comp)
{ {
int o = 1;
} }
void update(EntitiesData data) void update(EntitiesData data)
@ -284,6 +284,8 @@ import std.meta;
gEM.setJobDispachFunc(&dispatch); gEM.setJobDispachFunc(&dispatch);
assert(gEM !is null); assert(gEM !is null);
gEM.registerPass("fixed");
MonoTime time = MonoTime.currTime; MonoTime time = MonoTime.currTime;
gEM.registerComponent!TestComp2; gEM.registerComponent!TestComp2;
@ -299,7 +301,7 @@ import std.meta;
time = MonoTime.currTime; time = MonoTime.currTime;
gEM.registerSystem!TestSystemWithHighPriority(100); gEM.registerSystem!TestSystemWithHighPriority(100,"fixed");
gEM.registerSystem!TestSystem(0); gEM.registerSystem!TestSystem(0);
//gEM.registerSystem!TestSystemWithHighPriority(100); //gEM.registerSystem!TestSystemWithHighPriority(100);
//gEM.registerSystem!TestSystem2(0); //gEM.registerSystem!TestSystem2(0);
@ -346,6 +348,7 @@ import std.meta;
gEM.removeEntity(idss[j]); gEM.removeEntity(idss[j]);
gEM.end(); gEM.end();
} }
gEM.commit();
dur = (MonoTime.currTime - time).total!"usecs"; dur = (MonoTime.currTime - time).total!"usecs";
writeln("Entities adding: ", dur, " usecs"); writeln("Entities adding: ", dur, " usecs");
@ -373,12 +376,18 @@ import std.meta;
Entity entity2; Entity entity2;
time = MonoTime.currTime;
foreach (i; 0 .. 500_000) foreach (i; 0 .. 500_000)
{ {
entity2 = gEM.addEntity(tmpl); entity2 = gEM.addEntity(tmpl);
gEM.addEntity(tmpl2); gEM.addEntity(tmpl2);
} }
gEM.commit();
dur = (MonoTime.currTime - time).total!"usecs";
writeln("Entities adding2: ", dur, " usecs");
time = MonoTime.currTime; time = MonoTime.currTime;
gEM.begin(); gEM.begin();
@ -441,6 +450,7 @@ import std.meta;
gEM.begin(); gEM.begin();
gEM.update(); gEM.update();
gEM.update("fixed");
gEM.end(); gEM.end();
writeEntityComponents(gEM.getEntity(entity.id)); writeEntityComponents(gEM.getEntity(entity.id));