UniRx 에셋 추가
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public sealed class BooleanDisposable : IDisposable, ICancelable
|
||||
{
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public BooleanDisposable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal BooleanDisposable(bool isDisposed)
|
||||
{
|
||||
IsDisposed = isDisposed;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!IsDisposed) IsDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ff95c6eb380ca248984d8c27c1244d0
|
||||
timeCreated: 1455373899
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
// original code from GitHub Reactive-Extensions/Rx.NET
|
||||
// some modified.
|
||||
|
||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
#if (NETFX_CORE || NET_4_6 || NET_STANDARD_2_0 || UNITY_WSA_10_0)
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a disposable resource that has an associated <seealso cref="T:System.Threading.CancellationToken"/> that will be set to the cancellation requested state upon disposal.
|
||||
/// </summary>
|
||||
public sealed class CancellationDisposable : ICancelable
|
||||
{
|
||||
private readonly CancellationTokenSource _cts;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CancellationDisposable"/> class that uses an existing <seealso cref="T:System.Threading.CancellationTokenSource"/>.
|
||||
/// </summary>
|
||||
/// <param name="cts"><seealso cref="T:System.Threading.CancellationTokenSource"/> used for cancellation.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="cts"/> is null.</exception>
|
||||
public CancellationDisposable(CancellationTokenSource cts)
|
||||
{
|
||||
if (cts == null)
|
||||
throw new ArgumentNullException("cts");
|
||||
|
||||
_cts = cts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CancellationDisposable"/> class that uses a new <seealso cref="T:System.Threading.CancellationTokenSource"/>.
|
||||
/// </summary>
|
||||
public CancellationDisposable()
|
||||
: this(new CancellationTokenSource())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="T:System.Threading.CancellationToken"/> used by this CancellationDisposable.
|
||||
/// </summary>
|
||||
public CancellationToken Token
|
||||
{
|
||||
get { return _cts.Token; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the underlying <seealso cref="T:System.Threading.CancellationTokenSource"/>.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the object is disposed.
|
||||
/// </summary>
|
||||
public bool IsDisposed
|
||||
{
|
||||
get { return _cts.IsCancellationRequested; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c675907554bfa24d8bd411f386e410d
|
||||
timeCreated: 1475137543
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
// using System.Linq; do not use LINQ
|
||||
using System.Text;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
// copy, modified from Rx Official
|
||||
|
||||
public sealed class CompositeDisposable : ICollection<IDisposable>, IDisposable, ICancelable
|
||||
{
|
||||
private readonly object _gate = new object();
|
||||
|
||||
private bool _disposed;
|
||||
private List<IDisposable> _disposables;
|
||||
private int _count;
|
||||
private const int SHRINK_THRESHOLD = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CompositeDisposable"/> class with no disposables contained by it initially.
|
||||
/// </summary>
|
||||
public CompositeDisposable()
|
||||
{
|
||||
_disposables = new List<IDisposable>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CompositeDisposable"/> class with the specified number of disposables.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The number of disposables that the new CompositeDisposable can initially store.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
|
||||
public CompositeDisposable(int capacity)
|
||||
{
|
||||
if (capacity < 0)
|
||||
throw new ArgumentOutOfRangeException("capacity");
|
||||
|
||||
_disposables = new List<IDisposable>(capacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CompositeDisposable"/> class from a group of disposables.
|
||||
/// </summary>
|
||||
/// <param name="disposables">Disposables that will be disposed together.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="disposables"/> is null.</exception>
|
||||
public CompositeDisposable(params IDisposable[] disposables)
|
||||
{
|
||||
if (disposables == null)
|
||||
throw new ArgumentNullException("disposables");
|
||||
|
||||
_disposables = new List<IDisposable>(disposables);
|
||||
_count = _disposables.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.CompositeDisposable"/> class from a group of disposables.
|
||||
/// </summary>
|
||||
/// <param name="disposables">Disposables that will be disposed together.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="disposables"/> is null.</exception>
|
||||
public CompositeDisposable(IEnumerable<IDisposable> disposables)
|
||||
{
|
||||
if (disposables == null)
|
||||
throw new ArgumentNullException("disposables");
|
||||
|
||||
_disposables = new List<IDisposable>(disposables);
|
||||
_count = _disposables.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of disposables contained in the CompositeDisposable.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a disposable to the CompositeDisposable or disposes the disposable if the CompositeDisposable is disposed.
|
||||
/// </summary>
|
||||
/// <param name="item">Disposable to add.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
|
||||
public void Add(IDisposable item)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item");
|
||||
|
||||
var shouldDispose = false;
|
||||
lock (_gate)
|
||||
{
|
||||
shouldDispose = _disposed;
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposables.Add(item);
|
||||
_count++;
|
||||
}
|
||||
}
|
||||
if (shouldDispose)
|
||||
item.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes and disposes the first occurrence of a disposable from the CompositeDisposable.
|
||||
/// </summary>
|
||||
/// <param name="item">Disposable to remove.</param>
|
||||
/// <returns>true if found; false otherwise.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
|
||||
public bool Remove(IDisposable item)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item");
|
||||
|
||||
var shouldDispose = false;
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
//
|
||||
// List<T> doesn't shrink the size of the underlying array but does collapse the array
|
||||
// by copying the tail one position to the left of the removal index. We don't need
|
||||
// index-based lookup but only ordering for sequential disposal. So, instead of spending
|
||||
// cycles on the Array.Copy imposed by Remove, we use a null sentinel value. We also
|
||||
// do manual Swiss cheese detection to shrink the list if there's a lot of holes in it.
|
||||
//
|
||||
var i = _disposables.IndexOf(item);
|
||||
if (i >= 0)
|
||||
{
|
||||
shouldDispose = true;
|
||||
_disposables[i] = null;
|
||||
_count--;
|
||||
|
||||
if (_disposables.Capacity > SHRINK_THRESHOLD && _count < _disposables.Capacity / 2)
|
||||
{
|
||||
var old = _disposables;
|
||||
_disposables = new List<IDisposable>(_disposables.Capacity / 2);
|
||||
|
||||
foreach (var d in old)
|
||||
if (d != null)
|
||||
_disposables.Add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDispose)
|
||||
item.Dispose();
|
||||
|
||||
return shouldDispose;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all disposables in the group and removes them from the group.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
var currentDisposables = default(IDisposable[]);
|
||||
lock (_gate)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
currentDisposables = _disposables.ToArray();
|
||||
_disposables.Clear();
|
||||
_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentDisposables != null)
|
||||
{
|
||||
foreach (var d in currentDisposables)
|
||||
if (d != null)
|
||||
d.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes and disposes all disposables from the CompositeDisposable, but does not dispose the CompositeDisposable.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
var currentDisposables = default(IDisposable[]);
|
||||
lock (_gate)
|
||||
{
|
||||
currentDisposables = _disposables.ToArray();
|
||||
_disposables.Clear();
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
foreach (var d in currentDisposables)
|
||||
if (d != null)
|
||||
d.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the CompositeDisposable contains a specific disposable.
|
||||
/// </summary>
|
||||
/// <param name="item">Disposable to search for.</param>
|
||||
/// <returns>true if the disposable was found; otherwise, false.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
|
||||
public bool Contains(IDisposable item)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item");
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
return _disposables.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the disposables contained in the CompositeDisposable to an array, starting at a particular array index.
|
||||
/// </summary>
|
||||
/// <param name="array">Array to copy the contained disposables to.</param>
|
||||
/// <param name="arrayIndex">Target index at which to copy the first disposable of the group.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than zero. -or - <paramref name="arrayIndex"/> is larger than or equal to the array length.</exception>
|
||||
public void CopyTo(IDisposable[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
if (arrayIndex < 0 || arrayIndex >= array.Length)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
var disArray = new List<IDisposable>();
|
||||
foreach (var item in _disposables)
|
||||
{
|
||||
if (item != null) disArray.Add(item);
|
||||
}
|
||||
|
||||
Array.Copy(disArray.ToArray(), 0, array, arrayIndex, array.Length - arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Always returns false.
|
||||
/// </summary>
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the CompositeDisposable.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator to iterate over the disposables.</returns>
|
||||
public IEnumerator<IDisposable> GetEnumerator()
|
||||
{
|
||||
var res = new List<IDisposable>();
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
foreach (var d in _disposables)
|
||||
{
|
||||
if (d != null) res.Add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return res.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the CompositeDisposable.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator to iterate over the disposables.</returns>
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the object is disposed.
|
||||
/// </summary>
|
||||
public bool IsDisposed
|
||||
{
|
||||
get { return _disposed; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0f9d923bd5f4cd47b39bdd83125de27
|
||||
timeCreated: 1455373900
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,255 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public sealed class DictionaryDisposable<TKey, TValue> : IDisposable, IDictionary<TKey, TValue>
|
||||
where TValue : IDisposable
|
||||
{
|
||||
bool isDisposed = false;
|
||||
readonly Dictionary<TKey, TValue> inner;
|
||||
|
||||
public DictionaryDisposable()
|
||||
{
|
||||
inner = new Dictionary<TKey, TValue>();
|
||||
}
|
||||
|
||||
public DictionaryDisposable(IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
inner = new Dictionary<TKey, TValue>(comparer);
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return inner[key];
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
if (isDisposed) value.Dispose();
|
||||
|
||||
TValue oldValue;
|
||||
if (TryGetValue(key, out oldValue))
|
||||
{
|
||||
oldValue.Dispose();
|
||||
inner[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
inner[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return inner.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<TKey, TValue>.KeyCollection Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException("please use .Select(x => x.Key).ToArray()");
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<TKey, TValue>.ValueCollection Values
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException("please use .Select(x => x.Value).ToArray()");
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
if (isDisposed)
|
||||
{
|
||||
value.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
inner.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
foreach (var item in inner)
|
||||
{
|
||||
item.Value.Dispose();
|
||||
}
|
||||
inner.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
TValue oldValue;
|
||||
if (inner.TryGetValue(key, out oldValue))
|
||||
{
|
||||
var isSuccessRemove = inner.Remove(key);
|
||||
if (isSuccessRemove)
|
||||
{
|
||||
oldValue.Dispose();
|
||||
}
|
||||
return isSuccessRemove;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return inner.ContainsKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return inner.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<TKey, TValue>.Enumerator GetEnumerator()
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return new Dictionary<TKey, TValue>(inner).GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ICollection<KeyValuePair<TKey, TValue>>)inner).IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
ICollection<TKey> IDictionary<TKey, TValue>.Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return new List<TKey>(inner.Keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICollection<TValue> IDictionary<TKey, TValue>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return new List<TValue>(inner.Values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !UNITY_METRO
|
||||
|
||||
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
((System.Runtime.Serialization.ISerializable)inner).GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDeserialization(object sender)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
((System.Runtime.Serialization.IDeserializationCallback)inner).OnDeserialization(sender);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Add((TKey)item.Key, (TValue)item.Value);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<TKey, TValue>>)inner).Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
((ICollection<KeyValuePair<TKey, TValue>>)inner).CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
return new List<KeyValuePair<TKey, TValue>>((ICollection<KeyValuePair<TKey, TValue>>)inner).GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (inner)
|
||||
{
|
||||
if (isDisposed) return;
|
||||
isDisposed = true;
|
||||
|
||||
foreach (var item in inner)
|
||||
{
|
||||
item.Value.Dispose();
|
||||
}
|
||||
inner.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 702939929fc84d544b12076b76aa73b5
|
||||
timeCreated: 1455373899
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public static class Disposable
|
||||
{
|
||||
public static readonly IDisposable Empty = EmptyDisposable.Singleton;
|
||||
|
||||
public static IDisposable Create(Action disposeAction)
|
||||
{
|
||||
return new AnonymousDisposable(disposeAction);
|
||||
}
|
||||
|
||||
public static IDisposable CreateWithState<TState>(TState state, Action<TState> disposeAction)
|
||||
{
|
||||
return new AnonymousDisposable<TState>(state, disposeAction);
|
||||
}
|
||||
|
||||
class EmptyDisposable : IDisposable
|
||||
{
|
||||
public static EmptyDisposable Singleton = new EmptyDisposable();
|
||||
|
||||
private EmptyDisposable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class AnonymousDisposable : IDisposable
|
||||
{
|
||||
bool isDisposed = false;
|
||||
readonly Action dispose;
|
||||
|
||||
public AnonymousDisposable(Action dispose)
|
||||
{
|
||||
this.dispose = dispose;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!isDisposed)
|
||||
{
|
||||
isDisposed = true;
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AnonymousDisposable<T> : IDisposable
|
||||
{
|
||||
bool isDisposed = false;
|
||||
readonly T state;
|
||||
readonly Action<T> dispose;
|
||||
|
||||
public AnonymousDisposable(T state, Action<T> dispose)
|
||||
{
|
||||
this.state = state;
|
||||
this.dispose = dispose;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!isDisposed)
|
||||
{
|
||||
isDisposed = true;
|
||||
dispose(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 958f291bb8f434740a6d2c08ad5182a0
|
||||
timeCreated: 1455373900
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public static partial class DisposableExtensions
|
||||
{
|
||||
/// <summary>Add disposable(self) to CompositeDisposable(or other ICollection). Return value is self disposable.</summary>
|
||||
public static T AddTo<T>(this T disposable, ICollection<IDisposable> container)
|
||||
where T : IDisposable
|
||||
{
|
||||
if (disposable == null) throw new ArgumentNullException("disposable");
|
||||
if (container == null) throw new ArgumentNullException("container");
|
||||
|
||||
container.Add(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c4757265ae105441bae71007cbd0184
|
||||
timeCreated: 1455373900
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public interface ICancelable : IDisposable
|
||||
{
|
||||
bool IsDisposed { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5cd5b0b304c78345a49757b1f6f8ba8
|
||||
timeCreated: 1455373900
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public sealed class MultipleAssignmentDisposable : IDisposable, ICancelable
|
||||
{
|
||||
static readonly BooleanDisposable True = new BooleanDisposable(true);
|
||||
|
||||
object gate = new object();
|
||||
IDisposable current;
|
||||
|
||||
public bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return current == True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IDisposable Disposable
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return (current == True)
|
||||
? UniRx.Disposable.Empty
|
||||
: current;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
var shouldDispose = false;
|
||||
lock (gate)
|
||||
{
|
||||
shouldDispose = (current == True);
|
||||
if (!shouldDispose)
|
||||
{
|
||||
current = value;
|
||||
}
|
||||
}
|
||||
if (shouldDispose && value != null)
|
||||
{
|
||||
value.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IDisposable old = null;
|
||||
|
||||
lock (gate)
|
||||
{
|
||||
if (current != True)
|
||||
{
|
||||
old = current;
|
||||
current = True;
|
||||
}
|
||||
}
|
||||
|
||||
if (old != null) old.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb959083576ace749afd55c1e54b02d9
|
||||
timeCreated: 1455373901
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,152 @@
|
||||
// This code is borrwed from Rx Official and some 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;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a disposable resource that only disposes its underlying disposable resource when all <see cref="GetDisposable">dependent disposable objects</see> have been disposed.
|
||||
/// </summary>
|
||||
public sealed class RefCountDisposable : ICancelable
|
||||
{
|
||||
private readonly object _gate = new object();
|
||||
private IDisposable _disposable;
|
||||
private bool _isPrimaryDisposed;
|
||||
private int _count;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.RefCountDisposable"/> class with the specified disposable.
|
||||
/// </summary>
|
||||
/// <param name="disposable">Underlying disposable.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="disposable"/> is null.</exception>
|
||||
public RefCountDisposable(IDisposable disposable)
|
||||
{
|
||||
if (disposable == null)
|
||||
throw new ArgumentNullException("disposable");
|
||||
|
||||
_disposable = disposable;
|
||||
_isPrimaryDisposed = false;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the object is disposed.
|
||||
/// </summary>
|
||||
public bool IsDisposed
|
||||
{
|
||||
get { return _disposable == null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a dependent disposable that when disposed decreases the refcount on the underlying disposable.
|
||||
/// </summary>
|
||||
/// <returns>A dependent disposable contributing to the reference count that manages the underlying disposable's lifetime.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Backward compat + non-trivial work for a property getter.")]
|
||||
public IDisposable GetDisposable()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
if (_disposable == null)
|
||||
{
|
||||
return Disposable.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
_count++;
|
||||
return new InnerDisposable(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the underlying disposable only when all dependent disposables have been disposed.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
var disposable = default(IDisposable);
|
||||
lock (_gate)
|
||||
{
|
||||
if (_disposable != null)
|
||||
{
|
||||
if (!_isPrimaryDisposed)
|
||||
{
|
||||
_isPrimaryDisposed = true;
|
||||
|
||||
if (_count == 0)
|
||||
{
|
||||
disposable = _disposable;
|
||||
_disposable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disposable != null)
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
private void Release()
|
||||
{
|
||||
var disposable = default(IDisposable);
|
||||
lock (_gate)
|
||||
{
|
||||
if (_disposable != null)
|
||||
{
|
||||
_count--;
|
||||
|
||||
if (_isPrimaryDisposed)
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
disposable = _disposable;
|
||||
_disposable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disposable != null)
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
sealed class InnerDisposable : IDisposable
|
||||
{
|
||||
private RefCountDisposable _parent;
|
||||
object parentLock = new object();
|
||||
|
||||
public InnerDisposable(RefCountDisposable parent)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
RefCountDisposable parent;
|
||||
lock (parentLock)
|
||||
{
|
||||
parent = _parent;
|
||||
_parent = null;
|
||||
}
|
||||
if (parent != null)
|
||||
parent.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Observable
|
||||
{
|
||||
static IObservable<T> AddRef<T>(IObservable<T> xs, RefCountDisposable r)
|
||||
{
|
||||
return Observable.Create<T>((IObserver<T> observer) => new CompositeDisposable(new IDisposable[]
|
||||
{
|
||||
r.GetDisposable(),
|
||||
xs.Subscribe(observer)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fb5a2cdb138579498eb20d8b7818ad8
|
||||
timeCreated: 1455373898
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public sealed class ScheduledDisposable : ICancelable
|
||||
{
|
||||
private readonly IScheduler scheduler;
|
||||
private volatile IDisposable disposable;
|
||||
private int isDisposed = 0;
|
||||
|
||||
public ScheduledDisposable(IScheduler scheduler, IDisposable disposable)
|
||||
{
|
||||
this.scheduler = scheduler;
|
||||
this.disposable = disposable;
|
||||
}
|
||||
|
||||
public IScheduler Scheduler
|
||||
{
|
||||
get { return scheduler; }
|
||||
}
|
||||
|
||||
public IDisposable Disposable
|
||||
{
|
||||
get { return disposable; }
|
||||
}
|
||||
|
||||
public bool IsDisposed
|
||||
{
|
||||
get { return isDisposed != 0; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Scheduler.Schedule(DisposeInner);
|
||||
}
|
||||
|
||||
private void DisposeInner()
|
||||
{
|
||||
if (Interlocked.Increment(ref isDisposed) == 1)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db98ce742e859bd4e81db434c3ca3663
|
||||
timeCreated: 1455373901
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
public sealed class SerialDisposable : IDisposable, ICancelable
|
||||
{
|
||||
readonly object gate = new object();
|
||||
IDisposable current;
|
||||
bool disposed;
|
||||
|
||||
public bool IsDisposed { get { lock (gate) { return disposed; } } }
|
||||
|
||||
public IDisposable Disposable
|
||||
{
|
||||
get
|
||||
{
|
||||
return current;
|
||||
}
|
||||
set
|
||||
{
|
||||
var shouldDispose = false;
|
||||
var old = default(IDisposable);
|
||||
lock (gate)
|
||||
{
|
||||
shouldDispose = disposed;
|
||||
if (!shouldDispose)
|
||||
{
|
||||
old = current;
|
||||
current = value;
|
||||
}
|
||||
}
|
||||
if (old != null)
|
||||
{
|
||||
old.Dispose();
|
||||
}
|
||||
if (shouldDispose && value != null)
|
||||
{
|
||||
value.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var old = default(IDisposable);
|
||||
|
||||
lock (gate)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
old = current;
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (old != null)
|
||||
{
|
||||
old.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06fb064ad9e4d354ab15ff89f6343243
|
||||
timeCreated: 1455373897
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
// should be use Interlocked.CompareExchange for Threadsafe?
|
||||
// but CompareExchange cause ExecutionEngineException on iOS.
|
||||
// AOT...
|
||||
// use lock instead
|
||||
|
||||
public sealed class SingleAssignmentDisposable : IDisposable, ICancelable
|
||||
{
|
||||
readonly object gate = new object();
|
||||
IDisposable current;
|
||||
bool disposed;
|
||||
|
||||
public bool IsDisposed { get { lock (gate) { return disposed; } } }
|
||||
|
||||
public IDisposable Disposable
|
||||
{
|
||||
get
|
||||
{
|
||||
return current;
|
||||
}
|
||||
set
|
||||
{
|
||||
var old = default(IDisposable);
|
||||
bool alreadyDisposed;
|
||||
lock (gate)
|
||||
{
|
||||
alreadyDisposed = disposed;
|
||||
old = current;
|
||||
if (!alreadyDisposed)
|
||||
{
|
||||
if (value == null) return;
|
||||
current = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (alreadyDisposed && value != null)
|
||||
{
|
||||
value.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (old != null) throw new InvalidOperationException("Disposable is already set");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IDisposable old = null;
|
||||
|
||||
lock (gate)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
old = current;
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (old != null) old.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ec869f7548c62748ad57a5c86b2f6ba
|
||||
timeCreated: 1455373899
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,277 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniRx
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a group of disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
public abstract class StableCompositeDisposable : ICancelable
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new group containing two disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
/// <param name="disposable1">The first disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable2">The second disposable resoruce to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable Create(IDisposable disposable1, IDisposable disposable2)
|
||||
{
|
||||
if (disposable1 == null) throw new ArgumentNullException("disposable1");
|
||||
if (disposable2 == null) throw new ArgumentNullException("disposable2");
|
||||
|
||||
return new Binary(disposable1, disposable2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new group containing three disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
/// <param name="disposable1">The first disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable2">The second disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable3">The third disposable resoruce to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable Create(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3)
|
||||
{
|
||||
if (disposable1 == null) throw new ArgumentNullException("disposable1");
|
||||
if (disposable2 == null) throw new ArgumentNullException("disposable2");
|
||||
if (disposable3 == null) throw new ArgumentNullException("disposable3");
|
||||
|
||||
return new Trinary(disposable1, disposable2, disposable3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new group containing four disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
/// <param name="disposable1">The first disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable2">The second disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable3">The three disposable resoruce to add to the group.</param>
|
||||
/// <param name="disposable4">The four disposable resoruce to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable Create(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3, IDisposable disposable4)
|
||||
{
|
||||
if (disposable1 == null) throw new ArgumentNullException("disposable1");
|
||||
if (disposable2 == null) throw new ArgumentNullException("disposable2");
|
||||
if (disposable3 == null) throw new ArgumentNullException("disposable3");
|
||||
if (disposable4 == null) throw new ArgumentNullException("disposable4");
|
||||
|
||||
return new Quaternary(disposable1, disposable2, disposable3, disposable4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new group of disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
/// <param name="disposables">Disposable resources to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable Create(params IDisposable[] disposables)
|
||||
{
|
||||
if (disposables == null) throw new ArgumentNullException("disposables");
|
||||
|
||||
return new NAry(disposables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new group of disposable resources that are disposed together. Array is not copied, it's unsafe but optimized.
|
||||
/// </summary>
|
||||
/// <param name="disposables">Disposable resources to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable CreateUnsafe(IDisposable[] disposables)
|
||||
{
|
||||
return new NAryUnsafe(disposables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new group of disposable resources that are disposed together.
|
||||
/// </summary>
|
||||
/// <param name="disposables">Disposable resources to add to the group.</param>
|
||||
/// <returns>Group of disposable resources that are disposed together.</returns>
|
||||
public static ICancelable Create(IEnumerable<IDisposable> disposables)
|
||||
{
|
||||
if (disposables == null) throw new ArgumentNullException("disposables");
|
||||
|
||||
return new NAry(disposables);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all disposables in the group.
|
||||
/// </summary>
|
||||
public abstract void Dispose();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the object is disposed.
|
||||
/// </summary>
|
||||
public abstract bool IsDisposed
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
class Binary : StableCompositeDisposable
|
||||
{
|
||||
int disposedCallCount = -1;
|
||||
private volatile IDisposable _disposable1;
|
||||
private volatile IDisposable _disposable2;
|
||||
|
||||
public Binary(IDisposable disposable1, IDisposable disposable2)
|
||||
{
|
||||
_disposable1 = disposable1;
|
||||
_disposable2 = disposable2;
|
||||
}
|
||||
|
||||
public override bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return disposedCallCount != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Interlocked.Increment(ref disposedCallCount) == 0)
|
||||
{
|
||||
_disposable1.Dispose();
|
||||
_disposable2.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Trinary : StableCompositeDisposable
|
||||
{
|
||||
int disposedCallCount = -1;
|
||||
private volatile IDisposable _disposable1;
|
||||
private volatile IDisposable _disposable2;
|
||||
private volatile IDisposable _disposable3;
|
||||
|
||||
public Trinary(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3)
|
||||
{
|
||||
_disposable1 = disposable1;
|
||||
_disposable2 = disposable2;
|
||||
_disposable3 = disposable3;
|
||||
}
|
||||
|
||||
public override bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return disposedCallCount != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Interlocked.Increment(ref disposedCallCount) == 0)
|
||||
{
|
||||
_disposable1.Dispose();
|
||||
_disposable2.Dispose();
|
||||
_disposable3.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Quaternary : StableCompositeDisposable
|
||||
{
|
||||
int disposedCallCount = -1;
|
||||
private volatile IDisposable _disposable1;
|
||||
private volatile IDisposable _disposable2;
|
||||
private volatile IDisposable _disposable3;
|
||||
private volatile IDisposable _disposable4;
|
||||
|
||||
public Quaternary(IDisposable disposable1, IDisposable disposable2, IDisposable disposable3, IDisposable disposable4)
|
||||
{
|
||||
_disposable1 = disposable1;
|
||||
_disposable2 = disposable2;
|
||||
_disposable3 = disposable3;
|
||||
_disposable4 = disposable4;
|
||||
}
|
||||
|
||||
public override bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return disposedCallCount != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Interlocked.Increment(ref disposedCallCount) == 0)
|
||||
{
|
||||
_disposable1.Dispose();
|
||||
_disposable2.Dispose();
|
||||
_disposable3.Dispose();
|
||||
_disposable4.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NAry : StableCompositeDisposable
|
||||
{
|
||||
int disposedCallCount = -1;
|
||||
private volatile List<IDisposable> _disposables;
|
||||
|
||||
public NAry(IDisposable[] disposables)
|
||||
: this((IEnumerable<IDisposable>)disposables)
|
||||
{
|
||||
}
|
||||
|
||||
public NAry(IEnumerable<IDisposable> disposables)
|
||||
{
|
||||
_disposables = new List<IDisposable>(disposables);
|
||||
|
||||
//
|
||||
// Doing this on the list to avoid duplicate enumeration of disposables.
|
||||
//
|
||||
if (_disposables.Contains(null)) throw new ArgumentException("Disposables can't contains null", "disposables");
|
||||
}
|
||||
|
||||
public override bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return disposedCallCount != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Interlocked.Increment(ref disposedCallCount) == 0)
|
||||
{
|
||||
foreach (var d in _disposables)
|
||||
{
|
||||
d.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NAryUnsafe : StableCompositeDisposable
|
||||
{
|
||||
int disposedCallCount = -1;
|
||||
private volatile IDisposable[] _disposables;
|
||||
|
||||
public NAryUnsafe(IDisposable[] disposables)
|
||||
{
|
||||
_disposables = disposables;
|
||||
}
|
||||
|
||||
public override bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return disposedCallCount != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Interlocked.Increment(ref disposedCallCount) == 0)
|
||||
{
|
||||
var len = _disposables.Length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
_disposables[i].Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a9cd9fa22bc6a5439484581f5049cf8
|
||||
timeCreated: 1455373898
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user