UniRx 에셋 추가

This commit is contained in:
Mingu Kim
2025-06-02 00:27:36 +09:00
parent 915f292d7d
commit 8a54d47b56
510 changed files with 42973 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
// this code is borrowed from RxOfficial(rx.codeplex.com) and modified
using System;
using System.Collections.Generic;
namespace UniRx.InternalUtil
{
/// <summary>
/// Asynchronous lock.
/// </summary>
internal sealed class AsyncLock : IDisposable
{
private readonly Queue<Action> queue = new Queue<Action>();
private bool isAcquired = false;
private bool hasFaulted = false;
/// <summary>
/// Queues the action for execution. If the caller acquires the lock and becomes the owner,
/// the queue is processed. If the lock is already owned, the action is queued and will get
/// processed by the owner.
/// </summary>
/// <param name="action">Action to queue for execution.</param>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
public void Wait(Action action)
{
if (action == null)
throw new ArgumentNullException("action");
var isOwner = false;
lock (queue)
{
if (!hasFaulted)
{
queue.Enqueue(action);
isOwner = !isAcquired;
isAcquired = true;
}
}
if (isOwner)
{
while (true)
{
var work = default(Action);
lock (queue)
{
if (queue.Count > 0)
work = queue.Dequeue();
else
{
isAcquired = false;
break;
}
}
try
{
work();
}
catch
{
lock (queue)
{
queue.Clear();
hasFaulted = true;
}
throw;
}
}
}
}
/// <summary>
/// Clears the work items in the queue and drops further work being queued.
/// </summary>
public void Dispose()
{
lock (queue)
{
queue.Clear();
hasFaulted = true;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 23dbd656cfe9c5e47b02c3c263e476aa
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace UniRx.InternalUtil
{
internal interface ICancellableTaskCompletionSource
{
bool TrySetException(Exception exception);
bool TrySetCanceled();
}
internal class CancellableTaskCompletionSource<T> : TaskCompletionSource<T>, ICancellableTaskCompletionSource
{
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 622c7ba8630c25b4c911cd1612ee0887
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
namespace UniRx.InternalUtil
{
using System;
internal static class ExceptionExtensions
{
public static void Throw(this Exception exception)
{
#if (NET_4_6 || NET_STANDARD_2_0)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(exception).Throw();
#endif
throw exception;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 94d5d10805124b34c8b488ebf3f893eb
timeCreated: 1509016318
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
using System;
namespace UniRx.InternalUtil
{
// ImmutableList is sometimes useful, use for public.
public class ImmutableList<T>
{
public static readonly ImmutableList<T> Empty = new ImmutableList<T>();
T[] data;
public T[] Data
{
get { return data; }
}
ImmutableList()
{
data = new T[0];
}
public ImmutableList(T[] data)
{
this.data = data;
}
public ImmutableList<T> Add(T value)
{
var newData = new T[data.Length + 1];
Array.Copy(data, newData, data.Length);
newData[data.Length] = value;
return new ImmutableList<T>(newData);
}
public ImmutableList<T> Remove(T value)
{
var i = IndexOf(value);
if (i < 0) return this;
var length = data.Length;
if (length == 1) return Empty;
var newData = new T[length - 1];
Array.Copy(data, 0, newData, 0, i);
Array.Copy(data, i + 1, newData, i, length - i - 1);
return new ImmutableList<T>(newData);
}
public int IndexOf(T value)
{
for (var i = 0; i < data.Length; ++i)
{
// ImmutableList only use for IObserver(no worry for boxed)
if (object.Equals(data[i], value)) return i;
}
return -1;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: dbafd8a41f556ec40b4bbd46fca2e85c
timeCreated: 1455373901
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace UniRx.InternalUtil
{
public class ListObserver<T> : IObserver<T>
{
private readonly ImmutableList<IObserver<T>> _observers;
public ListObserver(ImmutableList<IObserver<T>> observers)
{
_observers = observers;
}
public void OnCompleted()
{
var targetObservers = _observers.Data;
for (int i = 0; i < targetObservers.Length; i++)
{
targetObservers[i].OnCompleted();
}
}
public void OnError(Exception error)
{
var targetObservers = _observers.Data;
for (int i = 0; i < targetObservers.Length; i++)
{
targetObservers[i].OnError(error);
}
}
public void OnNext(T value)
{
var targetObservers = _observers.Data;
for (int i = 0; i < targetObservers.Length; i++)
{
targetObservers[i].OnNext(value);
}
}
internal IObserver<T> Add(IObserver<T> observer)
{
return new ListObserver<T>(_observers.Add(observer));
}
internal IObserver<T> Remove(IObserver<T> observer)
{
var i = Array.IndexOf(_observers.Data, observer);
if (i < 0)
return this;
if (_observers.Data.Length == 2)
{
return _observers.Data[1 - i];
}
else
{
return new ListObserver<T>(_observers.Remove(observer));
}
}
}
public class EmptyObserver<T> : IObserver<T>
{
public static readonly EmptyObserver<T> Instance = new EmptyObserver<T>();
EmptyObserver()
{
}
public void OnCompleted()
{
}
public void OnError(Exception error)
{
}
public void OnNext(T value)
{
}
}
public class ThrowObserver<T> : IObserver<T>
{
public static readonly ThrowObserver<T> Instance = new ThrowObserver<T>();
ThrowObserver()
{
}
public void OnCompleted()
{
}
public void OnError(Exception error)
{
error.Throw();
}
public void OnNext(T value)
{
}
}
public class DisposedObserver<T> : IObserver<T>
{
public static readonly DisposedObserver<T> Instance = new DisposedObserver<T>();
DisposedObserver()
{
}
public void OnCompleted()
{
throw new ObjectDisposedException("");
}
public void OnError(Exception error)
{
throw new ObjectDisposedException("");
}
public void OnNext(T value)
{
throw new ObjectDisposedException("");
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 889dc2f3c5f44d24a98a2c25510b4346
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,170 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace UniRx.InternalUtil
{
/// <summary>
/// Simple supports(only yield return null) lightweight, threadsafe coroutine dispatcher.
/// </summary>
public class MicroCoroutine
{
const int InitialSize = 16;
readonly object runningAndQueueLock = new object();
readonly object arrayLock = new object();
readonly Action<Exception> unhandledExceptionCallback;
int tail = 0;
bool running = false;
IEnumerator[] coroutines = new IEnumerator[InitialSize];
Queue<IEnumerator> waitQueue = new Queue<IEnumerator>();
public MicroCoroutine(Action<Exception> unhandledExceptionCallback)
{
this.unhandledExceptionCallback = unhandledExceptionCallback;
}
public void AddCoroutine(IEnumerator enumerator)
{
lock (runningAndQueueLock)
{
if (running)
{
waitQueue.Enqueue(enumerator);
return;
}
}
// worst case at multi threading, wait lock until finish Run() but it is super rarely.
lock (arrayLock)
{
// Ensure Capacity
if (coroutines.Length == tail)
{
Array.Resize(ref coroutines, checked(tail * 2));
}
coroutines[tail++] = enumerator;
}
}
public void Run()
{
lock (runningAndQueueLock)
{
running = true;
}
lock (arrayLock)
{
var j = tail - 1;
// eliminate array-bound check for i
for (int i = 0; i < coroutines.Length; i++)
{
var coroutine = coroutines[i];
if (coroutine != null)
{
try
{
if (!coroutine.MoveNext())
{
coroutines[i] = null;
}
else
{
#if UNITY_EDITOR
// validation only on Editor.
if (coroutine.Current != null)
{
UnityEngine.Debug.LogWarning("MicroCoroutine supports only yield return null. return value = " + coroutine.Current);
}
#endif
continue; // next i
}
}
catch (Exception ex)
{
coroutines[i] = null;
try
{
unhandledExceptionCallback(ex);
}
catch { }
}
}
// find null, loop from tail
while (i < j)
{
var fromTail = coroutines[j];
if (fromTail != null)
{
try
{
if (!fromTail.MoveNext())
{
coroutines[j] = null;
j--;
continue; // next j
}
else
{
#if UNITY_EDITOR
// validation only on Editor.
if (fromTail.Current != null)
{
UnityEngine.Debug.LogWarning("MicroCoroutine supports only yield return null. return value = " + coroutine.Current);
}
#endif
// swap
coroutines[i] = fromTail;
coroutines[j] = null;
j--;
goto NEXT_LOOP; // next i
}
}
catch (Exception ex)
{
coroutines[j] = null;
j--;
try
{
unhandledExceptionCallback(ex);
}
catch { }
continue; // next j
}
}
else
{
j--;
}
}
tail = i; // loop end
break; // LOOP END
NEXT_LOOP:
continue;
}
lock (runningAndQueueLock)
{
running = false;
while (waitQueue.Count != 0)
{
if (coroutines.Length == tail)
{
Array.Resize(ref coroutines, checked(tail * 2));
}
coroutines[tail++] = waitQueue.Dequeue();
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 108be6d634275c94a95eeb2a39de0792
timeCreated: 1462599042
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
// this code is borrowed from RxOfficial(rx.codeplex.com) and modified
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace UniRx.InternalUtil
{
internal class PriorityQueue<T> where T : IComparable<T>
{
private static long _count = long.MinValue;
private IndexedItem[] _items;
private int _size;
public PriorityQueue()
: this(16)
{
}
public PriorityQueue(int capacity)
{
_items = new IndexedItem[capacity];
_size = 0;
}
private bool IsHigherPriority(int left, int right)
{
return _items[left].CompareTo(_items[right]) < 0;
}
private void Percolate(int index)
{
if (index >= _size || index < 0)
return;
var parent = (index - 1) / 2;
if (parent < 0 || parent == index)
return;
if (IsHigherPriority(index, parent))
{
var temp = _items[index];
_items[index] = _items[parent];
_items[parent] = temp;
Percolate(parent);
}
}
private void Heapify()
{
Heapify(0);
}
private void Heapify(int index)
{
if (index >= _size || index < 0)
return;
var left = 2 * index + 1;
var right = 2 * index + 2;
var first = index;
if (left < _size && IsHigherPriority(left, first))
first = left;
if (right < _size && IsHigherPriority(right, first))
first = right;
if (first != index)
{
var temp = _items[index];
_items[index] = _items[first];
_items[first] = temp;
Heapify(first);
}
}
public int Count { get { return _size; } }
public T Peek()
{
if (_size == 0)
throw new InvalidOperationException("HEAP is Empty");
return _items[0].Value;
}
private void RemoveAt(int index)
{
_items[index] = _items[--_size];
_items[_size] = default(IndexedItem);
Heapify();
if (_size < _items.Length / 4)
{
var temp = _items;
_items = new IndexedItem[_items.Length / 2];
Array.Copy(temp, 0, _items, 0, _size);
}
}
public T Dequeue()
{
var result = Peek();
RemoveAt(0);
return result;
}
public void Enqueue(T item)
{
if (_size >= _items.Length)
{
var temp = _items;
_items = new IndexedItem[_items.Length * 2];
Array.Copy(temp, _items, temp.Length);
}
var index = _size++;
_items[index] = new IndexedItem { Value = item, Id = Interlocked.Increment(ref _count) };
Percolate(index);
}
public bool Remove(T item)
{
for (var i = 0; i < _size; ++i)
{
if (EqualityComparer<T>.Default.Equals(_items[i].Value, item))
{
RemoveAt(i);
return true;
}
}
return false;
}
struct IndexedItem : IComparable<IndexedItem>
{
public T Value;
public long Id;
public int CompareTo(IndexedItem other)
{
var c = Value.CompareTo(other.Value);
if (c == 0)
c = Id.CompareTo(other.Id);
return c;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7956b408e24dc5a4884fe4f5a3d7c858
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace UniRx.InternalUtil
{
internal static class PromiseHelper
{
internal static void TrySetResultAll<T>(IEnumerable<TaskCompletionSource<T>> source, T value)
{
var rentArray = source.ToArray(); // better to use Arraypool.
var array = rentArray;
var len = rentArray.Length;
for (int i = 0; i < len; i++)
{
array[i].TrySetResult(value);
array[i] = null;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: daa7aa90cece0fe40920a35e79f526dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,257 @@
// this code is borrowed from RxOfficial(rx.codeplex.com) and modified
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace UniRx.InternalUtil
{
/// <summary>
/// Abstract base class for scheduled work items.
/// </summary>
internal class ScheduledItem : IComparable<ScheduledItem>
{
private readonly BooleanDisposable _disposable = new BooleanDisposable();
private readonly TimeSpan _dueTime;
private readonly Action _action;
/// <summary>
/// Creates a new scheduled work item to run at the specified time.
/// </summary>
/// <param name="dueTime">Absolute time at which the work item has to be executed.</param>
public ScheduledItem(Action action, TimeSpan dueTime)
{
_dueTime = dueTime;
_action = action;
}
/// <summary>
/// Gets the absolute time at which the item is due for invocation.
/// </summary>
public TimeSpan DueTime
{
get { return _dueTime; }
}
/// <summary>
/// Invokes the work item.
/// </summary>
public void Invoke()
{
if (!_disposable.IsDisposed)
{
_action();
}
}
#region Inequality
/// <summary>
/// Compares the work item with another work item based on absolute time values.
/// </summary>
/// <param name="other">Work item to compare the current work item to.</param>
/// <returns>Relative ordering between this and the specified work item.</returns>
/// <remarks>The inequality operators are overloaded to provide results consistent with the IComparable implementation. Equality operators implement traditional reference equality semantics.</remarks>
public int CompareTo(ScheduledItem other)
{
// MSDN: By definition, any object compares greater than null, and two null references compare equal to each other.
if (object.ReferenceEquals(other, null))
return 1;
return DueTime.CompareTo(other.DueTime);
}
/// <summary>
/// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due before a second specified ScheduledItem&lt;TAbsolute&gt; object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if the DueTime value of left is earlier than the DueTime value of right; otherwise, false.</returns>
/// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
public static bool operator <(ScheduledItem left, ScheduledItem right)
{
return left.CompareTo(right) < 0;
}
/// <summary>
/// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due before or at the same of a second specified ScheduledItem&lt;TAbsolute&gt; object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if the DueTime value of left is earlier than or simultaneous with the DueTime value of right; otherwise, false.</returns>
/// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
public static bool operator <=(ScheduledItem left, ScheduledItem right)
{
return left.CompareTo(right) <= 0;
}
/// <summary>
/// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due after a second specified ScheduledItem&lt;TAbsolute&gt; object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if the DueTime value of left is later than the DueTime value of right; otherwise, false.</returns>
/// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
public static bool operator >(ScheduledItem left, ScheduledItem right)
{
return left.CompareTo(right) > 0;
}
/// <summary>
/// Determines whether one specified ScheduledItem&lt;TAbsolute&gt; object is due after or at the same time of a second specified ScheduledItem&lt;TAbsolute&gt; object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if the DueTime value of left is later than or simultaneous with the DueTime value of right; otherwise, false.</returns>
/// <remarks>This operator provides results consistent with the IComparable implementation.</remarks>
public static bool operator >=(ScheduledItem left, ScheduledItem right)
{
return left.CompareTo(right) >= 0;
}
#endregion
#region Equality
/// <summary>
/// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are equal.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are equal; otherwise, false.</returns>
/// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
public static bool operator ==(ScheduledItem left, ScheduledItem right)
{
return object.ReferenceEquals(left, right);
}
/// <summary>
/// Determines whether two specified ScheduledItem&lt;TAbsolute, TValue&gt; objects are inequal.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>true if both ScheduledItem&lt;TAbsolute, TValue&gt; are inequal; otherwise, false.</returns>
/// <remarks>This operator does not provide results consistent with the IComparable implementation. Instead, it implements reference equality.</remarks>
public static bool operator !=(ScheduledItem left, ScheduledItem right)
{
return !(left == right);
}
/// <summary>
/// Determines whether a ScheduledItem&lt;TAbsolute&gt; object is equal to the specified object.
/// </summary>
/// <param name="obj">The object to compare to the current ScheduledItem&lt;TAbsolute&gt; object.</param>
/// <returns>true if the obj parameter is a ScheduledItem&lt;TAbsolute&gt; object and is equal to the current ScheduledItem&lt;TAbsolute&gt; object; otherwise, false.</returns>
public override bool Equals(object obj)
{
return object.ReferenceEquals(this, obj);
}
/// <summary>
/// Returns the hash code for the current ScheduledItem&lt;TAbsolute&gt; object.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion
public IDisposable Cancellation
{
get
{
return _disposable;
}
}
/// <summary>
/// Gets whether the work item has received a cancellation request.
/// </summary>
public bool IsCanceled
{
get { return _disposable.IsDisposed; }
}
}
/// <summary>
/// Efficient scheduler queue that maintains scheduled items sorted by absolute time.
/// </summary>
/// <remarks>This type is not thread safe; users should ensure proper synchronization.</remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "But it *is* a queue!")]
internal class SchedulerQueue
{
private readonly PriorityQueue<ScheduledItem> _queue;
/// <summary>
/// Creates a new scheduler queue with a default initial capacity.
/// </summary>
public SchedulerQueue()
: this(1024)
{
}
/// <summary>
/// Creats a new scheduler queue with the specified initial capacity.
/// </summary>
/// <param name="capacity">Initial capacity of the scheduler queue.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
public SchedulerQueue(int capacity)
{
if (capacity < 0)
throw new ArgumentOutOfRangeException("capacity");
_queue = new PriorityQueue<ScheduledItem>(capacity);
}
/// <summary>
/// Gets the number of scheduled items in the scheduler queue.
/// </summary>
public int Count
{
get
{
return _queue.Count;
}
}
/// <summary>
/// Enqueues the specified work item to be scheduled.
/// </summary>
/// <param name="scheduledItem">Work item to be scheduled.</param>
public void Enqueue(ScheduledItem scheduledItem)
{
_queue.Enqueue(scheduledItem);
}
/// <summary>
/// Removes the specified work item from the scheduler queue.
/// </summary>
/// <param name="scheduledItem">Work item to be removed from the scheduler queue.</param>
/// <returns>true if the item was found; false otherwise.</returns>
public bool Remove(ScheduledItem scheduledItem)
{
return _queue.Remove(scheduledItem);
}
/// <summary>
/// Dequeues the next work item from the scheduler queue.
/// </summary>
/// <returns>Next work item in the scheduler queue (removed).</returns>
public ScheduledItem Dequeue()
{
return _queue.Dequeue();
}
/// <summary>
/// Peeks the next work item in the scheduler queue.
/// </summary>
/// <returns>Next work item in the scheduler queue (not removed).</returns>
public ScheduledItem Peek()
{
return _queue.Peek();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 45457ee4a77967347828238b7a52b851
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,112 @@
using System;
namespace UniRx.InternalUtil
{
public class ThreadSafeQueueWorker
{
const int MaxArrayLength = 0X7FEFFFFF;
const int InitialSize = 16;
object gate = new object();
bool dequing = false;
int actionListCount = 0;
Action<object>[] actionList = new Action<object>[InitialSize];
object[] actionStates = new object[InitialSize];
int waitingListCount = 0;
Action<object>[] waitingList = new Action<object>[InitialSize];
object[] waitingStates = new object[InitialSize];
public void Enqueue(Action<object> action, object state)
{
lock (gate)
{
if (dequing)
{
// Ensure Capacity
if (waitingList.Length == waitingListCount)
{
var newLength = waitingListCount * 2;
if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
var newArray = new Action<object>[newLength];
var newArrayState = new object[newLength];
Array.Copy(waitingList, newArray, waitingListCount);
Array.Copy(waitingStates, newArrayState, waitingListCount);
waitingList = newArray;
waitingStates = newArrayState;
}
waitingList[waitingListCount] = action;
waitingStates[waitingListCount] = state;
waitingListCount++;
}
else
{
// Ensure Capacity
if (actionList.Length == actionListCount)
{
var newLength = actionListCount * 2;
if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
var newArray = new Action<object>[newLength];
var newArrayState = new object[newLength];
Array.Copy(actionList, newArray, actionListCount);
Array.Copy(actionStates, newArrayState, actionListCount);
actionList = newArray;
actionStates = newArrayState;
}
actionList[actionListCount] = action;
actionStates[actionListCount] = state;
actionListCount++;
}
}
}
public void ExecuteAll(Action<Exception> unhandledExceptionCallback)
{
lock (gate)
{
if (actionListCount == 0) return;
dequing = true;
}
for (int i = 0; i < actionListCount; i++)
{
var action = actionList[i];
var state = actionStates[i];
try
{
action(state);
}
catch (Exception ex)
{
unhandledExceptionCallback(ex);
}
finally
{
// Clear
actionList[i] = null;
actionStates[i] = null;
}
}
lock (gate)
{
dequing = false;
var swapTempActionList = actionList;
var swapTempActionStates = actionStates;
actionListCount = waitingListCount;
actionList = waitingList;
actionStates = waitingStates;
waitingListCount = 0;
waitingList = swapTempActionList;
waitingStates = swapTempActionStates;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 768cbfcbe2a8e704a8953eea28cd33df
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,271 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#endif
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UniRx.InternalUtil
{
internal static class UnityEqualityComparer
{
public static readonly IEqualityComparer<Vector2> Vector2 = new Vector2EqualityComparer();
public static readonly IEqualityComparer<Vector3> Vector3 = new Vector3EqualityComparer();
public static readonly IEqualityComparer<Vector4> Vector4 = new Vector4EqualityComparer();
public static readonly IEqualityComparer<Color> Color = new ColorEqualityComparer();
public static readonly IEqualityComparer<Color32> Color32 = new Color32EqualityComparer();
public static readonly IEqualityComparer<Rect> Rect = new RectEqualityComparer();
public static readonly IEqualityComparer<Bounds> Bounds = new BoundsEqualityComparer();
public static readonly IEqualityComparer<Quaternion> Quaternion = new QuaternionEqualityComparer();
static readonly RuntimeTypeHandle vector2Type = typeof(Vector2).TypeHandle;
static readonly RuntimeTypeHandle vector3Type = typeof(Vector3).TypeHandle;
static readonly RuntimeTypeHandle vector4Type = typeof(Vector4).TypeHandle;
static readonly RuntimeTypeHandle colorType = typeof(Color).TypeHandle;
static readonly RuntimeTypeHandle color32Type = typeof(Color32).TypeHandle;
static readonly RuntimeTypeHandle rectType = typeof(Rect).TypeHandle;
static readonly RuntimeTypeHandle boundsType = typeof(Bounds).TypeHandle;
static readonly RuntimeTypeHandle quaternionType = typeof(Quaternion).TypeHandle;
#if UNITY_2017_2_OR_NEWER
public static readonly IEqualityComparer<Vector2Int> Vector2Int = new Vector2IntEqualityComparer();
public static readonly IEqualityComparer<Vector3Int> Vector3Int = new Vector3IntEqualityComparer();
public static readonly IEqualityComparer<RangeInt> RangeInt = new RangeIntEqualityComparer();
public static readonly IEqualityComparer<RectInt> RectInt = new RectIntEqualityComparer();
public static readonly IEqualityComparer<BoundsInt> BoundsInt = new BoundsIntEqualityComparer();
static readonly RuntimeTypeHandle vector2IntType = typeof(Vector2Int).TypeHandle;
static readonly RuntimeTypeHandle vector3IntType = typeof(Vector3Int).TypeHandle;
static readonly RuntimeTypeHandle rangeIntType = typeof(RangeInt).TypeHandle;
static readonly RuntimeTypeHandle rectIntType = typeof(RectInt).TypeHandle;
static readonly RuntimeTypeHandle boundsIntType = typeof(BoundsInt).TypeHandle;
#endif
static class Cache<T>
{
public static readonly IEqualityComparer<T> Comparer;
static Cache()
{
var comparer = GetDefaultHelper(typeof(T));
if (comparer == null)
{
Comparer = EqualityComparer<T>.Default;
}
else
{
Comparer = (IEqualityComparer<T>)comparer;
}
}
}
public static IEqualityComparer<T> GetDefault<T>()
{
return Cache<T>.Comparer;
}
static object GetDefaultHelper(Type type)
{
var t = type.TypeHandle;
if (t.Equals(vector2Type)) return (object)UnityEqualityComparer.Vector2;
if (t.Equals(vector3Type)) return (object)UnityEqualityComparer.Vector3;
if (t.Equals(vector4Type)) return (object)UnityEqualityComparer.Vector4;
if (t.Equals(colorType)) return (object)UnityEqualityComparer.Color;
if (t.Equals(color32Type)) return (object)UnityEqualityComparer.Color32;
if (t.Equals(rectType)) return (object)UnityEqualityComparer.Rect;
if (t.Equals(boundsType)) return (object)UnityEqualityComparer.Bounds;
if (t.Equals(quaternionType)) return (object)UnityEqualityComparer.Quaternion;
#if UNITY_2017_2_OR_NEWER
if (t.Equals(vector2IntType)) return (object)UnityEqualityComparer.Vector2Int;
if (t.Equals(vector3IntType)) return (object)UnityEqualityComparer.Vector3Int;
if (t.Equals(rangeIntType)) return (object)UnityEqualityComparer.RangeInt;
if (t.Equals(rectIntType)) return (object)UnityEqualityComparer.RectInt;
if (t.Equals(boundsIntType)) return (object)UnityEqualityComparer.BoundsInt;
#endif
return null;
}
sealed class Vector2EqualityComparer : IEqualityComparer<Vector2>
{
public bool Equals(Vector2 self, Vector2 vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y);
}
public int GetHashCode(Vector2 obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2;
}
}
sealed class Vector3EqualityComparer : IEqualityComparer<Vector3>
{
public bool Equals(Vector3 self, Vector3 vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z);
}
public int GetHashCode(Vector3 obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2;
}
}
sealed class Vector4EqualityComparer : IEqualityComparer<Vector4>
{
public bool Equals(Vector4 self, Vector4 vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z) && self.w.Equals(vector.w);
}
public int GetHashCode(Vector4 obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2 ^ obj.w.GetHashCode() >> 1;
}
}
sealed class ColorEqualityComparer : IEqualityComparer<Color>
{
public bool Equals(Color self, Color other)
{
return self.r.Equals(other.r) && self.g.Equals(other.g) && self.b.Equals(other.b) && self.a.Equals(other.a);
}
public int GetHashCode(Color obj)
{
return obj.r.GetHashCode() ^ obj.g.GetHashCode() << 2 ^ obj.b.GetHashCode() >> 2 ^ obj.a.GetHashCode() >> 1;
}
}
sealed class RectEqualityComparer : IEqualityComparer<Rect>
{
public bool Equals(Rect self, Rect other)
{
return self.x.Equals(other.x) && self.width.Equals(other.width) && self.y.Equals(other.y) && self.height.Equals(other.height);
}
public int GetHashCode(Rect obj)
{
return obj.x.GetHashCode() ^ obj.width.GetHashCode() << 2 ^ obj.y.GetHashCode() >> 2 ^ obj.height.GetHashCode() >> 1;
}
}
sealed class BoundsEqualityComparer : IEqualityComparer<Bounds>
{
public bool Equals(Bounds self, Bounds vector)
{
return self.center.Equals(vector.center) && self.extents.Equals(vector.extents);
}
public int GetHashCode(Bounds obj)
{
return obj.center.GetHashCode() ^ obj.extents.GetHashCode() << 2;
}
}
sealed class QuaternionEqualityComparer : IEqualityComparer<Quaternion>
{
public bool Equals(Quaternion self, Quaternion vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z) && self.w.Equals(vector.w);
}
public int GetHashCode(Quaternion obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2 ^ obj.w.GetHashCode() >> 1;
}
}
sealed class Color32EqualityComparer : IEqualityComparer<Color32>
{
public bool Equals(Color32 self, Color32 vector)
{
return self.a.Equals(vector.a) && self.r.Equals(vector.r) && self.g.Equals(vector.g) && self.b.Equals(vector.b);
}
public int GetHashCode(Color32 obj)
{
return obj.a.GetHashCode() ^ obj.r.GetHashCode() << 2 ^ obj.g.GetHashCode() >> 2 ^ obj.b.GetHashCode() >> 1;
}
}
#if UNITY_2017_2_OR_NEWER
sealed class Vector2IntEqualityComparer : IEqualityComparer<Vector2Int>
{
public bool Equals(Vector2Int self, Vector2Int vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y);
}
public int GetHashCode(Vector2Int obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2;
}
}
sealed class Vector3IntEqualityComparer : IEqualityComparer<Vector3Int>
{
public static readonly Vector3IntEqualityComparer Default = new Vector3IntEqualityComparer();
public bool Equals(Vector3Int self, Vector3Int vector)
{
return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z);
}
public int GetHashCode(Vector3Int obj)
{
return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2;
}
}
sealed class RangeIntEqualityComparer : IEqualityComparer<RangeInt>
{
public bool Equals(RangeInt self, RangeInt vector)
{
return self.start.Equals(vector.start) && self.length.Equals(vector.length);
}
public int GetHashCode(RangeInt obj)
{
return obj.start.GetHashCode() ^ obj.length.GetHashCode() << 2;
}
}
sealed class RectIntEqualityComparer : IEqualityComparer<RectInt>
{
public bool Equals(RectInt self, RectInt other)
{
return self.x.Equals(other.x) && self.width.Equals(other.width) && self.y.Equals(other.y) && self.height.Equals(other.height);
}
public int GetHashCode(RectInt obj)
{
return obj.x.GetHashCode() ^ obj.width.GetHashCode() << 2 ^ obj.y.GetHashCode() >> 2 ^ obj.height.GetHashCode() >> 1;
}
}
sealed class BoundsIntEqualityComparer : IEqualityComparer<BoundsInt>
{
public bool Equals(BoundsInt self, BoundsInt vector)
{
return Vector3IntEqualityComparer.Default.Equals(self.position, vector.position)
&& Vector3IntEqualityComparer.Default.Equals(self.size, vector.size);
}
public int GetHashCode(BoundsInt obj)
{
return Vector3IntEqualityComparer.Default.GetHashCode(obj.position) ^ Vector3IntEqualityComparer.Default.GetHashCode(obj.size) << 2;
}
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 626a410137515ac45bb59d1ca91d8f3f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: