Browse Source

working on something new

tags/Rel1
sebas77 7 years ago
parent
commit
a2f1f384fa
15 changed files with 465 additions and 285 deletions
  1. +24
    -9
      DataStructures/FasterList.cs
  2. +16
    -16
      DataStructures/Priority Queue/HeapPriorityQueue.cs
  3. +112
    -135
      DataStructures/ThreadSafeDictionary.cs
  4. +39
    -15
      ECS/EngineNodeDB.cs
  5. +97
    -82
      ECS/EnginesRoot.cs
  6. +22
    -6
      ECS/EntityDescriptor.cs
  7. +19
    -1
      ECS/IEngine.cs
  8. +2
    -0
      ECS/IEngineNodeDB.cs
  9. +66
    -0
      ECS/NodeEngineWrapper.cs
  10. +9
    -0
      ECS/NodeSubmissionScheduler.cs
  11. +1
    -1
      ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs
  12. +2
    -2
      ECS/Profiler/EngineProfiler.cs
  13. +3
    -3
      ECS/SingleNodeEngine.cs
  14. +38
    -0
      Extensions/Unity/UnitySumbmissionNodeScheduler.cs
  15. +15
    -15
      Utilities/DesignByContract.cs

+ 24
- 9
DataStructures/FasterList.cs View File

@@ -193,7 +193,8 @@ namespace Svelto.DataStructures
{
public FasterListThreadSafe(FasterList<T> list)
{
_list = list;
if (list == null) throw new ArgumentException("invalid list");
_list = list;
_lockQ = new ReaderWriterLockSlim();
}

@@ -288,14 +289,14 @@ namespace Svelto.DataStructures

public void CopyTo(T[] array, int arrayIndex)
{
_lockQ.EnterWriteLock();
_lockQ.EnterReadLock();
try
{
_list.CopyTo(array, arrayIndex);
}
finally
{
_lockQ.ExitWriteLock();
_lockQ.ExitReadLock();
}
}

@@ -351,6 +352,19 @@ namespace Svelto.DataStructures
}
}

public void UnorderredRemoveAt(int index)
{
_lockQ.EnterWriteLock();
try
{
_list.UnorderredRemoveAt(index);
}
finally
{
_lockQ.ExitWriteLock();
}
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
throw new NotImplementedException();
@@ -368,8 +382,6 @@ namespace Svelto.DataStructures

public struct FasterReadOnlyListCast<T, U> : IList<U> where U:T
{
public static FasterList<T> DefaultList = new FasterList<T>();

public int Count { get { return _list.Count; } }
public bool IsReadOnly { get { return true; } }

@@ -402,7 +414,7 @@ namespace Svelto.DataStructures

public void CopyTo(U[] array, int arrayIndex)
{
throw new NotImplementedException();
Array.Copy(_list.ToArrayFast(), 0, array, arrayIndex, _list.Count);
}

public bool Remove(U item)
@@ -440,6 +452,8 @@ namespace Svelto.DataStructures

public class FasterList<T> : IList<T>
{
public static FasterList<T> DefaultList = new FasterList<T>();

const int MIN_SIZE = 4;

public int Count
@@ -752,14 +766,15 @@ namespace Svelto.DataStructures
Resize(_count);
}

public bool Reuse(int index, out T result)
public bool Reuse<U>(int index, out U result)
where U:class, T
{
result = default(T);
result = default(U);

if (index >= _buffer.Length)
return false;

result = _buffer[index];
result = (U)_buffer[index];

return result != null;
}


+ 16
- 16
DataStructures/Priority Queue/HeapPriorityQueue.cs View File

@@ -13,9 +13,9 @@ namespace Svelto.DataStructures
public sealed class HeapPriorityQueue<T> : IPriorityQueue<T>
where T : PriorityQueueNode
{
private int _numNodes;
private readonly FasterList<T> _nodes;
private long _numNodesEverEnqueued;
int _numNodes;
private readonly FasterList<T> _nodes;
long _numNodesEverEnqueued;

/// <summary>
/// Instantiate a new Priority Queue
@@ -101,10 +101,10 @@ namespace Svelto.DataStructures
CascadeUp(_nodes[_numNodes]);
}

#if NET_VERSION_4_5
#if NET_VERSION_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private void Swap(T node1, T node2)
#endif
void Swap(T node1, T node2)
{
//Swap the nodes
_nodes[node1.QueueIndex] = node2;
@@ -117,14 +117,14 @@ namespace Svelto.DataStructures
}

//Performance appears to be slightly better when this is NOT inlined o_O
private void CascadeUp(T node)
void CascadeUp(T node)
{
//aka Heapify-up
int parent = node.QueueIndex / 2;
while(parent >= 1)
while (parent >= 1)
{
T parentNode = _nodes[parent];
if(HasHigherPriority(parentNode, node))
if (HasHigherPriority(parentNode, node))
break;

//Node has lower priority value, so move it up the heap
@@ -134,9 +134,9 @@ namespace Svelto.DataStructures
}
}

#if NET_VERSION_4_5
#if NET_VERSION_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
#endif
private void CascadeDown(T node)
{
//aka Heapify-down
@@ -198,10 +198,10 @@ namespace Svelto.DataStructures
/// Returns true if 'higher' has higher priority than 'lower', false otherwise.
/// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
/// </summary>
#if NET_VERSION_4_5
#if NET_VERSION_4_5
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private bool HasHigherPriority(T higher, T lower)
#endif
bool HasHigherPriority(T higher, T lower)
{
return (higher.Priority < lower.Priority ||
(higher.Priority == lower.Priority && higher.InsertionIndex < lower.InsertionIndex));
@@ -242,13 +242,13 @@ namespace Svelto.DataStructures
OnNodeUpdated(node);
}

private void OnNodeUpdated(T node)
void OnNodeUpdated(T node)
{
//Bubble the updated node up or down as appropriate
int parentIndex = node.QueueIndex / 2;
T parentNode = _nodes[parentIndex];

if(parentIndex > 0 && HasHigherPriority(node, parentNode))
if (parentIndex > 0 && HasHigherPriority(node, parentNode))
{
CascadeUp(node);
}


+ 112
- 135
DataStructures/ThreadSafeDictionary.cs View File

@@ -31,10 +31,15 @@ namespace Svelto.DataStructures
{
get
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict.Count;
}
finally
{
LockQ.ExitReadLock();
}
}
}

@@ -42,10 +47,15 @@ namespace Svelto.DataStructures
{
get
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict.IsReadOnly;
}
finally
{
LockQ.ExitReadLock();
}
}
}

@@ -53,10 +63,15 @@ namespace Svelto.DataStructures
{
get
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return new FasterList<TKey>(dict.Keys);
}
finally
{
LockQ.ExitReadLock();
}
}
}

@@ -64,10 +79,15 @@ namespace Svelto.DataStructures
{
get
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return new FasterList<TValue>(dict.Values);
}
finally
{
LockQ.ExitReadLock();
}
}
}

@@ -75,91 +95,146 @@ namespace Svelto.DataStructures
{
get
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict[key];
}
finally
{
LockQ.ExitReadLock();
}
}

set
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
dict[key] = value;
}
finally
{
LockQ.ExitWriteLock();
}
}
}

public virtual void Add(KeyValuePair<TKey, TValue> item)
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
dict.Add(item);
}
finally
{
LockQ.ExitWriteLock();
}
}

public virtual void Clear()
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
dict.Clear();
}
finally
{
LockQ.ExitWriteLock();
}
}

public virtual bool Contains(KeyValuePair<TKey, TValue> item)
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict.Contains(item);
}
finally
{
LockQ.ExitReadLock();
}
}

public virtual void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
dict.CopyTo(array, arrayIndex);
}
finally
{
LockQ.ExitReadLock();
}
}

public virtual bool Remove(KeyValuePair<TKey, TValue> item)
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
return dict.Remove(item);
}
finally
{
LockQ.ExitWriteLock();
}
}

public virtual void Add(TKey key, TValue value)
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
dict.Add(key, value);
}
finally
{
LockQ.ExitWriteLock();
}
}

public virtual bool ContainsKey(TKey key)
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict.ContainsKey(key);
}
finally
{
LockQ.ExitReadLock();
}
}

public virtual bool Remove(TKey key)
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
return dict.Remove(key);
}
finally
{
LockQ.ExitWriteLock();
}
}

public virtual bool TryGetValue(TKey key, out TValue value)
{
using (new ReadOnlyLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
return dict.TryGetValue(key, out value);
}
finally
{
LockQ.ExitReadLock();
}
}

/// <summary>
@@ -169,7 +244,8 @@ namespace Svelto.DataStructures
/// <param name = "newValue">New Value</param>
public void MergeSafe(TKey key, TValue newValue)
{
using (new WriteLock(dictionaryLock))
LockQ.EnterWriteLock();
try
{
// take a writelock immediately since we will always be writing
if (dict.ContainsKey(key))
@@ -177,6 +253,10 @@ namespace Svelto.DataStructures

dict.Add(key, newValue);
}
finally
{
LockQ.ExitWriteLock();
}
}

/// <summary>
@@ -185,132 +265,29 @@ namespace Svelto.DataStructures
/// <param name = "key">Key to remove</param>
public void RemoveSafe(TKey key)
{
using (new ReadLock(dictionaryLock))
LockQ.EnterReadLock();
try
{
if (dict.ContainsKey(key))
using (new WriteLock(dictionaryLock))
{
dict.Remove(key);
}
LockQ.EnterWriteLock();
try
{
dict.Remove(key);
}
finally
{
LockQ.ExitWriteLock();
}
}
finally
{
LockQ.ExitReadLock();
}
}

// This is the internal dictionary that we are wrapping
readonly IDictionary<TKey, TValue> dict;

[NonSerialized] readonly ReaderWriterLockSlim dictionaryLock = Locks.GetLockInstance(LockRecursionPolicy.NoRecursion);
}

public static class Locks
{
public static ReaderWriterLockSlim GetLockInstance()
{
return GetLockInstance(LockRecursionPolicy.SupportsRecursion);
}

public static ReaderWriterLockSlim GetLockInstance(LockRecursionPolicy recursionPolicy)
{
return new ReaderWriterLockSlim(recursionPolicy);
}

public static void GetReadLock(ReaderWriterLockSlim locks)
{
var lockAcquired = false;
while (!lockAcquired)
lockAcquired = locks.TryEnterUpgradeableReadLock(1);
}

public static void GetReadOnlyLock(ReaderWriterLockSlim locks)
{
var lockAcquired = false;
while (!lockAcquired)
lockAcquired = locks.TryEnterReadLock(1);
}

public static void GetWriteLock(ReaderWriterLockSlim locks)
{
var lockAcquired = false;
while (!lockAcquired)
lockAcquired = locks.TryEnterWriteLock(1);
}

public static void ReleaseLock(ReaderWriterLockSlim locks)
{
ReleaseWriteLock(locks);
ReleaseReadLock(locks);
ReleaseReadOnlyLock(locks);
}

public static void ReleaseReadLock(ReaderWriterLockSlim locks)
{
if (locks.IsUpgradeableReadLockHeld)
locks.ExitUpgradeableReadLock();
}

public static void ReleaseReadOnlyLock(ReaderWriterLockSlim locks)
{
if (locks.IsReadLockHeld)
locks.ExitReadLock();
}

public static void ReleaseWriteLock(ReaderWriterLockSlim locks)
{
if (locks.IsWriteLockHeld)
locks.ExitWriteLock();
}
}

public abstract class BaseLock : IDisposable
{
protected ReaderWriterLockSlim _Locks;

public BaseLock(ReaderWriterLockSlim locks)
{
_Locks = locks;
}

public abstract void Dispose();
}

public class ReadLock : BaseLock
{
public ReadLock(ReaderWriterLockSlim locks)
: base(locks)
{
Locks.GetReadLock(_Locks);
}

public override void Dispose()
{
Locks.ReleaseReadLock(_Locks);
}
}

public class ReadOnlyLock : BaseLock
{
public ReadOnlyLock(ReaderWriterLockSlim locks)
: base(locks)
{
Locks.GetReadOnlyLock(_Locks);
}

public override void Dispose()
{
Locks.ReleaseReadOnlyLock(_Locks);
}
}

public class WriteLock : BaseLock
{
public WriteLock(ReaderWriterLockSlim locks)
: base(locks)
{
Locks.GetWriteLock(_Locks);
}

public override void Dispose()
{
Locks.ReleaseWriteLock(_Locks);
}
readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim();
}
}

+ 39
- 15
ECS/EngineNodeDB.cs View File

@@ -10,29 +10,39 @@ namespace Svelto.ECS
Dictionary<Type, Dictionary<int, INode>> nodesDBdic,
Dictionary<Type, FasterList<INode>> nodesDBgroups)
{
_nodesDB = nodesDB;
_nodesDBdic = nodesDBdic;
_nodesDBgroups = nodesDBgroups;
_nodesDB = new DataStructures.WeakReference<Dictionary<Type, FasterList<INode>>>(nodesDB);
_nodesDBdic = new DataStructures.WeakReference<Dictionary<Type, Dictionary<int, INode>>>(nodesDBdic);
_nodesDBgroups = new DataStructures.WeakReference<Dictionary<Type, FasterList<INode>>>(nodesDBgroups);
}

public FasterReadOnlyListCast<INode, T> QueryNodes<T>() where T:INode
{
var type = typeof(T);

if (_nodesDB.ContainsKey(type) == false)
if (_nodesDB.IsValid == false || _nodesDB.Target.ContainsKey(type) == false)
return RetrieveEmptyNodeList<T>();

return new FasterReadOnlyListCast<INode, T>(_nodesDB[type]);
return new FasterReadOnlyListCast<INode, T>(_nodesDB.Target[type]);
}

/* public FasterReadOnlyList<T> QueryStructNodes<T>() where T:struct
{
var type = typeof(T);

if (_nodesDBStructs.ContainsKey(type) == false)
return RetrieveEmptyStructNodeList<T>();

return new FasterReadOnlyList<T>(((StructNodeList<T>)(_nodesDBStructs[type])).list);
}*/

public ReadOnlyDictionary<int, INode> QueryIndexableNodes<T>() where T:INode
{
var type = typeof(T);

if (_nodesDBdic.ContainsKey(type) == false)
if (_nodesDB.IsValid == false || _nodesDBdic.Target.ContainsKey(type) == false)
return _defaultEmptyNodeDict;

return new ReadOnlyDictionary<int, INode>(_nodesDBdic[type]);
return new ReadOnlyDictionary<int, INode>(_nodesDBdic.Target[type]);
}

public T QueryNodeFromGroup<T>(int groupID) where T : INode
@@ -49,10 +59,10 @@ namespace Svelto.ECS
{
var type = typeof(T);

if (_nodesDBgroups.ContainsKey(type) == false)
if (_nodesDBgroups.IsValid == false || _nodesDBgroups.Target.ContainsKey(type) == false)
return RetrieveEmptyNodeList<T>();

return new FasterReadOnlyListCast<INode, T>(_nodesDBgroups[type]);
return new FasterReadOnlyListCast<INode, T>(_nodesDBgroups.Target[type]);
}

public bool QueryNode<T>(int ID, out T node) where T:INode
@@ -61,7 +71,7 @@ namespace Svelto.ECS

INode internalNode;

if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode))
if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode))
{
node = (T)internalNode;

@@ -79,7 +89,7 @@ namespace Svelto.ECS

INode internalNode;

if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode))
if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode))
return (T)internalNode;

throw new Exception("Node Not Found");
@@ -87,17 +97,31 @@ namespace Svelto.ECS

static FasterReadOnlyListCast<INode, T> RetrieveEmptyNodeList<T>() where T : INode
{
return new FasterReadOnlyListCast<INode, T>(FasterReadOnlyListCast<INode, T>.DefaultList);
return new FasterReadOnlyListCast<INode, T>(FasterList<INode>.DefaultList);
}

static FasterReadOnlyList<T> RetrieveEmptyStructNodeList<T>() where T : struct
{
return new FasterReadOnlyList<T>(FasterList<T>.DefaultList);
}

Dictionary<Type, FasterList<INode>> _nodesDB;
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;
Dictionary<Type, FasterList<INode>> _nodesDBgroups;
Svelto.DataStructures.WeakReference<Dictionary<Type, FasterList<INode>>> _nodesDB;
Svelto.DataStructures.WeakReference<Dictionary<Type, Dictionary<int, INode>>> _nodesDBdic;
Svelto.DataStructures.WeakReference<Dictionary<Type, FasterList<INode>>> _nodesDBgroups;
// Dictionary<Type, StructNodeList> _nodesDBStructs;

//Dictionary<Type, ThreadSafeFasterList<INode>> _nodesDB;
//Dictionary<Type, ThreadsSafeDictionary<int, INode>> _nodesDBdic;
// Dictionary<Type, ThreadSafeFasterList<INode>> _nodesDBgroups;

ReadOnlyDictionary<int, INode> _defaultEmptyNodeDict = new ReadOnlyDictionary<int, INode>(new Dictionary<int, INode>());

class StructNodeList
{ }

class StructNodeList<T> : StructNodeList where T : struct
{
public FasterList<T> list = new FasterList<T>();
}
}
}

+ 97
- 82
ECS/EnginesRoot.cs View File

@@ -4,7 +4,8 @@ using System.Collections.Generic;
using Svelto.DataStructures;
using UnityEngine;
using WeakReference = Svelto.DataStructures.WeakReference<Svelto.ECS.EnginesRoot>;

using Svelto.ECS.NodeSchedulers;
using Svelto.ECS.Internal;
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
#endif
@@ -14,26 +15,11 @@ using System.Reflection;

namespace Svelto.ECS
{
class Scheduler : MonoBehaviour
{
IEnumerator Start()
{
while (true)
{
yield return new WaitForEndOfFrame();

OnTick();
}
}

internal Action OnTick;
}

public sealed class EnginesRoot : IEnginesRoot, IEntityFactory
{
public EnginesRoot()
public EnginesRoot(NodeSubmissionScheduler nodeScheduler)
{
_nodeEngines = new Dictionary<Type, FasterList<INodeEngine<INode>>>();
_nodeEngines = new Dictionary<Type, FasterList<INodeEngine>>();
_engineRootWeakReference = new WeakReference(this);
_otherEnginesReferences = new FasterList<IEngine>();

@@ -45,9 +31,8 @@ namespace Svelto.ECS

_nodesDBgroups = new Dictionary<Type, FasterList<INode>>();

GameObject go = new GameObject("ECSScheduler");

go.AddComponent<Scheduler>().OnTick += SubmitNodes;
_scheduler = nodeScheduler;
_scheduler.Schedule(SubmitNodes);

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
GameObject debugEngineObject = new GameObject("Engine Debugger");
@@ -109,6 +94,28 @@ namespace Svelto.ECS
_groupNodesToAdd.Clear();
}

public void AddEngine<T>(INodeEngine<T> engine) where T:class, INode
{
AddEngine(new NodeEngineWrapper<T>(engine));

if (engine is IQueryableNodeEngine)
(engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic, _nodesDBgroups);
}

public void AddEngine<T, U>(INodeEngine<T, U> engine) where T:class, INode where U:class, INode
{
AddEngine(new NodeEngineWrapper<T, U>(engine));
AddEngine((INodeEngine<U>)(engine));
}

public void AddEngine<T, U, V>(INodeEngine<T, U, V> engine) where T:class, INode
where U:class, INode
where V:class, INode
{
AddEngine(new NodeEngineWrapper<T, U, V>(engine));
AddEngine((INodeEngine<U, V>)(engine));
}

public void AddEngine(IEngine engine)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
@@ -125,9 +132,7 @@ namespace Svelto.ECS
}
else
{

var engineType = engine.GetType();
// Type baseInterface = null;

#if !NETFX_CORE
var baseType = engineType.BaseType;
@@ -138,12 +143,28 @@ namespace Svelto.ECS

if (baseType.IsConstructedGenericType
#endif
&& baseType.GetGenericTypeDefinition() == typeof (SingleNodeEngine<>))
&& baseType.GetGenericTypeDefinition() == typeof(SingleNodeEngine<>))
{
AddEngine(engine as INodeEngine<INode>, baseType.GetGenericArguments(), _nodeEngines);
AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines);
}
else
_otherEnginesReferences.Add(engine);
{
bool found = false;

for (int i = 0, maxLength = engineType.GetInterfaces().Length; i < maxLength; i++)
{
var type = engineType.GetInterfaces()[i];
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(INodeEngine<>))
{
AddEngine(engine as INodeEngine, type.GetGenericArguments(), _nodeEngines);

found = true;
}
}

if (found == false)
_otherEnginesReferences.Add(engine);
}
}
if (engine is ICallBackOnAddEngine)
@@ -152,10 +173,10 @@ namespace Svelto.ECS

public void BuildEntity(int ID, EntityDescriptor ed)
{
var entityNodes = ed.BuildNodes(ID, (node) =>
var entityNodes = ed.BuildNodes(ID, (nodes) =>
{
if (_engineRootWeakReference.IsValid == true)
InternalRemove(node);
InternalRemove(nodes);
});
_nodesToAdd.AddRange(entityNodes);
@@ -176,26 +197,26 @@ namespace Svelto.ECS
/// <param name="ed"></param>
public void BuildEntityGroup(int groupID, EntityDescriptor ed)
{
var entityNodes = ed.BuildNodes(groupID, (node) =>
var entityNodes = ed.BuildNodes(groupID, (nodes) =>
{
if (_engineRootWeakReference.IsValid == true)
InternalGroupRemove(node);
InternalGroupRemove(nodes);
});

_groupNodesToAdd.AddRange(entityNodes);
}

static void AddEngine<T>(T engine, Type[] types, Dictionary<Type, FasterList<INodeEngine<INode>>> engines) where T : INodeEngine<INode>
static void AddEngine(INodeEngine engine, Type[] types, Dictionary<Type, FasterList<INodeEngine>> engines)
{
for (int i = 0; i < types.Length; i++)
{
FasterList<INodeEngine<INode>> list;
FasterList<INodeEngine> list;

var type = types[i];

if (engines.TryGetValue(type, out list) == false)
{
list = new FasterList<INodeEngine<INode>>();
list = new FasterList<INodeEngine>();

engines.Add(type, list);
}
@@ -215,7 +236,7 @@ namespace Svelto.ECS
AddNodeToNodesDictionary(node, nodeType);
}

void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode
void AddNodeToTheDB(INode node, Type nodeType)
{
FasterList<INode> nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == false)
@@ -226,7 +247,7 @@ namespace Svelto.ECS
AddNodeToNodesDictionary(node, nodeType);
}

void AddNodeToNodesDictionary<T>(T node, Type nodeType) where T : INode
void AddNodeToNodesDictionary(INode node, Type nodeType)
{
if (node is NodeWithID)
{
@@ -238,9 +259,9 @@ namespace Svelto.ECS
}
}

void AddNodeToTheSuitableEngines<T>(T node, Type nodeType) where T : INode
void AddNodeToTheSuitableEngines(INode node, Type nodeType)
{
FasterList<INodeEngine<INode>> enginesForNode;
FasterList<INodeEngine> enginesForNode;

if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
{
@@ -255,91 +276,85 @@ namespace Svelto.ECS
}
}

void RemoveNodeFromTheDB<T>(T node, Type nodeType) where T : INode
{
FasterList<INode> nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero?

RemoveNodeFromNodesDictionary(node, nodeType);
}

void RemoveNodeFromNodesDictionary<T>(T node, Type nodeType) where T : INode
void RemoveNodesFromDB(Dictionary<Type, FasterList<INode>> DB, FasterReadOnlyList<INode> nodes)
{
if (node is NodeWithID)
for (int i = 0; i < nodes.Count; i++)
{
Dictionary<int, INode> nodesDic;
FasterList<INode> nodesInDB;

if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
nodesDic.Remove((node as NodeWithID).ID);
}
}
var node = nodes[i];
var nodeType = node.GetType();
if (DB.TryGetValue(nodeType, out nodesInDB) == true)
nodesInDB.UnorderredRemove(node); //should I remove it from the dictionary if length is zero?

void RemoveNodeFromGroupDB<T>(T node, Type nodeType) where T : INode
{
FasterList<INode> nodes;
if (_nodesDBgroups.TryGetValue(nodeType, out nodes) == true)
nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero?
if (node is NodeWithID)
{
Dictionary<int, INode> nodesDic;

RemoveNodeFromNodesDictionary(node, nodeType);
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
nodesDic.Remove((node as NodeWithID).ID);
}
}
}

void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode
void RemoveNodesFromEngines(FasterReadOnlyList<INode> nodes)
{
FasterList<INodeEngine<INode>> enginesForNode;

if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
for (int i = 0; i < nodes.Count; i++)
{
for (int j = 0; j < enginesForNode.Count; j++)
FasterList<INodeEngine> enginesForNode;
var node = nodes[i];

if (_nodeEngines.TryGetValue(node.GetType(), out enginesForNode))
{
for (int j = 0; j < enginesForNode.Count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node);
EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node);
#else
enginesForNode[j].Remove(node);
enginesForNode[j].Remove(node);
#endif
}
}
}
}
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
void AddNodeToEngine(INodeEngine<INode> engine, INode node)
static void AddNodeToEngine(INodeEngine engine, INode node)
{
engine.Add(node);
}

void RemoveNodeFromEngine(INodeEngine<INode> engine, INode node)
static void RemoveNodeFromEngine(INodeEngine engine, INode node)
{
engine.Remove(node);
}
#endif
void InternalRemove<T>(T node) where T : INode
{
Type nodeType = node.GetType();

RemoveNodeFromEngines(node, nodeType);
RemoveNodeFromTheDB(node, node.GetType());
void InternalRemove(FasterReadOnlyList<INode> nodes)
{
RemoveNodesFromEngines(nodes);
RemoveNodesFromDB(_nodesDB, nodes);
}

void InternalGroupRemove<T>(T node) where T : INode
void InternalGroupRemove(FasterReadOnlyList<INode> nodes)
{
Type nodeType = node.GetType();

RemoveNodeFromEngines(node, nodeType);
RemoveNodeFromGroupDB(node, node.GetType());
RemoveNodesFromEngines(nodes);
RemoveNodesFromDB(_nodesDBgroups, nodes);
}

Dictionary<Type, FasterList<INodeEngine<INode>>> _nodeEngines;
Dictionary<Type, FasterList<INodeEngine>> _nodeEngines;
FasterList<IEngine> _otherEnginesReferences;

Dictionary<Type, FasterList<INode>> _nodesDB;
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;

Dictionary<Type, FasterList<INode>> _nodesDBgroups;

Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;

FasterList<INode> _nodesToAdd;
FasterList<INode> _groupNodesToAdd;

WeakReference _engineRootWeakReference;
NodeSubmissionScheduler _scheduler;
}
}


+ 22
- 6
ECS/EntityDescriptor.cs View File

@@ -15,6 +15,11 @@ namespace Svelto.ECS
_nodesToBuild = nodesToBuild;
}

/* protected EntityDescriptor(IStructNodeBuilder[] structNodesToBuild)
{
_structNodesToBuild = structNodesToBuild;
}*/

public void AddImplementors(params object[] componentsImplementor)
{
var implementors = new object[componentsImplementor.Length + _implementors.Length];
@@ -25,23 +30,22 @@ namespace Svelto.ECS
_implementors = implementors;
}

public virtual FasterList<INode> BuildNodes(int ID, Action<INode> removeAction)
public virtual FasterList<INode> BuildNodes(int ID, Action<FasterReadOnlyList<INode>> removeAction)
{
var nodes = new FasterList<INode>();

for (int index = 0; index < _nodesToBuild.Length; index++)
for (int index = _nodesToBuild.Length - 1; index >= 0; index--)
{
var nodeBuilder = _nodesToBuild[index];
var node = FillNode(nodeBuilder.Build(ID), () =>
{
for (int i = 0; i < nodes.Count; i++)
removeAction(nodes[i]);
removeAction(new FasterReadOnlyList<INode>());

nodes.Clear();
}
);

nodes.Add (node);
nodes.Add(node);
}

return nodes;
@@ -88,7 +92,8 @@ namespace Svelto.ECS

object[] _implementors;

readonly INodeBuilder[] _nodesToBuild;
readonly INodeBuilder[] _nodesToBuild;
// readonly IStructNodeBuilder[] _structNodesToBuild;
}

public interface INodeBuilder
@@ -105,4 +110,15 @@ namespace Svelto.ECS
return (NodeType)node;
}
}
/*
public interface IStructNodeBuilder
{}

public class StructNodeBuilder<NodeType> : IStructNodeBuilder where NodeType : struct
{
public NodeType Build()
{
return new NodeType();
}
}*/
}

+ 19
- 1
ECS/IEngine.cs View File

@@ -9,7 +9,25 @@ namespace Svelto.ECS
void Remove(TNodeType obj);
}

public interface INodesEngine : INodeEngine<INode>
public interface INodeEngine<in T, in U>:INodeEngine<U> where T:INode where U:INode
{
void Add(T obj);
void Remove(T obj);
}

public interface INodeEngine<in T, in U, in V>:INodeEngine<U, V> where T:INode where U:INode where V:INode
{
void Add(T obj);
void Remove(T obj);
}

public interface INodeEngine:IEngine
{
void Add(INode obj);
void Remove(INode obj);
}

public interface INodesEngine : INodeEngine
{
System.Type[] AcceptedNodes();
}


+ 2
- 0
ECS/IEngineNodeDB.cs View File

@@ -11,6 +11,8 @@ namespace Svelto.ECS
FasterReadOnlyListCast<INode, T> QueryNodes<T>() where T:INode;

// FasterReadOnlyList<T> QueryStructNodes<T>() where T : struct;

bool QueryNodeFromGroup<T>(int ID, out T node) where T : INode;
T QueryNodeFromGroup<T>(int ID) where T : INode;
FasterReadOnlyListCast<INode, T> QueryNodesFromGroups<T>() where T : INode;


+ 66
- 0
ECS/NodeEngineWrapper.cs View File

@@ -0,0 +1,66 @@
using System;

namespace Svelto.ECS.Internal
{
class NodeEngineWrapper<T> : SingleNodeEngine<T> where T : class, INode
{
INodeEngine<T> engine;

public NodeEngineWrapper(INodeEngine<T> engine)
{
this.engine = engine;
}

protected override void Add(T node)
{
engine.Add((T)node);
}

protected override void Remove(T node)
{
engine.Remove((T)node);
}
}

class NodeEngineWrapper<T, U>: SingleNodeEngine<T> where T : class, INode where U : class, INode
{
INodeEngine<T, U> engine;

public NodeEngineWrapper(INodeEngine<T, U> engine)
{
this.engine = engine;
}

protected override void Add(T node)
{
engine.Add((T)node);
}

protected override void Remove(T node)
{
engine.Remove((T)node);
}
}

class NodeEngineWrapper<T, U, V>: SingleNodeEngine<T> where T : class, INode
where U : class, INode
where V : class, INode
{
INodeEngine<T, U, V> engine;

public NodeEngineWrapper(INodeEngine<T, U, V> engine)
{
this.engine = engine;
}

protected override void Add(T node)
{
engine.Add((T)node);
}

protected override void Remove(T node)
{
engine.Remove((T)node);
}
}
}

+ 9
- 0
ECS/NodeSubmissionScheduler.cs View File

@@ -0,0 +1,9 @@
using System;

namespace Svelto.ECS.NodeSchedulers
{
public abstract class NodeSubmissionScheduler
{
abstract public void Schedule(Action submitNodes);
}
}

+ 1
- 1
ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs View File

@@ -5,7 +5,7 @@ using UnityEditor;

namespace Svelto.ECS.Profiler
{
internal class EngineProfilerMenuItem
class EngineProfilerMenuItem
{
[MenuItem("Engines/Enable Profiler")]
public static void EnableProfiler()


+ 2
- 2
ECS/Profiler/EngineProfiler.cs View File

@@ -11,7 +11,7 @@ namespace Svelto.ECS.Profiler
{
static readonly Stopwatch _stopwatch = new Stopwatch();

public static void MonitorAddDuration(Action<INodeEngine<INode>, INode> addingFunc, INodeEngine<INode> engine, INode node)
public static void MonitorAddDuration(Action<INodeEngine, INode> addingFunc, INodeEngine engine, INode node)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))
@@ -25,7 +25,7 @@ namespace Svelto.ECS.Profiler
}
}

public static void MonitorRemoveDuration(Action<INodeEngine<INode>, INode> removeFunc, INodeEngine<INode> engine, INode node)
public static void MonitorRemoveDuration(Action<INodeEngine, INode> removeFunc, INodeEngine engine, INode node)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))


+ 3
- 3
ECS/SingleNodeEngine.cs View File

@@ -1,13 +1,13 @@
namespace Svelto.ECS
{
public abstract class SingleNodeEngine<TNodeType> : INodeEngine<INode> where TNodeType : class, INode
public abstract class SingleNodeEngine<TNodeType> : INodeEngine where TNodeType : class, INode
{
void INodeEngine<INode>.Add(INode obj)
void INodeEngine.Add(INode obj)
{
Add(obj as TNodeType);
}

void INodeEngine<INode>.Remove(INode obj)
void INodeEngine.Remove(INode obj)
{
Remove(obj as TNodeType);
}


+ 38
- 0
Extensions/Unity/UnitySumbmissionNodeScheduler.cs View File

@@ -0,0 +1,38 @@
using System;
using System.Collections;
using UnityEngine;

namespace Svelto.ECS.NodeSchedulers
{
public class UnitySumbmissionNodeScheduler : NodeSubmissionScheduler
{
public UnitySumbmissionNodeScheduler()
{
GameObject go = new GameObject("ECSScheduler");

_scheduler = go.AddComponent<Scheduler>();
}

public override void Schedule(Action submitNodes)
{
_scheduler.OnTick += submitNodes;
}

class Scheduler : MonoBehaviour
{
IEnumerator Start()
{
while (true)
{
yield return new WaitForEndOfFrame();

OnTick();
}
}

internal Action OnTick;
}

Scheduler _scheduler;
}
}

+ 15
- 15
Utilities/DesignByContract.cs View File

@@ -324,18 +324,18 @@ namespace DesignByContract
useAssertions = value;
}
}
#endregion // Interface

#region Implementation
#endregion // Interface

// No creation
private Check() {}
#region Implementation

/// <summary>
/// Is exception handling being used?
/// </summary>
private static bool UseExceptions
// No creation
Check() { }

/// <summary>
/// Is exception handling being used?
/// </summary>
private static bool UseExceptions
{
get
{
@@ -343,15 +343,15 @@ namespace DesignByContract
}
}

// Are trace assertion statements being used?
// Default is to use exception handling.
private static bool useAssertions = false;
// Are trace assertion statements being used?
// Default is to use exception handling.
static bool useAssertions = false;

#endregion // Implementation
#endregion // Implementation

} // End Check
} // End Check

internal class Trace
class Trace
{
internal static void Assert(bool assertion, string v)
{


Loading…
Cancel
Save