-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:
parent
430ce8074c
commit
d3f7593afc
6 changed files with 406 additions and 189 deletions
|
|
@ -5,8 +5,11 @@ import ecs.manager;
|
|||
import std.experimental.allocator;
|
||||
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* getBlock()
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ mixin template EventManagerCode()
|
|||
|
||||
//@disable this();
|
||||
|
||||
this(EntityManager m)
|
||||
/*this(EntityManager m)
|
||||
{
|
||||
manager = m;
|
||||
}
|
||||
}*/
|
||||
|
||||
void sendSelfEvent(Ev)(EntityID id, Ev event)
|
||||
{
|
||||
|
|
@ -120,6 +120,6 @@ mixin template EventManagerCode()
|
|||
EventList current_events;
|
||||
EventList process_events;
|
||||
|
||||
BlockAllocator!(events_block_size, events_blocks_in_allocation) allocator;
|
||||
BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator;
|
||||
EntityManager manager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
module ecs.id_manager;
|
||||
|
||||
import std.experimental.allocator;
|
||||
import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
|
||||
|
||||
import ecs.entity;
|
||||
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.
|
||||
*/
|
||||
|
|
@ -11,17 +18,62 @@ struct IDManager
|
|||
/************************************************************************************************************************
|
||||
*Get new ID.
|
||||
*/
|
||||
EntityID getNewID()
|
||||
pragma(inline, false) EntityID getNewID()
|
||||
{
|
||||
if (m_next_id >= m_ids_array.length)
|
||||
m_ids_array.add(Data());
|
||||
//uint current = m_next_id;
|
||||
//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;
|
||||
id.id = add_id;
|
||||
id.counter = 0;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
//current += 1;
|
||||
uint index = m_free_stack[current];
|
||||
EntityID id;
|
||||
id.id = m_next_id;
|
||||
id.counter = /*++*/m_ids_array[m_next_id].counter;
|
||||
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;
|
||||
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;
|
||||
}*/
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
|
|
@ -33,9 +85,12 @@ struct IDManager
|
|||
if (data.counter != id.counter)
|
||||
return;
|
||||
data.counter++;
|
||||
data.next_id = m_next_id;
|
||||
//data.next_id = m_next_id;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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];
|
||||
if (data.counter != id.counter)
|
||||
return null;
|
||||
|
|
@ -67,16 +143,81 @@ struct IDManager
|
|||
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
|
||||
{
|
||||
uint counter = 0;
|
||||
uint next_id = uint.max;
|
||||
//uint next_id = uint.max;
|
||||
Entity* entity = null;
|
||||
}
|
||||
|
||||
private:
|
||||
uint m_next_id;
|
||||
Vector!Data m_ids_array;
|
||||
Mutex add_mutex;
|
||||
//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
|
||||
|
|
|
|||
|
|
@ -59,10 +59,30 @@ class EntityManager
|
|||
threads_count = 0;
|
||||
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;
|
||||
//event_manager = EventManager(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:
|
||||
*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;
|
||||
|
||||
assert(pass < passes.length);
|
||||
|
||||
System system;
|
||||
system.m_pass = pass;
|
||||
|
||||
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
|
||||
{
|
||||
|
|
@ -450,10 +473,6 @@ class EntityManager
|
|||
|
||||
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);
|
||||
if (sys_id < systems.length)
|
||||
{
|
||||
|
|
@ -492,13 +511,13 @@ class EntityManager
|
|||
version (UpdateBySystems)
|
||||
{
|
||||
bool added = false;
|
||||
foreach (i, ref caller; system_callers)
|
||||
foreach (i, ref caller; passes[pass].system_callers)
|
||||
{
|
||||
if (systems[caller.system_id].priority > priority)
|
||||
{
|
||||
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
|
||||
sys_caller.system_id = Sys.system_id;
|
||||
system_callers.add(sys_caller, i);
|
||||
passes[pass].system_callers.add(sys_caller, i);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -507,7 +526,7 @@ class EntityManager
|
|||
{
|
||||
SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller;
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
|
@ -564,7 +592,7 @@ class EntityManager
|
|||
{
|
||||
components.add(info);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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().
|
||||
*/
|
||||
export void update()
|
||||
export void update(ushort pass = 0)
|
||||
{
|
||||
assert(pass < passes.length);
|
||||
version (UpdateBySystems)
|
||||
{
|
||||
foreach (caller; system_callers)
|
||||
foreach (caller; passes[pass].system_callers)
|
||||
{
|
||||
System* sys = &systems[caller.system_id];
|
||||
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,
|
||||
"Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc().");
|
||||
Vector!CallData tmp_datas;
|
||||
tmp_datas.reserve(8);
|
||||
|
||||
foreach (caller; system_callers)
|
||||
foreach (caller; passes[pass].system_callers)
|
||||
{
|
||||
System* sys = &systems[caller.system_id];
|
||||
if (sys.enabled)
|
||||
|
|
@ -766,7 +816,7 @@ class EntityManager
|
|||
nextJob();
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
if (index < system_callers.length)
|
||||
system_callers[index].infos.add(&entity);
|
||||
if (index < passes[system.m_pass].system_callers.length)
|
||||
passes[system.m_pass].system_callers[index].infos.add(&entity);
|
||||
/*for (; index < entity.callers.length; index++)
|
||||
{
|
||||
CallData* caller = &entity.callers[index];
|
||||
|
|
@ -1137,10 +1187,6 @@ class EntityManager
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1361,9 +1407,9 @@ class EntityManager
|
|||
threads[thread_id].blocks_to_update.add(block);
|
||||
|
||||
Entity* entity = cast(Entity*) start;
|
||||
add_mutex.lock_nothrow();
|
||||
//add_mutex.lock_nothrow();
|
||||
entity.id = id_manager.getNewID();
|
||||
add_mutex.unlock_nothrow();
|
||||
//add_mutex.unlock_nothrow();
|
||||
entity.updateID();
|
||||
|
||||
return *entity;
|
||||
|
|
@ -1605,28 +1651,28 @@ class EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
export void commit()
|
||||
{
|
||||
id_manager.optimize();
|
||||
updateBlocks();
|
||||
removeEntities();
|
||||
changeEntities();
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
*Begin of update process. Should be called before any update is called.
|
||||
*/
|
||||
export void begin()
|
||||
{
|
||||
updateBlocks();
|
||||
removeEntities();
|
||||
changeEntities();
|
||||
|
||||
commit();
|
||||
m_call_data_allocator.clear();
|
||||
|
||||
/*version (UpdateBySystems)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{*/
|
||||
foreach (ref system; instance.systems)
|
||||
{
|
||||
if (system.m_begin)
|
||||
(cast(void function(void*)) system.m_begin)(system.m_system_pointer);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
|
|
@ -1634,22 +1680,14 @@ class EntityManager
|
|||
*/
|
||||
export void end()
|
||||
{
|
||||
/*version (UpdateBySystems)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{*/
|
||||
|
||||
foreach (ref system; instance.systems)
|
||||
{
|
||||
if (system.m_end)
|
||||
(cast(void function(void*)) system.m_end)(system.m_system_pointer);
|
||||
}
|
||||
//}
|
||||
|
||||
updateBlocks();
|
||||
removeEntities();
|
||||
changeEntities();
|
||||
commit();
|
||||
|
||||
//clearEvents();
|
||||
}
|
||||
|
|
@ -1665,140 +1703,149 @@ class EntityManager
|
|||
/*private */
|
||||
void generateDependencies()
|
||||
{
|
||||
foreach (caller; system_callers)
|
||||
foreach(pass_id,pass;passes)
|
||||
{
|
||||
caller.system = &systems[caller.system_id];
|
||||
if(caller.exclusion)Mallocator.instance.dispose(caller.exclusion);
|
||||
if(caller.dependencies)Mallocator.instance.dispose(caller.dependencies);
|
||||
}
|
||||
uint index = 0;
|
||||
SystemCaller*[] exclusion;
|
||||
exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0
|
||||
.. system_callers.length];
|
||||
foreach (caller; system_callers)
|
||||
{
|
||||
index = 0;
|
||||
out_for: foreach (caller2; system_callers)
|
||||
foreach (caller; pass.system_callers)
|
||||
{
|
||||
if (/*caller.system.priority != caller2.system.priority ||*/ caller is caller2)
|
||||
continue;
|
||||
foreach (cmp; caller.system.m_read_only_components)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_modified_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (cmp; caller.system.m_modified_components)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_read_only_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
foreach (cmp2; caller2.system.m_modified_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
caller.system = &systems[caller.system_id];
|
||||
if (caller.exclusion)
|
||||
Mallocator.instance.dispose(caller.exclusion);
|
||||
if (caller.dependencies)
|
||||
Mallocator.instance.dispose(caller.dependencies);
|
||||
}
|
||||
|
||||
|
||||
if(index > 0)caller.exclusion = Mallocator.instance.makeArray(exclusion[0..index]);
|
||||
else caller.exclusion = null;
|
||||
|
||||
/*import std.stdio;
|
||||
write("Exclusive systems for system ", caller.system.name, ": ");
|
||||
foreach (ex; exclusion[0 .. index])
|
||||
write(ex.system.name, " ");
|
||||
writeln();*/
|
||||
}
|
||||
|
||||
extern (C) static int compareSystems(const void* a, const void* b)
|
||||
{
|
||||
SystemCaller* _a = *cast(SystemCaller**) a;
|
||||
SystemCaller* _b = *cast(SystemCaller**) b;
|
||||
if (_a.system.priority < _b.system.priority)
|
||||
return -1;
|
||||
else if (_a.system.priority == _b.system.priority)
|
||||
uint index = 0;
|
||||
SystemCaller*[] exclusion;
|
||||
exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0
|
||||
.. pass.system_callers.length];
|
||||
foreach (caller; pass.system_callers)
|
||||
{
|
||||
if (_a.exclusion.length < _b.exclusion.length)
|
||||
index = 0;
|
||||
out_for: foreach (caller2; pass.system_callers)
|
||||
{
|
||||
if ( /*caller.system.priority != caller2.system.priority ||*/ caller is caller2)
|
||||
continue;
|
||||
foreach (cmp; caller.system.m_read_only_components)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_modified_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (cmp; caller.system.m_modified_components)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_read_only_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
foreach (cmp2; caller2.system.m_modified_components)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index > 0)
|
||||
caller.exclusion = Mallocator.instance.makeArray(exclusion[0 .. index]);
|
||||
else
|
||||
caller.exclusion = null;
|
||||
|
||||
/*import std.stdio;
|
||||
write("Exclusive systems for system ", caller.system.name, ": ");
|
||||
foreach (ex; exclusion[0 .. index])
|
||||
write(ex.system.name, " ");
|
||||
writeln();*/
|
||||
}
|
||||
|
||||
extern (C) static int compareSystems(const void* a, const void* b)
|
||||
{
|
||||
SystemCaller* _a = *cast(SystemCaller**) a;
|
||||
SystemCaller* _b = *cast(SystemCaller**) b;
|
||||
if (_a.system.priority < _b.system.priority)
|
||||
return -1;
|
||||
else if (_a.exclusion.length == _b.exclusion.length)
|
||||
return 0;
|
||||
else if (_a.system.priority == _b.system.priority)
|
||||
{
|
||||
if (_a.exclusion.length < _b.exclusion.length)
|
||||
return -1;
|
||||
else if (_a.exclusion.length == _b.exclusion.length)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
qsort(system_callers.array.ptr, system_callers.length, (SystemCaller*)
|
||||
.sizeof, &compareSystems);
|
||||
qsort(pass.system_callers.array.ptr, pass.system_callers.length, (SystemCaller*)
|
||||
.sizeof, &compareSystems);
|
||||
|
||||
/*static struct CallerData
|
||||
{
|
||||
uint id;
|
||||
//bool
|
||||
}*/
|
||||
|
||||
/*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0
|
||||
.. system_callers.length];*/
|
||||
|
||||
foreach(uint i,caller;system_callers)caller.job_group.id = i;
|
||||
|
||||
int priority = int.min;
|
||||
uint beg = 0;
|
||||
index = 0;
|
||||
foreach(uint i,caller;system_callers)
|
||||
{
|
||||
/*
|
||||
if(priority == int.min)priority = caller.system.priority;
|
||||
if(priority != caller.system.priority)
|
||||
/*static struct CallerData
|
||||
{
|
||||
foreach(caller2;system_callers[beg..i])
|
||||
{
|
||||
|
||||
}
|
||||
priority = caller.system.priority;
|
||||
beg = i;
|
||||
uint id;
|
||||
//bool
|
||||
}*/
|
||||
|
||||
/*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0
|
||||
.. pass.system_callers.length];*/
|
||||
|
||||
foreach (uint i, caller; pass.system_callers)
|
||||
caller.job_group.id = i;
|
||||
|
||||
int priority = int.min;
|
||||
uint beg = 0;
|
||||
index = 0;
|
||||
foreach(ex;caller.exclusion)
|
||||
foreach (uint i, caller; pass.system_callers)
|
||||
{
|
||||
if(ex.job_group.id > caller.job_group.id)continue;
|
||||
|
||||
exclusion[index++] = ex;
|
||||
}
|
||||
|
||||
if(index > 0)
|
||||
{
|
||||
caller.dependencies = Mallocator.instance.makeArray(exclusion[0..index]);
|
||||
caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index);
|
||||
|
||||
foreach(j,dep;caller.dependencies)
|
||||
/*
|
||||
if(priority == int.min)priority = caller.system.priority;
|
||||
if(priority != caller.system.priority)
|
||||
{
|
||||
caller.job_group.dependencies[j] = &dep.job_group;
|
||||
}
|
||||
}
|
||||
else caller.dependencies = null;
|
||||
foreach(caller2;pass.system_callers[beg..i])
|
||||
{
|
||||
|
||||
}
|
||||
priority = caller.system.priority;
|
||||
beg = i;
|
||||
}*/
|
||||
index = 0;
|
||||
foreach (ex; caller.exclusion)
|
||||
{
|
||||
if (ex.job_group.id > caller.job_group.id)
|
||||
continue;
|
||||
|
||||
/*import std.stdio;
|
||||
write("Dependencies for system ", caller.system.name, ": ");
|
||||
foreach (ex; caller.dependencies)
|
||||
write(ex.system.name, " ");
|
||||
writeln();*/
|
||||
exclusion[index++] = ex;
|
||||
}
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
caller.dependencies = Mallocator.instance.makeArray(exclusion[0 .. index]);
|
||||
caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index);
|
||||
|
||||
foreach (j, dep; caller.dependencies)
|
||||
{
|
||||
caller.job_group.dependencies[j] = &dep.job_group;
|
||||
}
|
||||
}
|
||||
else
|
||||
caller.dependencies = null;
|
||||
|
||||
/*import std.stdio;
|
||||
write("Dependencies for system ", caller.system.name, ": ");
|
||||
foreach (ex; caller.dependencies)
|
||||
write(ex.system.name, " ");
|
||||
writeln();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1963,11 +2010,24 @@ class EntityManager
|
|||
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;
|
||||
|
||||
ThreadData[] threads;
|
||||
|
||||
Vector!(SystemCaller*) system_callers;
|
||||
Vector!(UpdatePass*) passes;
|
||||
|
||||
//Vector!(SystemCaller*) system_callers;
|
||||
|
||||
alias SytemFuncType = void function(ref EntityManager.CallData data);
|
||||
|
||||
|
|
@ -1981,7 +2041,7 @@ class EntityManager
|
|||
enum pages_in_block = 128;
|
||||
|
||||
IDManager id_manager;
|
||||
BlockAllocator!(page_size, pages_in_block) allocator;
|
||||
BlockAllocator/*!(page_size, pages_in_block)*/ allocator;
|
||||
|
||||
//EventManager event_manager;
|
||||
mixin EventManagerCode;
|
||||
|
|
@ -1995,13 +2055,14 @@ class EntityManager
|
|||
|
||||
HashMap!(ushort[], EntityInfo*) entities_infos;
|
||||
HashMap!(const(char)[], ushort) systems_map;
|
||||
HashMap!(string, ushort) components_map;
|
||||
HashMap!(string, ushort) events_map;
|
||||
HashMap!(const(char)[], ushort) components_map;
|
||||
HashMap!(const(char)[], ushort) events_map;
|
||||
HashMap!(const(char)[], ushort) passes_map;
|
||||
Vector!System systems;
|
||||
Vector!ComponentInfo components;
|
||||
Vector!EventInfo events;
|
||||
|
||||
Mutex add_mutex;
|
||||
//Mutex add_mutex;
|
||||
Mutex entity_block_alloc_mutex;
|
||||
|
||||
CallDataAllocator m_call_data_allocator;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ package:
|
|||
int m_priority;
|
||||
///pointer to system implementation
|
||||
void* m_system_pointer;
|
||||
///system pass index
|
||||
int m_pass;
|
||||
|
||||
///system name
|
||||
const (char)[] name;
|
||||
|
|
@ -66,7 +68,7 @@ package:
|
|||
|
||||
EntityManager.Job[] jobs;
|
||||
|
||||
System*[] m_dependencies;
|
||||
//System*[] m_dependencies;
|
||||
ushort[] m_read_only_components;
|
||||
ushort[] m_modified_components;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue