-
-
Notifications
You must be signed in to change notification settings - Fork 179
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #675 from hadashiA/ku/runner
Refine PlayerLoopRunner loop
- Loading branch information
Showing
5 changed files
with
218 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
VContainer/Assets/VContainer/Runtime/Internal/FreeList.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
#if UNITY_2021_3_OR_NEWER | ||
using Unity.Collections.LowLevel.Unsafe; | ||
#endif | ||
|
||
namespace VContainer.Internal | ||
{ | ||
class FreeList<T> where T : class | ||
{ | ||
public bool IsDisposed => lastIndex == -2; | ||
public int Length => lastIndex + 1; | ||
|
||
readonly object gate = new object(); | ||
T[] values; | ||
int lastIndex = -1; | ||
|
||
public FreeList(int initialCapacity) | ||
{ | ||
values = new T[initialCapacity]; | ||
} | ||
|
||
#if NETSTANDARD2_1 | ||
public ReadOnlySpan<T> AsSpan() | ||
{ | ||
if (lastIndex < 0) | ||
{ | ||
return ReadOnlySpan<T>.Empty; | ||
} | ||
return values.AsSpan(0, lastIndex + 1); | ||
} | ||
#endif | ||
|
||
public T this[int index] => values[index]; | ||
|
||
public void Add(T item) | ||
{ | ||
lock (gate) | ||
{ | ||
CheckDispose(); | ||
|
||
// try find blank | ||
var index = FindNullIndex(values); | ||
if (index == -1) | ||
{ | ||
// full, 1, 4, 6,...resize(x1.5) | ||
var len = values.Length; | ||
var newValues = new T[len + len / 2]; | ||
Array.Copy(values, newValues, len); | ||
values = newValues; | ||
index = len; | ||
} | ||
|
||
values[index] = item; | ||
if (lastIndex < index) | ||
{ | ||
lastIndex = index; | ||
} | ||
} | ||
} | ||
|
||
public void RemoveAt(int index) | ||
{ | ||
lock (gate) | ||
{ | ||
if (index < values.Length) | ||
{ | ||
ref var v = ref values[index]; | ||
if (v == null) throw new KeyNotFoundException($"key index {index} is not found."); | ||
|
||
v = null; | ||
if (index == lastIndex) | ||
{ | ||
lastIndex = FindLastNonNullIndex(values, index); | ||
} | ||
} | ||
} | ||
} | ||
|
||
public bool Remove(T value) | ||
{ | ||
lock (gate) | ||
{ | ||
if (lastIndex < 0) return false; | ||
|
||
var index = -1; | ||
for (var i = 0; i < values.Length; i++) | ||
{ | ||
if (values[i] == value) | ||
{ | ||
index = i; | ||
break; | ||
} | ||
} | ||
|
||
if (index != -1) | ||
{ | ||
RemoveAt(index); | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public void Clear() | ||
{ | ||
lock (gate) | ||
{ | ||
if (lastIndex > 0) | ||
{ | ||
Array.Clear(values, 0, lastIndex + 1); | ||
lastIndex = -1; | ||
} | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
lock (gate) | ||
{ | ||
lastIndex = -2; // -2 is disposed. | ||
} | ||
} | ||
|
||
void CheckDispose() | ||
{ | ||
if (IsDisposed) | ||
{ | ||
throw new ObjectDisposedException(GetType().FullName); | ||
} | ||
} | ||
|
||
#if UNITY_2021_3_OR_NEWER | ||
static unsafe int FindNullIndex(T[] target) | ||
{ | ||
ref var head = ref UnsafeUtility.As<T, IntPtr>(ref MemoryMarshal.GetReference(target.AsSpan())); | ||
fixed (void* p = &head) | ||
{ | ||
var span = new ReadOnlySpan<IntPtr>(p, target.Length); | ||
|
||
#if NETSTANDARD2_1 | ||
return span.IndexOf(IntPtr.Zero); | ||
#else | ||
for (int i = 0; i < span.Length; i++) | ||
{ | ||
if (span[i] == IntPtr.Zero) return i; | ||
} | ||
return -1; | ||
#endif | ||
} | ||
} | ||
|
||
static unsafe int FindLastNonNullIndex(T[] target, int lastIndex) | ||
{ | ||
ref var head = ref UnsafeUtility.As<T, IntPtr>(ref MemoryMarshal.GetReference(target.AsSpan())); | ||
fixed (void* p = &head) | ||
{ | ||
var span = new ReadOnlySpan<IntPtr>(p, lastIndex); // without lastIndexed value. | ||
|
||
for (var i = span.Length - 1; i >= 0; i--) | ||
{ | ||
if (span[i] != IntPtr.Zero) return i; | ||
} | ||
|
||
return -1; | ||
} | ||
} | ||
#else | ||
static int FindNullIndex(T[] target) | ||
{ | ||
for (var i = 0; i < target.Length; i++) | ||
{ | ||
if (target[i] == null) return i; | ||
} | ||
return -1; | ||
} | ||
|
||
static int FindLastNonNullIndex(T[] target, int lastIndex) | ||
{ | ||
for (var i = lastIndex; i >= 0; i--) | ||
{ | ||
if (target[i] != null) return i; | ||
} | ||
return -1; | ||
} | ||
#endif | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
VContainer/Assets/VContainer/Runtime/Internal/FreeList.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters