From 3e58bcdd2239ab4523b74fb309ae92326c58468d Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Fri, 31 Aug 2018 22:08:44 +0300 Subject: [PATCH 01/57] CHANGELOG update --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ca4ee..a8df8f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). ----------------------- -## [0.9.6] - unreleased +## [0.9.7] - unreleased + +----------------------- +## [0.9.6] - 2018.08.31 ### Added - Added `Play`/`Wait` extension methods for `Animation` and `Animator`. From b8c20b5daf7230716da216b9b009515241c5a12a Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sat, 1 Sep 2018 22:02:03 +0300 Subject: [PATCH 02/57] Added possibility to end operations with an error message (an Exception instance is created internally, saves user a few strokes) --- .../Api/Core/AsyncResult.Helpers.cs | 58 +++++++++++++++ src/UnityFx.Async/Api/Core/AsyncResult.cs | 29 ++++++++ .../Api/Extensions/AsyncExtensions.cs | 70 +++++++++++++++++++ 3 files changed, 157 insertions(+) diff --git a/src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs b/src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs index a27bfe4..82c1cf6 100644 --- a/src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs +++ b/src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs @@ -140,12 +140,40 @@ public static AsyncResult FromCanceled(object asyncState) return new AsyncResult(AsyncOperationStatus.Canceled, asyncState); } + /// + /// Creates a that has completed with the specified error message. + /// + /// An exception message. + /// A faulted operation. + /// + /// + /// + public static AsyncResult FromException(string message) + { + return new AsyncResult(new Exception(message), null); + } + + /// + /// Creates a that has completed with a specified error message. + /// + /// An exception message. + /// User-defined data returned by . + /// A faulted operation. + /// + /// + /// + public static AsyncResult FromException(string message, object asyncState) + { + return new AsyncResult(new Exception(message), asyncState); + } + /// /// Creates a that has completed with a specified exception. /// /// The exception to complete the operation with. /// A faulted operation. /// + /// /// /// /// @@ -161,6 +189,7 @@ public static AsyncResult FromException(Exception exception) /// User-defined data returned by . /// A faulted operation. /// + /// /// /// /// @@ -198,11 +227,39 @@ public static AsyncResult FromExceptions(IEnumerable exceptions, obje return new AsyncResult(exceptions, asyncState); } + /// + /// Creates a that has completed with a specified error message. + /// + /// An exception message. + /// A faulted operation. + /// + /// + /// + public static AsyncResult FromException(string message) + { + return new AsyncResult(new Exception(message), null); + } + + /// + /// Creates a that has completed with a specified error message. + /// + /// An exception message. + /// User-defined data returned by . + /// A faulted operation. + /// + /// + /// + public static AsyncResult FromException(string message, object asyncState) + { + return new AsyncResult(new Exception(message), asyncState); + } + /// /// Creates a that has completed with a specified exception. /// /// The exception to complete the operation with. /// A faulted operation. + /// /// /// /// @@ -218,6 +275,7 @@ public static AsyncResult FromException(Exception exception) /// The exception to complete the operation with. /// User-defined data returned by . /// A faulted operation. + /// /// /// /// diff --git a/src/UnityFx.Async/Api/Core/AsyncResult.cs b/src/UnityFx.Async/Api/Core/AsyncResult.cs index 3a6fa6b..74f199e 100644 --- a/src/UnityFx.Async/Api/Core/AsyncResult.cs +++ b/src/UnityFx.Async/Api/Core/AsyncResult.cs @@ -387,6 +387,35 @@ protected internal bool TrySetCanceled(bool completedSynchronously) return false; } + /// + /// Attempts to transition the operation into the . The method calls + /// passing a new instance with the specified . + /// + /// An exception message. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. + /// + protected internal bool TrySetException(string message) + { + return TrySetException(new Exception(message), false); + } + + /// + /// Attempts to transition the operation into the . The method calls + /// passing a new instance with the specified . + /// + /// An exception message. + /// Value of the property. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. + /// + protected internal bool TrySetException(string message, bool completedSynchronously) + { + return TrySetException(new Exception(message), completedSynchronously); + } + /// /// Attempts to transition the operation into the (or /// if the exception is ) state. diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs index 2b9769f..95db74e 100644 --- a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs @@ -314,6 +314,76 @@ public static void SetCanceled(this IAsyncCompletionSource com } } + /// + /// Attempts to transition the underlying into the state. + /// + /// The completion source instance. + /// An exception message. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. + /// + /// + /// + public static bool TrySetException(this IAsyncCompletionSource completionSource, string message) + { + return completionSource.TrySetException(new Exception(message)); + } + + /// + /// Attempts to transition the underlying into the state. + /// + /// The completion source instance. + /// An exception message. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. + /// + /// + /// + public static bool TrySetException(this IAsyncCompletionSource completionSource, string message) + { + return completionSource.TrySetException(new Exception(message)); + } + + /// + /// Transitions the underlying into the state. + /// + /// The completion source instance. + /// An exception message. + /// Thrown if is . + /// Thrown if the transition fails. + /// Thrown is the operation is disposed. + /// + /// + /// + public static void SetException(this IAsyncCompletionSource completionSource, string message) + { + if (!completionSource.TrySetException(new Exception(message))) + { + throw new InvalidOperationException(); + } + } + + /// + /// Transitions the underlying into the state. + /// + /// The completion source instance. + /// An exception message. + /// Thrown if is . + /// Thrown if the transition fails. + /// Thrown is the operation is disposed. + /// + /// + /// + public static void SetException(this IAsyncCompletionSource completionSource, string message) + { + if (!completionSource.TrySetException(new Exception(message))) + { + throw new InvalidOperationException(); + } + } + /// /// Transitions the underlying into the state. /// From 2187669ca817688b31bd43a0031899585c06bd30 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sat, 1 Sep 2018 22:44:13 +0300 Subject: [PATCH 03/57] Fixed compile errors in AsyncUtility on Unity 5 --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 221a45a..2b5619d 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -4,7 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; -#if !NET_2_0 && !NET_2_0_SUBSET +#if NET_4_6 || NET_STANDARD_2_0 using System.Collections.Concurrent; #endif using System.Threading; @@ -419,10 +419,10 @@ private sealed class AsyncRootBehaviour : MonoBehaviour private SynchronizationContext _context; private SynchronizationContext _mainThreadContext; -#if NET_2_0 || NET_2_0_SUBSET - private Queue _actionQueue; -#else +#if NET_4_6 || NET_STANDARD_2_0 private ConcurrentQueue _actionQueue; +#else + private Queue _actionQueue; #endif #endregion @@ -602,14 +602,10 @@ private void Awake() _mainThreadContext = currentContext; } -#if NET_2_0 || NET_2_0_SUBSET - - _actionQueue = new Queue(); - -#else - +#if NET_4_6 || NET_STANDARD_2_0 _actionQueue = new ConcurrentQueue(); - +#else + _actionQueue = new Queue(); #endif } @@ -680,7 +676,25 @@ private void Update() } } -#if NET_2_0 || NET_2_0_SUBSET +#if NET_4_6 || NET_STANDARD_2_0 + + InvokeResult invokeResult; + + while (_actionQueue.TryDequeue(out invokeResult)) + { + try + { + invokeResult.Start(); + invokeResult.SetCompleted(); + } + catch (Exception e) + { + invokeResult.SetException(e); + Debug.LogException(e, this); + } + } + +#else if (_actionQueue.Count > 0) { @@ -704,22 +718,6 @@ private void Update() } } -#else - - while (_actionQueue.TryDequeue(out var invokeResult)) - { - try - { - invokeResult.Start(); - invokeResult.SetCompleted(); - } - catch (Exception e) - { - invokeResult.SetException(e); - Debug.LogException(e, this); - } - } - #endif } @@ -770,15 +768,6 @@ private void OnDestroy() SynchronizationContext.SetSynchronizationContext(null); } -#if NET_2_0 || NET_2_0_SUBSET - - lock (_actionQueue) - { - _actionQueue.Clear(); - } - -#endif - _mainThreadContext = null; _context = null; } From 27719c1532dcea4f4e14f60d62d3f2761dd60877 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 2 Sep 2018 00:01:05 +0300 Subject: [PATCH 04/57] Changed compiler version used for UnityFx.Async.AssetsStore project to match Unity default compiler --- src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj b/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj index 05bb96d..d193d6b 100644 --- a/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj +++ b/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj @@ -17,6 +17,7 @@ false true ../CodingConventions/Cs/CsharpRules.ruleset + 6 From 81ba5e6d9d37cf37dc6332b6d30d15293d48093c Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 2 Sep 2018 23:29:47 +0300 Subject: [PATCH 05/57] Added error handling to AsyncOperationResult{T} --- .../Scripts/Helpers/AsyncOperationResult{T}.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/AsyncOperationResult{T}.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/AsyncOperationResult{T}.cs index e44cf52..1e1ff1f 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/AsyncOperationResult{T}.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/AsyncOperationResult{T}.cs @@ -116,7 +116,15 @@ private void OnSetCompleted(AsyncOperation op) try { var result = GetResult(op); - TrySetResult(result); + + if (result != null) + { + TrySetResult(result); + } + else + { + throw new NullReferenceException(); + } } catch (Exception e) { From e36b1cc18175accfc31f8bf732f3ea80ee62d605 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 4 Sep 2018 17:06:13 +0300 Subject: [PATCH 06/57] Changed project structure --- src/UnityFx.Async/Api/{Core => }/AsyncContinuationOptions.cs | 0 src/UnityFx.Async/Api/{Core => }/AsyncCreationOptions.cs | 0 src/UnityFx.Async/Api/{Core => }/AsyncLazy.cs | 0 src/UnityFx.Async/Api/{Core => }/AsyncOperationStatus.cs | 0 .../Implementation/{ => Private}/Common/AssemblyInfo.cs | 0 .../Implementation/{ => Private}/Common/Constants.cs | 0 .../Implementation/{ => Private}/Common/VoidResult.cs | 0 .../{ => Private}/Continuations/ContinueWithResult{T,U}.cs | 0 .../Continuations/Promises/CatchResult{T,TException}.cs | 0 .../{ => Private}/Continuations/Promises/DoneResult{T}.cs | 0 .../{ => Private}/Continuations/Promises/FinallyResult{T}.cs | 0 .../{ => Private}/Continuations/Promises/RebindResult{T,U}.cs | 0 .../{ => Private}/Continuations/Promises/ThenAllResult{T,U}.cs | 0 .../{ => Private}/Continuations/Promises/ThenAnyResult{T,U}.cs | 0 .../{ => Private}/Continuations/Promises/ThenResult{T,U}.cs | 0 .../Implementation/{ => Private}/Continuations/UnwrapResult{T}.cs | 0 .../Implementation/{ => Private}/Core/CallbackData.cs | 0 .../Implementation/{ => Private}/Core/CallbackUtility.cs | 0 .../Implementation/{ => Private}/Core/IAsyncCallbackCollection.cs | 0 .../Implementation/{ => Private}/Core/ListCallbackCollection.cs | 0 .../{ => Private}/Core/MultiContextCallbackCollection.cs | 0 .../{ => Private}/Core/SingleContextCallbackCollection.cs | 0 .../{ => Private}/Observable/AsyncObservableResult{T}.cs | 0 .../{ => Private}/Observable/AsyncObservableSubscription{T}.cs | 0 .../Implementation/{ => Private}/Specialized/RetryResult{T}.cs | 0 .../Implementation/{ => Private}/Specialized/TimerDelayResult.cs | 0 .../{ => Private}/Specialized/TimerRetryResult{T}.cs | 0 .../{ => Private}/Specialized/UpdatableDelayResult.cs | 0 .../{ => Private}/Specialized/UpdatableRetryResult{T}.cs | 0 .../Implementation/{ => Private}/Specialized/WhenAllResult{T}.cs | 0 .../Implementation/{ => Private}/Specialized/WhenAnyResult{T}.cs | 0 .../{Api/Core => Implementation/Public}/AsyncCompletionSource.cs | 0 .../Public}/AsyncCompletionSource{TResult}.cs | 0 .../{Api/Core => Implementation/Public}/AsyncResult.Events.cs | 0 .../{Api/Core => Implementation/Public}/AsyncResult.Helpers.cs | 0 .../{Api/Core => Implementation/Public}/AsyncResult.cs | 0 .../{Api/Core => Implementation/Public}/AsyncResultQueue{T}.cs | 0 .../{Api/Core => Implementation/Public}/AsyncResult{TResult}.cs | 0 .../{Api/Core => Implementation/Public}/AsyncUpdateSource.cs | 0 39 files changed, 0 insertions(+), 0 deletions(-) rename src/UnityFx.Async/Api/{Core => }/AsyncContinuationOptions.cs (100%) rename src/UnityFx.Async/Api/{Core => }/AsyncCreationOptions.cs (100%) rename src/UnityFx.Async/Api/{Core => }/AsyncLazy.cs (100%) rename src/UnityFx.Async/Api/{Core => }/AsyncOperationStatus.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Common/AssemblyInfo.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Common/Constants.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Common/VoidResult.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/ContinueWithResult{T,U}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/CatchResult{T,TException}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/DoneResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/FinallyResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/RebindResult{T,U}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/ThenAllResult{T,U}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/ThenAnyResult{T,U}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/Promises/ThenResult{T,U}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Continuations/UnwrapResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/CallbackData.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/CallbackUtility.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/IAsyncCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/ListCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/MultiContextCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Core/SingleContextCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Observable/AsyncObservableResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Observable/AsyncObservableSubscription{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/RetryResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/TimerDelayResult.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/TimerRetryResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/UpdatableDelayResult.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/UpdatableRetryResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/WhenAllResult{T}.cs (100%) rename src/UnityFx.Async/Implementation/{ => Private}/Specialized/WhenAnyResult{T}.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncCompletionSource.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncCompletionSource{TResult}.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncResult.Events.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncResult.Helpers.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncResult.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncResultQueue{T}.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncResult{TResult}.cs (100%) rename src/UnityFx.Async/{Api/Core => Implementation/Public}/AsyncUpdateSource.cs (100%) diff --git a/src/UnityFx.Async/Api/Core/AsyncContinuationOptions.cs b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncContinuationOptions.cs rename to src/UnityFx.Async/Api/AsyncContinuationOptions.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncCreationOptions.cs b/src/UnityFx.Async/Api/AsyncCreationOptions.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncCreationOptions.cs rename to src/UnityFx.Async/Api/AsyncCreationOptions.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncLazy.cs b/src/UnityFx.Async/Api/AsyncLazy.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncLazy.cs rename to src/UnityFx.Async/Api/AsyncLazy.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncOperationStatus.cs b/src/UnityFx.Async/Api/AsyncOperationStatus.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncOperationStatus.cs rename to src/UnityFx.Async/Api/AsyncOperationStatus.cs diff --git a/src/UnityFx.Async/Implementation/Common/AssemblyInfo.cs b/src/UnityFx.Async/Implementation/Private/Common/AssemblyInfo.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Common/AssemblyInfo.cs rename to src/UnityFx.Async/Implementation/Private/Common/AssemblyInfo.cs diff --git a/src/UnityFx.Async/Implementation/Common/Constants.cs b/src/UnityFx.Async/Implementation/Private/Common/Constants.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Common/Constants.cs rename to src/UnityFx.Async/Implementation/Private/Common/Constants.cs diff --git a/src/UnityFx.Async/Implementation/Common/VoidResult.cs b/src/UnityFx.Async/Implementation/Private/Common/VoidResult.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Common/VoidResult.cs rename to src/UnityFx.Async/Implementation/Private/Common/VoidResult.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/ContinueWithResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/ContinueWithResult{T,U}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/CatchResult{T,TException}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/CatchResult{T,TException}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/CatchResult{T,TException}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/CatchResult{T,TException}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/DoneResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/DoneResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/DoneResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/DoneResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/FinallyResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/FinallyResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/FinallyResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/FinallyResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/RebindResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/RebindResult{T,U}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/RebindResult{T,U}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/RebindResult{T,U}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/ThenAllResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenAllResult{T,U}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/ThenAllResult{T,U}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenAllResult{T,U}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/ThenAnyResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenAnyResult{T,U}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/ThenAnyResult{T,U}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenAnyResult{T,U}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/Promises/ThenResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenResult{T,U}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/Promises/ThenResult{T,U}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/Promises/ThenResult{T,U}.cs diff --git a/src/UnityFx.Async/Implementation/Continuations/UnwrapResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/UnwrapResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Continuations/UnwrapResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Continuations/UnwrapResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Core/CallbackData.cs b/src/UnityFx.Async/Implementation/Private/Core/CallbackData.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/CallbackData.cs rename to src/UnityFx.Async/Implementation/Private/Core/CallbackData.cs diff --git a/src/UnityFx.Async/Implementation/Core/CallbackUtility.cs b/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/CallbackUtility.cs rename to src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs diff --git a/src/UnityFx.Async/Implementation/Core/IAsyncCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Core/IAsyncCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/IAsyncCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Core/IAsyncCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Core/ListCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Core/ListCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/ListCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Core/ListCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Core/MultiContextCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Core/MultiContextCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/MultiContextCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Core/MultiContextCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Core/SingleContextCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Core/SingleContextCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Core/SingleContextCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Core/SingleContextCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Observable/AsyncObservableResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Observable/AsyncObservableResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Observable/AsyncObservableResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Observable/AsyncObservableResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Observable/AsyncObservableSubscription{T}.cs b/src/UnityFx.Async/Implementation/Private/Observable/AsyncObservableSubscription{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Observable/AsyncObservableSubscription{T}.cs rename to src/UnityFx.Async/Implementation/Private/Observable/AsyncObservableSubscription{T}.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/RetryResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/RetryResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/TimerDelayResult.cs b/src/UnityFx.Async/Implementation/Private/Specialized/TimerDelayResult.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/TimerDelayResult.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/TimerDelayResult.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/TimerRetryResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/TimerRetryResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/TimerRetryResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/TimerRetryResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/UpdatableDelayResult.cs b/src/UnityFx.Async/Implementation/Private/Specialized/UpdatableDelayResult.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/UpdatableDelayResult.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/UpdatableDelayResult.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/UpdatableRetryResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/UpdatableRetryResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/UpdatableRetryResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/UpdatableRetryResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/WhenAllResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/WhenAllResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/WhenAllResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/WhenAllResult{T}.cs diff --git a/src/UnityFx.Async/Implementation/Specialized/WhenAnyResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/WhenAnyResult{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Specialized/WhenAnyResult{T}.cs rename to src/UnityFx.Async/Implementation/Private/Specialized/WhenAnyResult{T}.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncCompletionSource.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncCompletionSource.cs rename to src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncCompletionSource{TResult}.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncCompletionSource{TResult}.cs rename to src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncResult.Events.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncResult.Events.cs rename to src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncResult.Helpers.cs rename to src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncResult.cs rename to src/UnityFx.Async/Implementation/Public/AsyncResult.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncResultQueue{T}.cs b/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncResultQueue{T}.cs rename to src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncResult{TResult}.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncResult{TResult}.cs rename to src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs diff --git a/src/UnityFx.Async/Api/Core/AsyncUpdateSource.cs b/src/UnityFx.Async/Implementation/Public/AsyncUpdateSource.cs similarity index 100% rename from src/UnityFx.Async/Api/Core/AsyncUpdateSource.cs rename to src/UnityFx.Async/Implementation/Public/AsyncUpdateSource.cs From 42e19d0bfb46aedc98464a39d0233a95830bfd71 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 5 Sep 2018 12:51:21 +0300 Subject: [PATCH 07/57] Removed samples --- .../LoadTextureHelper.UseCases.Await.cs | 39 ---------------- ...xtureHelper.UseCases.CompletionCallback.cs | 33 ------------- .../LoadTextureHelper.UseCases.Join.cs | 46 ------------------- .../LoadTextureHelper.UseCases.Yield.cs | 33 ------------- .../Samples/LoadTextureHelper.cs | 40 ---------------- 5 files changed, 191 deletions(-) delete mode 100644 src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Await.cs delete mode 100644 src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.CompletionCallback.cs delete mode 100644 src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Join.cs delete mode 100644 src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Yield.cs delete mode 100644 src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.cs diff --git a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Await.cs b/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Await.cs deleted file mode 100644 index 4bae280..0000000 --- a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Await.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using System; -#if NET_4_6 || NET_STANDARD_2_0 -using System.Threading.Tasks; -#endif - -using UnityEngine; - -namespace UnityFx.Async.Samples -{ - partial class LoadTextureHelper - { -#if SHOULD_NEVER_GET_HERE //NET_4_6 || NET_STANDARD_2_0 - - /// - /// Waits for the in with await. - /// - public async Task WaitForLoadOperationWithAwait(string textureUrl) - { - try - { - var texture = await LoadTextureAsync(textureUrl); - Debug.Log("Yay! The texture is loaded!"); - } - catch (OperationCanceledException) - { - Debug.LogWarning("The operation was canceled."); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - -#endif - } -} diff --git a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.CompletionCallback.cs b/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.CompletionCallback.cs deleted file mode 100644 index 290b753..0000000 --- a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.CompletionCallback.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using UnityEngine; - -namespace UnityFx.Async.Samples -{ - partial class LoadTextureHelper - { - /// - /// Waits for the in completion callback. - /// - public void WaitForLoadOperationInCompletionCallback(string textureUrl) - { - LoadTextureAsync(textureUrl).AddCompletionCallback(op => - { - if (op.IsCompletedSuccessfully) - { - var texture = (op as IAsyncOperation).Result; - Debug.Log("Yay! Texture " + texture.name + " loaded."); - } - else if (op.IsFaulted) - { - Debug.LogException(op.Exception); - } - else if (op.IsCanceled) - { - Debug.LogWarning("The operation was canceled."); - } - }); - } - } -} diff --git a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Join.cs b/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Join.cs deleted file mode 100644 index 92d7bc3..0000000 --- a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Join.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using System; -using System.Threading; -using UnityEngine; - -namespace UnityFx.Async.Samples -{ - partial class LoadTextureHelper - { - /// - /// Waits for the in a thread. - /// - public void WaitForLoadOperationInAnotherThread(string textureUrl) - { - var loadOp = LoadTextureAsync(textureUrl); - - ThreadPool.QueueUserWorkItem( - args => - { - // Dispose the opepration when it is not needed. - using (var op = args as IAsyncOperation) - { - try - { - // Block the thread until the result is available. - var texture = op.Join(); - - // The texture is loaded - Debug.Log(texture); - } - catch (OperationCanceledException) - { - // The operation was canceled - } - catch (Exception) - { - // Load failed - } - } - }, - loadOp); - } - } -} diff --git a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Yield.cs b/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Yield.cs deleted file mode 100644 index fcbc0a0..0000000 --- a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.UseCases.Yield.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using System.Collections; -using UnityEngine; - -namespace UnityFx.Async.Samples -{ - partial class LoadTextureHelper - { - /// - /// Waits for the in Unity coroutine. - /// - public IEnumerator WaitForLoadOperationInCoroutine(string textureUrl) - { - var op = LoadTextureAsync(textureUrl); - yield return op; - - if (op.IsCompletedSuccessfully) - { - Debug.Log("Yay!"); - } - else if (op.IsFaulted) - { - Debug.LogException(op.Exception); - } - else if (op.IsCanceled) - { - Debug.LogWarning("The operation was canceled."); - } - } - } -} diff --git a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.cs b/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.cs deleted file mode 100644 index 129f6ba..0000000 --- a/src/UnityFx.Async.AssetStore/Assets/UnityFx.Async/Samples/LoadTextureHelper.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using System; -using System.Collections; -using UnityEngine; - -namespace UnityFx.Async.Samples -{ - /// - /// A that demonstrates wrapping Unity3d web requests in Task-based Asynchronous Pattern manner. - /// - public partial class LoadTextureHelper : MonoBehaviour - { - /// - /// Asynchronously loads a from the specified URL. - /// - public IAsyncOperation LoadTextureAsync(string textureUrl) - { - var result = new AsyncCompletionSource(); - StartCoroutine(LoadTextureInternal(result, textureUrl)); - return result.Operation; - } - - private IEnumerator LoadTextureInternal(IAsyncCompletionSource op, string textureUrl) - { - var www = new WWW(textureUrl); - yield return www; - - if (!string.IsNullOrEmpty(www.error)) - { - op.SetException(new Exception(www.error)); - } - else - { - op.SetResult(www.texture); - } - } - } -} From 28dbb5ca46e5f9aad48e79314edfb457ad6436d0 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 11 Sep 2018 19:12:54 +0300 Subject: [PATCH 08/57] Added benchmarks project --- .../Benchmarks/ConstructorBenchmarks.cs | 40 ++++++++++++++++++ .../Benchmarks/ContinueWithBenchmarks.cs | 41 +++++++++++++++++++ src/UnityFx.Async.Benchmarks/Program.cs | 17 ++++++++ .../UnityFx.Async.Benchmarks.csproj | 17 ++++++++ src/UnityFx.Async.sln | 6 +++ 5 files changed, 121 insertions(+) create mode 100644 src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs create mode 100644 src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs create mode 100644 src/UnityFx.Async.Benchmarks/Program.cs create mode 100644 src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs new file mode 100644 index 0000000..0ac065b --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs @@ -0,0 +1,40 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; + +namespace UnityFx.Async.Benchmarks +{ + [MemoryDiagnoser] + public class ConstructorBenchmarks + { + private readonly AsyncCallback _asyncCallback = op => { }; + private readonly Action _action = () => { }; + + [Benchmark] + public object CreateAsync() + { + return new AsyncResult(_asyncCallback, null); + } + + [Benchmark] + public object CreateAsyncCompletionSource() + { + return new AsyncCompletionSource(); + } + + [Benchmark] + public object CreateTask() + { + return new Task(_action); + } + + [Benchmark] + public object CreateTaskCompletionSource() + { + return new TaskCompletionSource(); + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs new file mode 100644 index 0000000..fde5ec9 --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs @@ -0,0 +1,41 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; + +namespace UnityFx.Async.Benchmarks +{ + [MemoryDiagnoser] + public class ContinueWithBenchmarks + { + private readonly Action> _action1 = op => { }; + private readonly Action> _action2 = task => { }; + + [Params(1, 2, 4, 8, 16)] + public int N { get; set; } + + [Benchmark] + public void Async_ContinueWith() + { + var acp = new AsyncCompletionSource(); + + for (int i = 0; i < N; i++) + { + acp.Operation.ContinueWith(_action1); + } + } + + [Benchmark] + public void Task_ContinueWith() + { + var tcs = new TaskCompletionSource(); + + for (int i = 0; i < N; i++) + { + tcs.Task.ContinueWith(_action2); + } + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/Program.cs b/src/UnityFx.Async.Benchmarks/Program.cs new file mode 100644 index 0000000..2f0eddf --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Program.cs @@ -0,0 +1,17 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using BenchmarkDotNet.Running; + +namespace UnityFx.Async.Benchmarks +{ + public class Program + { + public static void Main(string[] args) + { + //BenchmarkRunner.Run(); + BenchmarkRunner.Run(); + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj b/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj new file mode 100644 index 0000000..d97dd97 --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj @@ -0,0 +1,17 @@ + + + + net46 + Exe + false + + + + + + + + + + + diff --git a/src/UnityFx.Async.sln b/src/UnityFx.Async.sln index d99ad47..ddcf973 100644 --- a/src/UnityFx.Async.sln +++ b/src/UnityFx.Async.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityFx.Async.Tests", "Unit EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityFx.Async.AssetStore", "UnityFx.Async.AssetStore\UnityFx.Async.AssetStore.csproj", "{6ACDE97B-C722-4135-894A-340F2213514D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityFx.Async.Benchmarks", "UnityFx.Async.Benchmarks\UnityFx.Async.Benchmarks.csproj", "{EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {6ACDE97B-C722-4135-894A-340F2213514D}.Debug|Any CPU.Build.0 = Debug|Any CPU {6ACDE97B-C722-4135-894A-340F2213514D}.Release|Any CPU.ActiveCfg = Release|Any CPU {6ACDE97B-C722-4135-894A-340F2213514D}.Release|Any CPU.Build.0 = Release|Any CPU + {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 9fb329a3b7c90979d97d4c4a191b226745566c6e Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 12 Sep 2018 15:28:20 +0300 Subject: [PATCH 09/57] Benchmarks update, added comparison to RSG.Promise --- .../Benchmarks/CallbackBenchmarks.cs | 76 +++++++++++++++++++ .../Benchmarks/ConstructorBenchmarks.cs | 22 ++---- .../Benchmarks/ContinueWithBenchmarks.cs | 41 ---------- .../Benchmarks/ThenBenchmarks.cs | 74 ++++++++++++++++++ src/UnityFx.Async.Benchmarks/Config.cs | 22 ++++++ src/UnityFx.Async.Benchmarks/Program.cs | 6 +- .../UnityFx.Async.Benchmarks.csproj | 1 + 7 files changed, 185 insertions(+), 57 deletions(-) create mode 100644 src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs delete mode 100644 src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs create mode 100644 src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs create mode 100644 src/UnityFx.Async.Benchmarks/Config.cs diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs new file mode 100644 index 0000000..11afda3 --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs @@ -0,0 +1,76 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.ComponentModel; +using BenchmarkDotNet.Attributes; + +namespace UnityFx.Async.Benchmarks +{ + [MemoryDiagnoser] + public class CallbackBenchmarks + { + private readonly Action _action = op => { }; + private readonly Action _action2 = op => { }; + private readonly AsyncCompletedEventHandler _eventHandler = (sender, args) => { }; + private readonly ProgressChangedEventHandler _eventHandler2 = (sender, args) => { }; + + [Params(1, 2, 4, 8)] + public int N { get; set; } + + [Benchmark(Baseline = true)] + public void Add_Baseline() + { + var action = new Action(_action); + + for (var i = 0; i < N; i++) + { + action += _action; + } + } + + [Benchmark] + public void AddCompletionCallback() + { + var op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op.AddCompletionCallback(_action); + } + } + + [Benchmark] + public void AddCompletionEvent() + { + var op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op.Completed += _eventHandler; + } + } + + [Benchmark] + public void AddProgressCallback() + { + var op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op.AddProgressCallback(_action2); + } + } + + [Benchmark] + public void AddProgressEvent() + { + var op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op.ProgressChanged += _eventHandler2; + } + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs index 0ac065b..c7406e9 100644 --- a/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs @@ -2,8 +2,8 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; -using System.Threading.Tasks; using BenchmarkDotNet.Attributes; +using RSG; namespace UnityFx.Async.Benchmarks { @@ -13,28 +13,22 @@ public class ConstructorBenchmarks private readonly AsyncCallback _asyncCallback = op => { }; private readonly Action _action = () => { }; - [Benchmark] - public object CreateAsync() - { - return new AsyncResult(_asyncCallback, null); - } - - [Benchmark] - public object CreateAsyncCompletionSource() + [Benchmark(Baseline = true)] + public object Create_Baseline() { - return new AsyncCompletionSource(); + return new Action(_action); } [Benchmark] - public object CreateTask() + public object Create_Async() { - return new Task(_action); + return new AsyncResult(); } [Benchmark] - public object CreateTaskCompletionSource() + public object Create_RsgPromise() { - return new TaskCompletionSource(); + return new Promise(); } } } diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs deleted file mode 100644 index fde5ec9..0000000 --- a/src/UnityFx.Async.Benchmarks/Benchmarks/ContinueWithBenchmarks.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -using System; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; - -namespace UnityFx.Async.Benchmarks -{ - [MemoryDiagnoser] - public class ContinueWithBenchmarks - { - private readonly Action> _action1 = op => { }; - private readonly Action> _action2 = task => { }; - - [Params(1, 2, 4, 8, 16)] - public int N { get; set; } - - [Benchmark] - public void Async_ContinueWith() - { - var acp = new AsyncCompletionSource(); - - for (int i = 0; i < N; i++) - { - acp.Operation.ContinueWith(_action1); - } - } - - [Benchmark] - public void Task_ContinueWith() - { - var tcs = new TaskCompletionSource(); - - for (int i = 0; i < N; i++) - { - tcs.Task.ContinueWith(_action2); - } - } - } -} diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs new file mode 100644 index 0000000..1f4b7c1 --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs @@ -0,0 +1,74 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using BenchmarkDotNet.Attributes; +using RSG; +using UnityFx.Async.Promises; + +namespace UnityFx.Async.Benchmarks +{ + [MemoryDiagnoser] + public class ThenBenchmarks + { + private readonly Action _action = () => { }; + + [Params(1, 2, 4, 8)] + public int N { get; set; } + + [Benchmark(Baseline = true)] + public void Then_Baseline() + { + var action = new Action(_action); + + for (var i = 0; i < N; i++) + { + action += _action; + } + } + + [Benchmark] + public void Then_Async() + { + IAsyncOperation op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op = op.Then(_action); + } + } + + [Benchmark] + public void Then_Async_2() + { + IAsyncOperation op = new AsyncResult(); + + for (var i = 0; i < N; i++) + { + op.Then(_action); + } + } + + [Benchmark] + public void Then_RsgPromise() + { + IPromise op = new Promise(); + + for (var i = 0; i < N; i++) + { + op = op.Then(_action); + } + } + + [Benchmark] + public void Then_RsgPromise_2() + { + IPromise op = new Promise(); + + for (var i = 0; i < N; i++) + { + op.Then(_action); + } + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/Config.cs b/src/UnityFx.Async.Benchmarks/Config.cs new file mode 100644 index 0000000..2c3cd49 --- /dev/null +++ b/src/UnityFx.Async.Benchmarks/Config.cs @@ -0,0 +1,22 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Linq; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Running; +using BenchmarkDotNet.Validators; + +namespace UnityFx.Async.Benchmarks +{ + public class Config : ManualConfig + { + public Config() + { + Add(JitOptimizationsValidator.DontFailOnError); + Add(DefaultConfig.Instance.GetLoggers().ToArray()); + Add(DefaultConfig.Instance.GetExporters().ToArray()); + Add(DefaultConfig.Instance.GetColumnProviders().ToArray()); + } + } +} diff --git a/src/UnityFx.Async.Benchmarks/Program.cs b/src/UnityFx.Async.Benchmarks/Program.cs index 2f0eddf..1cd253a 100644 --- a/src/UnityFx.Async.Benchmarks/Program.cs +++ b/src/UnityFx.Async.Benchmarks/Program.cs @@ -10,8 +10,10 @@ public class Program { public static void Main(string[] args) { - //BenchmarkRunner.Run(); - BenchmarkRunner.Run(); + var config = new Config(); + BenchmarkRunner.Run(config); + BenchmarkRunner.Run(config); + BenchmarkRunner.Run(config); } } } diff --git a/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj b/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj index d97dd97..b616aa4 100644 --- a/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj +++ b/src/UnityFx.Async.Benchmarks/UnityFx.Async.Benchmarks.csproj @@ -12,6 +12,7 @@ + From 476a50c94566851ffff2099ef723c827349b33e0 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Fri, 14 Sep 2018 14:12:47 +0300 Subject: [PATCH 10/57] Benchmark baselines changes --- .../Benchmarks/CallbackBenchmarks.cs | 7 ++++--- .../Benchmarks/ConstructorBenchmarks.cs | 4 ++-- src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs | 8 +++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs index 11afda3..93a5552 100644 --- a/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/CallbackBenchmarks.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; +using System.Collections.Generic; using System.ComponentModel; using BenchmarkDotNet.Attributes; @@ -19,13 +20,13 @@ public class CallbackBenchmarks public int N { get; set; } [Benchmark(Baseline = true)] - public void Add_Baseline() + public void Add_List() { - var action = new Action(_action); + var list = new List>(N); for (var i = 0; i < N; i++) { - action += _action; + list.Add(_action); } } diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs index c7406e9..c8be670 100644 --- a/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ConstructorBenchmarks.cs @@ -14,9 +14,9 @@ public class ConstructorBenchmarks private readonly Action _action = () => { }; [Benchmark(Baseline = true)] - public object Create_Baseline() + public object Create_object() { - return new Action(_action); + return new object(); } [Benchmark] diff --git a/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs b/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs index 1f4b7c1..31e46c3 100644 --- a/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs +++ b/src/UnityFx.Async.Benchmarks/Benchmarks/ThenBenchmarks.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; +using System.Collections.Generic; +using System.Threading; using BenchmarkDotNet.Attributes; using RSG; using UnityFx.Async.Promises; @@ -17,13 +19,13 @@ public class ThenBenchmarks public int N { get; set; } [Benchmark(Baseline = true)] - public void Then_Baseline() + public void Then_List() { - var action = new Action(_action); + var list = new List(N); for (var i = 0; i < N; i++) { - action += _action; + list.Add(_action); } } From 794622c32284852ca30228ff20db6769eea6fb68 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Fri, 14 Sep 2018 14:21:50 +0300 Subject: [PATCH 11/57] Optimized callback collection allocations for single-threaded applications (like Unity) --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 3 + .../Private/Core/CallbackUtility.cs | 18 +----- .../Public/AsyncResult.Events.cs | 56 ++++++++----------- .../Implementation/Public/AsyncResult.cs | 15 +++++ 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 2b5619d..d261388 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -607,6 +607,9 @@ private void Awake() #else _actionQueue = new Queue(); #endif + + // Set main thread context as default for all continuations. This saves allocations in many cases. + AsyncResult.DefaultSynchronizationContext = _mainThreadContext; } private void Update() diff --git a/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs b/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs index c74be7e..589c2cb 100644 --- a/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs +++ b/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs @@ -84,21 +84,6 @@ void InvokeInline(object callback) } } - public static void InvokeCompletionCallbackAsync(IAsyncOperation op, object continuation, SynchronizationContext syncContext) - { - Debug.Assert(op != null); - Debug.Assert(continuation != null); - - if (syncContext != null && syncContext.GetType() != typeof(SynchronizationContext)) - { - syncContext.Post(args => InvokeCompletionCallback(op, args), continuation); - } - else - { - ThreadPool.QueueUserWorkItem(args => InvokeCompletionCallback(op, args), continuation); - } - } - public static void InvokeProgressCallback(IAsyncOperation op, object callback) { Debug.Assert(op != null); @@ -138,5 +123,8 @@ public static void InvokeProgressCallback(IAsyncOperation op, object callback, S } #endregion + + #region implementation + #endregion } } diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs index 0b2bd9a..c883143 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs @@ -13,11 +13,6 @@ namespace UnityFx.Async partial class AsyncResult { #region data - - private static readonly object _callbackCompletionSentinel = new object(); - - private volatile object _callback; - #endregion #region interface @@ -100,7 +95,8 @@ public event AsyncCompletedEventHandler Completed if (!TryAddCallback(value, syncContext, true)) { - InvokeCompletionCallback(value, syncContext); + var invokeAsync = (_flags & _flagRunContinuationsAsynchronously) != 0; + CallbackUtility.InvokeCompletionCallback(this, value, syncContext, invokeAsync); } } remove @@ -148,7 +144,8 @@ public void AddCompletionCallback(Action action, Synchronizatio if (!TryAddCallback(action, syncContext, true)) { - InvokeCompletionCallback(action, syncContext); + var invokeAsync = (_flags & _flagRunContinuationsAsynchronously) != 0; + CallbackUtility.InvokeCompletionCallback(this, action, syncContext, invokeAsync); } } @@ -201,7 +198,8 @@ public void AddCompletionCallback(IAsyncContinuation continuation, Synchronizati if (!TryAddCallback(continuation, syncContext, true)) { - InvokeCompletionCallback(continuation, syncContext); + var invokeAsync = (_flags & _flagRunContinuationsAsynchronously) != 0; + CallbackUtility.InvokeCompletionCallback(this, continuation, syncContext, invokeAsync); } } @@ -348,9 +346,19 @@ private bool TryAddCallback(object callbackToAdd, SynchronizationContext syncCon { if (syncContext != null) { - var newList = CreateCallbackCollection(); - newList.AddCompletionCallback(callbackToAdd, syncContext); - newValue = newList; + // An optimization for single-threaded applications (Unity as an instance): + // in most cases we expect continuations to run on _defaultContext, and if it + // is the case we just set a flag instead of allocating callback callection. + if (syncContext == _defaultContext) + { + TrySetFlag(_flagContinueOnDefaultContext); + } + else + { + var newList = CreateCallbackCollection(); + newList.AddCompletionCallback(callbackToAdd, syncContext); + newValue = newList; + } } } else @@ -477,6 +485,7 @@ private void InvokeCallbacks() if (value != null) { var invokeAsync = (_flags & _flagRunContinuationsAsynchronously) != 0; + var continueOnDefaultContext = (_flags & _flagContinueOnDefaultContext) != 0; if (value is IAsyncCallbackCollection callbackList) { @@ -485,35 +494,14 @@ private void InvokeCallbacks() callbackList.Invoke(invokeAsync); } } - else if (invokeAsync) - { - CallbackUtility.InvokeCompletionCallbackAsync(this, value, SynchronizationContext.Current); - } else { - CallbackUtility.InvokeCompletionCallback(this, value); + var syncContext = continueOnDefaultContext ? _defaultContext : SynchronizationContext.Current; + CallbackUtility.InvokeCompletionCallback(this, value, syncContext, invokeAsync); } } } - private void InvokeCompletionCallback(object continuation, SynchronizationContext syncContext) - { - Debug.Assert(continuation != null); - - if ((_flags & _flagRunContinuationsAsynchronously) != 0) - { - CallbackUtility.InvokeCompletionCallbackAsync(this, continuation, syncContext); - } - else if (syncContext == null || syncContext == SynchronizationContext.Current) - { - CallbackUtility.InvokeCompletionCallback(this, continuation); - } - else - { - syncContext.Post(args => CallbackUtility.InvokeCompletionCallback(this, args), continuation); - } - } - private IAsyncCallbackCollection CreateCallbackCollection() { return new MultiContextCallbackCollection(this); diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index 74f199e..d3dbb14 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -48,6 +48,7 @@ public partial class AsyncResult : IAsyncOperation, IAsyncContinuation, IEnumera private const int _flagCompletedSynchronously = _flagCompleted | _flagCompletionReserved | _flagSynchronous; private const int _flagCancellationRequested = 0x00100000; private const int _flagDisposed = 0x00200000; + private const int _flagContinueOnDefaultContext = 0x00400000; private const int _flagDoNotDispose = OptionDoNotDispose << _optionsOffset; private const int _flagRunContinuationsAsynchronously = OptionRunContinuationsAsynchronously << _optionsOffset; @@ -57,18 +58,32 @@ public partial class AsyncResult : IAsyncOperation, IAsyncContinuation, IEnumera private const int _optionsMask = 0x78000000; private const int _optionsOffset = 27; + private static readonly object _callbackCompletionSentinel = new object(); private static int _idCounter; + private static SynchronizationContext _defaultContext; private readonly object _asyncState; private int _id; private Exception _exception; private EventWaitHandle _waitHandle; private volatile int _flags; + private volatile object _callback; #endregion #region interface + /// + /// Gets or sets a reference to that is used for majority of continuations. + /// + /// + /// This property is supposed to be used as allocation optimization in applications working mostly with single + /// instance (single thread) such as Unity3d applications. It should be + /// set to main thread context is most cases. + /// + /// An instance of that is used as default one. Initial value is . + public static SynchronizationContext DefaultSynchronizationContext { get => _defaultContext; set => _defaultContext = value; } + /// /// Gets the used to create this operation. /// From 726f8e059a98f86260e4f4592b154965f2548a6d Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Fri, 14 Sep 2018 14:31:02 +0300 Subject: [PATCH 12/57] CHANGELOG update --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8df8f7..4fca595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj ----------------------- ## [0.9.7] - unreleased +### Added +- Added convenience overloads for `SetException`-like methods accepting as error message string. +- Added allocation optimizations for single-threaded applications (particularly for Unity3d). See `AsyncResult.DefaultSynchronizationContext` for more info. +- Added performance benchmarks. + +### Fixed +- Fixed error handling in `AsyncOperationResult`. + +### Removed +- Removed Asset Store samples. + ----------------------- ## [0.9.6] - 2018.08.31 From 9a9ee242c71a5927c74625fbb8505d1d604ebd29 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Fri, 14 Sep 2018 15:40:21 +0300 Subject: [PATCH 13/57] Added missing error messages --- .../Api/Extensions/AsyncExtensions.cs | 32 +++++----- .../Private/Common/Constants.cs | 17 ------ .../Implementation/Private/Common/Messages.cs | 60 +++++++++++++++++++ .../Private/Specialized/RetryResult{T}.cs | 4 +- .../Public/AsyncCompletionSource.cs | 2 +- .../Public/AsyncCompletionSource{TResult}.cs | 2 +- .../Public/AsyncResult.Helpers.cs | 38 ++++++------ .../Implementation/Public/AsyncResult.cs | 6 +- .../Public/AsyncResultQueue{T}.cs | 2 +- .../Public/AsyncResult{TResult}.cs | 2 +- 10 files changed, 104 insertions(+), 61 deletions(-) delete mode 100644 src/UnityFx.Async/Implementation/Private/Common/Constants.cs create mode 100644 src/UnityFx.Async/Implementation/Private/Common/Messages.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs index 95db74e..41d8bc9 100644 --- a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs @@ -102,7 +102,7 @@ public static bool SpinUntilCompleted(this IAsyncResult op, int millisecondsTime { if (millisecondsTimeout < -1) { - throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, Constants.ErrorInvalidTimeout); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, Messages.FormatError_InvalidTimeout()); } if (millisecondsTimeout == Timeout.Infinite) @@ -127,7 +127,7 @@ public static bool SpinUntilCompleted(this IAsyncResult op, TimeSpan timeout) if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(timeout), timeout, Constants.ErrorInvalidTimeout); + throw new ArgumentOutOfRangeException(nameof(timeout), timeout, Messages.FormatError_InvalidTimeout()); } if (totalMilliseconds == Timeout.Infinite) @@ -172,7 +172,7 @@ public static bool SpinUntilCompleted(this IAsyncResult op, int millisecondsTime { if (millisecondsTimeout < -1) { - throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, Constants.ErrorInvalidTimeout); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, Messages.FormatError_InvalidTimeout()); } if (millisecondsTimeout == Timeout.Infinite) @@ -199,7 +199,7 @@ public static bool SpinUntilCompleted(this IAsyncResult op, TimeSpan timeout, Ca if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException(nameof(timeout), timeout, Constants.ErrorInvalidTimeout); + throw new ArgumentOutOfRangeException(nameof(timeout), timeout, Messages.FormatError_InvalidTimeout()); } if (totalMilliseconds == Timeout.Infinite) @@ -259,7 +259,7 @@ public static void SetProgress(this IAsyncCompletionSource completionSource, flo { if (!completionSource.TrySetProgress(progress)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -276,7 +276,7 @@ public static void SetProgress(this IAsyncCompletionSource com { if (!completionSource.TrySetProgress(progress)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -293,7 +293,7 @@ public static void SetCanceled(this IAsyncCompletionSource completionSource) { if (!completionSource.TrySetCanceled()) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -310,7 +310,7 @@ public static void SetCanceled(this IAsyncCompletionSource com { if (!completionSource.TrySetCanceled()) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -361,7 +361,7 @@ public static void SetException(this IAsyncCompletionSource completionSource, st { if (!completionSource.TrySetException(new Exception(message))) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -380,7 +380,7 @@ public static void SetException(this IAsyncCompletionSource co { if (!completionSource.TrySetException(new Exception(message))) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -399,7 +399,7 @@ public static void SetException(this IAsyncCompletionSource completionSource, Ex { if (!completionSource.TrySetException(exception)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -418,7 +418,7 @@ public static void SetException(this IAsyncCompletionSource co { if (!completionSource.TrySetException(exception)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -437,7 +437,7 @@ public static void SetExceptions(this IAsyncCompletionSource completionSource, I { if (!completionSource.TrySetExceptions(exceptions)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -456,7 +456,7 @@ public static void SetExceptions(this IAsyncCompletionSource c { if (!completionSource.TrySetExceptions(exceptions)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -473,7 +473,7 @@ public static void SetCompleted(this IAsyncCompletionSource completionSource) { if (!completionSource.TrySetCompleted()) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } @@ -491,7 +491,7 @@ public static void SetResult(this IAsyncCompletionSource compl { if (!completionSource.TrySetResult(result)) { - throw new InvalidOperationException(); + throw new InvalidOperationException(Messages.FormatError_OperationStateCannotBeChanged()); } } diff --git a/src/UnityFx.Async/Implementation/Private/Common/Constants.cs b/src/UnityFx.Async/Implementation/Private/Common/Constants.cs deleted file mode 100644 index 4cd0f5f..0000000 --- a/src/UnityFx.Async/Implementation/Private/Common/Constants.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Alexander Bogarsukov. -// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. - -namespace UnityFx.Async -{ - internal static class Constants - { - public const string ErrorListIsEmpty = "The list cannot be empty."; - public const string ErrorListElementIsNull = "The list elements cannot be null."; - public const string ErrorValueIsLessThanZero = "The valus cannot be less than zero."; - public const string ErrorOperationIsNotCompleted = "The operation should be completed."; - public const string ErrorResultNotAvailable = "The operation result is not available."; - public const string ErrorInvalidTimeout = "The timeout value specified is not valid."; - public const string ErrorInvalidProgress = "The progress value should be in range [0, 1]."; - public const string ErrorMaxNumberOrRetries = "Maximum number of retries exceeded."; - } -} diff --git a/src/UnityFx.Async/Implementation/Private/Common/Messages.cs b/src/UnityFx.Async/Implementation/Private/Common/Messages.cs new file mode 100644 index 0000000..cf4ed8e --- /dev/null +++ b/src/UnityFx.Async/Implementation/Private/Common/Messages.cs @@ -0,0 +1,60 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async +{ + internal static class Messages + { + public static string FormatError_ListIsEmpty() + { + return "The list cannot be empty."; + } + + public static string FormatError_ListElementIsNull() + { + return "The list elements cannot be null."; + } + + public static string FormatError_ValueIsLessThanZero() + { + return "The valus cannot be less than zero."; + } + + public static string FormatError_OperationIsNotCompleted() + { + return "The operation should be completed."; + } + + public static string FormatError_OperationResultIsNotAvailable() + { + return "The operation result is not available. Result value is only available for operations that have completed successfully."; + } + + public static string FormatError_OperationStateCannotBeChanged() + { + return "The operation state cannot be changed. Most likely the operation is already completed."; + } + + public static string FormatError_InvalidTimeout() + { + return "The timeout value specified is not valid. The supported range is [-1, MaxInt]."; + } + + public static string FormatError_InvalidProgress() + { + return "The progress value should be in range [0, 1]."; + } + + public static string FormatError_InvalidDelegateType(Type type) + { + return $"Invalid delegate type: {type.Name}."; + } + + public static string FormatError_MaxNumberOrRetriesReached(int numberOfRetries) + { + return "Maximum number of retries exceeded."; + } + } +} diff --git a/src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs b/src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs index 09f38ca..d1c7b6d 100644 --- a/src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs +++ b/src/UnityFx.Async/Implementation/Private/Specialized/RetryResult{T}.cs @@ -110,7 +110,7 @@ private void StartOperation() } else { - throw new InvalidOperationException("Invalid delegate type."); + throw new InvalidOperationException(Messages.FormatError_InvalidDelegateType(_opFactory.GetType())); } _op.AddCompletionCallback(this); @@ -141,7 +141,7 @@ private void Retry() else { // NOTE: should not get here. - TrySetException(new Exception(Constants.ErrorMaxNumberOrRetries)); + TrySetException(new Exception(Messages.FormatError_MaxNumberOrRetriesReached(_maxRetryCount))); } } diff --git a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs index e916168..0e142c0 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs @@ -215,7 +215,7 @@ public bool TrySetProgress(float progress) { if (progress < 0 || progress > 1) { - throw new ArgumentOutOfRangeException(nameof(progress), progress, Constants.ErrorInvalidProgress); + throw new ArgumentOutOfRangeException(nameof(progress), progress, Messages.FormatError_InvalidProgress()); } ThrowIfDisposed(); diff --git a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs index a65b64b..0398621 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs @@ -216,7 +216,7 @@ public bool TrySetProgress(float progress) { if (progress < 0 || progress > 1) { - throw new ArgumentOutOfRangeException(nameof(progress), progress, Constants.ErrorInvalidProgress); + throw new ArgumentOutOfRangeException(nameof(progress), progress, Messages.FormatError_InvalidProgress()); } ThrowIfDisposed(); diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs index 82c1cf6..bd6e214 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs @@ -627,7 +627,7 @@ public static AsyncResult Delay(int millisecondsDelay) { if (millisecondsDelay < Timeout.Infinite) { - throw new ArgumentOutOfRangeException(nameof(millisecondsDelay), millisecondsDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsDelay), millisecondsDelay, Messages.FormatError_ValueIsLessThanZero()); } if (millisecondsDelay == 0) @@ -666,7 +666,7 @@ public static AsyncResult Delay(int millisecondsDelay, IAsyncUpdateSource update if (millisecondsDelay < Timeout.Infinite) { - throw new ArgumentOutOfRangeException(nameof(millisecondsDelay), millisecondsDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsDelay), millisecondsDelay, Messages.FormatError_ValueIsLessThanZero()); } if (millisecondsDelay == 0) @@ -726,7 +726,7 @@ public static AsyncResult Delay(float secondsDelay, IAsyncUpdateSource updateSou if (secondsDelay < Timeout.Infinite) { - throw new ArgumentOutOfRangeException(nameof(secondsDelay), secondsDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(secondsDelay), secondsDelay, Messages.FormatError_ValueIsLessThanZero()); } if (secondsDelay == 0) @@ -841,12 +841,12 @@ public static AsyncResult Retry(Func opFactory, int millisecond if (millisecondsRetryDelay < 0) { - throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Messages.FormatError_ValueIsLessThanZero()); } if (maxRetryCount < 0) { - throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Messages.FormatError_ValueIsLessThanZero()); } var result = new TimerRetryResult(opFactory, millisecondsRetryDelay, maxRetryCount); @@ -879,12 +879,12 @@ public static AsyncResult Retry(Func opFactory, int millisecond if (millisecondsRetryDelay < 0) { - throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Messages.FormatError_ValueIsLessThanZero()); } if (maxRetryCount < 0) { - throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Messages.FormatError_ValueIsLessThanZero()); } var result = new UpdatableRetryResult(opFactory, millisecondsRetryDelay, maxRetryCount, updateSource); @@ -1014,12 +1014,12 @@ public static AsyncResult Retry(Func> if (millisecondsRetryDelay < 0) { - throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Messages.FormatError_ValueIsLessThanZero()); } if (maxRetryCount < 0) { - throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Messages.FormatError_ValueIsLessThanZero()); } var result = new TimerRetryResult(opFactory, millisecondsRetryDelay, maxRetryCount); @@ -1052,12 +1052,12 @@ public static AsyncResult Retry(Func> if (millisecondsRetryDelay < 0) { - throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(millisecondsRetryDelay), millisecondsRetryDelay, Messages.FormatError_ValueIsLessThanZero()); } if (maxRetryCount < 0) { - throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(maxRetryCount), maxRetryCount, Messages.FormatError_ValueIsLessThanZero()); } var result = new UpdatableRetryResult(opFactory, millisecondsRetryDelay, maxRetryCount, updateSource); @@ -1165,7 +1165,7 @@ public static AsyncResult WhenAll(IEnumerable ops) { if (op == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opList.Add(op); @@ -1201,7 +1201,7 @@ public static AsyncResult WhenAll(IEnumerable> ops) { if (op == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opList.Add(op); @@ -1242,7 +1242,7 @@ public static AsyncResult WhenAll(params IAsyncOperation[] ops) { if (ops[i] == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opArray[i] = ops[i]; @@ -1278,7 +1278,7 @@ public static AsyncResult WhenAll(params IAsyncOperation[] ops) { if (ops[i] == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opArray[i] = ops[i]; @@ -1312,7 +1312,7 @@ public static AsyncResult WhenAny(IEnumerable ops) where T : IAsyncOper { if (op == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opList.Add(op); @@ -1320,7 +1320,7 @@ public static AsyncResult WhenAny(IEnumerable ops) where T : IAsyncOper if (opList.Count == 0) { - throw new ArgumentException(Constants.ErrorListIsEmpty, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListIsEmpty(), nameof(ops)); } return new WhenAnyResult(opList.ToArray()); @@ -1343,7 +1343,7 @@ public static AsyncResult WhenAny(params T[] ops) where T : IAsyncOperatio if (ops.Length == 0) { - throw new ArgumentException(Constants.ErrorListIsEmpty, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListIsEmpty(), nameof(ops)); } var opArray = new T[ops.Length]; @@ -1352,7 +1352,7 @@ public static AsyncResult WhenAny(params T[] ops) where T : IAsyncOperatio { if (ops[i] == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(ops)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(ops)); } opArray[i] = ops[i]; diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index d3dbb14..45e6ebe 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -542,7 +542,7 @@ protected internal bool TrySetExceptions(IEnumerable exceptions, bool { if (e == null) { - throw new ArgumentException(Constants.ErrorListElementIsNull, nameof(exceptions)); + throw new ArgumentException(Messages.FormatError_ListElementIsNull(), nameof(exceptions)); } list.Add(e); @@ -550,7 +550,7 @@ protected internal bool TrySetExceptions(IEnumerable exceptions, bool if (list.Count == 0) { - throw new ArgumentException(Constants.ErrorListIsEmpty, nameof(exceptions)); + throw new ArgumentException(Messages.FormatError_ListIsEmpty(), nameof(exceptions)); } if (TryReserveCompletion()) @@ -1251,7 +1251,7 @@ public void Dispose() { if (!IsCompleted) { - throw new InvalidOperationException(Constants.ErrorOperationIsNotCompleted); + throw new InvalidOperationException(Messages.FormatError_OperationIsNotCompleted()); } Dispose(true); diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs b/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs index 98ca79e..b5d11c4 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs @@ -77,7 +77,7 @@ public int MaxCount { if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(MaxCount), value, Constants.ErrorValueIsLessThanZero); + throw new ArgumentOutOfRangeException(nameof(MaxCount), value, Messages.FormatError_ValueIsLessThanZero()); } _maxOpsSize = value; diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs index 8de618c..fccb6bb 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult{TResult}.cs @@ -280,7 +280,7 @@ public TResult Result { if (!IsCompleted) { - throw new InvalidOperationException(Constants.ErrorResultNotAvailable); + throw new InvalidOperationException(Messages.FormatError_OperationResultIsNotAvailable()); } ThrowIfNonSuccess(); From e2e83bb4d0a1eccec3aebb2469383f0510e8539a Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sat, 15 Sep 2018 14:07:29 +0300 Subject: [PATCH 14/57] Moved README.txt to Asset Store package only and added publisher information to it --- src/Build.ps1 | 6 ++---- .../Assets/Plugins}/UnityFx.Async/README.txt | 3 +++ src/UnityFx.Async/UnityFx.Async.csproj | 7 ------- 3 files changed, 5 insertions(+), 11 deletions(-) rename src/{ => UnityFx.Async.AssetStore/Assets/Plugins}/UnityFx.Async/README.txt (88%) diff --git a/src/Build.ps1 b/src/Build.ps1 index 9d3f704..08bf86d 100644 --- a/src/Build.ps1 +++ b/src/Build.ps1 @@ -69,18 +69,16 @@ function _PublishAssetStorePackage param([string]$targetFramework) $changelogPath = (Join-Path $scriptPath "..\CHANGELOG.md") - $readmePath = (Join-Path $scriptPath "UnityFx.Async\README.txt") $filesToPublish = (Join-Path $scriptPath "UnityFx.Async.AssetStore\Assets\*") - $binToPublish =(Join-Path $binPath (Join-Path $targetFramework "\*")) + $binToPublish =(Join-Path $binPath (Join-Path $targetFramework "\*")) $publishPath = (Join-Path $assetStorePath (Join-Path $targetFramework "Assets")) $publishPath2 = (Join-Path $publishPath "Plugins\UnityFx.Async") $publishBinPath = (Join-Path $publishPath "Plugins\UnityFx.Async\Bin") - + New-Item $publishBinPath -ItemType Directory Copy-Item -Path $filesToPublish -Destination $publishPath -Force -Recurse Copy-Item -Path $binToPublish -Destination $publishBinPath -Force -Recurse Copy-Item -Path $changelogPath -Destination $publishPath2 -Force - Copy-Item -Path $readmePath -Destination $publishPath2 -Force } _PublishAssetStorePackage "net35" diff --git a/src/UnityFx.Async/README.txt b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/README.txt similarity index 88% rename from src/UnityFx.Async/README.txt rename to src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/README.txt index 2b4ffb0..8302ce4 100644 --- a/src/UnityFx.Async/README.txt +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/README.txt @@ -1,6 +1,9 @@ SUMMARY The package provides lightweight Task-like asynchronous operations (promises) for Unity3d. +PUBLISHER INFORMATION +https://www.linkedin.com/in/alexander-bogarsukov-93b9682/ + LICENSE https://github.com/Arvtesh/UnityFx.Async/blob/master/LICENSE.md diff --git a/src/UnityFx.Async/UnityFx.Async.csproj b/src/UnityFx.Async/UnityFx.Async.csproj index ee12508..438f15b 100644 --- a/src/UnityFx.Async/UnityFx.Async.csproj +++ b/src/UnityFx.Async/UnityFx.Async.csproj @@ -31,11 +31,4 @@ - - - true - README.txt - - - From a9fcb7eaf4add5ff91a53885aa942972665f9de0 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Mon, 17 Sep 2018 12:51:08 +0300 Subject: [PATCH 15/57] Minor changes to project structure --- .../Implementation/Private/{Core => Callbacks}/CallbackData.cs | 0 .../Private/{Core => Callbacks}/CallbackUtility.cs | 0 .../Private/{Core => Callbacks}/IAsyncCallbackCollection.cs | 0 .../Private/{Core => Callbacks}/ListCallbackCollection.cs | 0 .../{Core => Callbacks}/MultiContextCallbackCollection.cs | 0 .../{Core => Callbacks}/SingleContextCallbackCollection.cs | 0 src/UnityFx.Async/UnityFx.Async.csproj | 2 +- 7 files changed, 1 insertion(+), 1 deletion(-) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/CallbackData.cs (100%) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/CallbackUtility.cs (100%) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/IAsyncCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/ListCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/MultiContextCallbackCollection.cs (100%) rename src/UnityFx.Async/Implementation/Private/{Core => Callbacks}/SingleContextCallbackCollection.cs (100%) diff --git a/src/UnityFx.Async/Implementation/Private/Core/CallbackData.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/CallbackData.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/CallbackData.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/CallbackData.cs diff --git a/src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/CallbackUtility.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/CallbackUtility.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/CallbackUtility.cs diff --git a/src/UnityFx.Async/Implementation/Private/Core/IAsyncCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/IAsyncCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/IAsyncCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/IAsyncCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Private/Core/ListCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/ListCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/ListCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/ListCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Private/Core/MultiContextCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/MultiContextCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/MultiContextCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/MultiContextCallbackCollection.cs diff --git a/src/UnityFx.Async/Implementation/Private/Core/SingleContextCallbackCollection.cs b/src/UnityFx.Async/Implementation/Private/Callbacks/SingleContextCallbackCollection.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Private/Core/SingleContextCallbackCollection.cs rename to src/UnityFx.Async/Implementation/Private/Callbacks/SingleContextCallbackCollection.cs diff --git a/src/UnityFx.Async/UnityFx.Async.csproj b/src/UnityFx.Async/UnityFx.Async.csproj index 438f15b..7b1f36e 100644 --- a/src/UnityFx.Async/UnityFx.Async.csproj +++ b/src/UnityFx.Async/UnityFx.Async.csproj @@ -2,7 +2,7 @@ net35;net46;netstandard2.0 - Task-like asynchronous operations for Unity3d. + Task-like asynchronous operations (promises) for Unity3d. Alexander Bogarsukov Alexander Bogarsukov From 339f5a32c89061808546053a2d0e9e962ebf51f5 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 18 Sep 2018 18:30:04 +0300 Subject: [PATCH 16/57] Added examples project --- src/UnityFx.Async.Examples/Example.cs | 25 ++++++++++++++++++ .../Example01/Example01.cs | 23 ++++++++++++++++ .../Example02/Example02.cs | 23 ++++++++++++++++ .../Example03/Example03.cs | 23 ++++++++++++++++ src/UnityFx.Async.Examples/Program.cs | 26 +++++++++++++++++++ .../UnityFx.Async.Examples.csproj | 14 ++++++++++ src/UnityFx.Async.sln | 8 +++++- 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/UnityFx.Async.Examples/Example.cs create mode 100644 src/UnityFx.Async.Examples/Example01/Example01.cs create mode 100644 src/UnityFx.Async.Examples/Example02/Example02.cs create mode 100644 src/UnityFx.Async.Examples/Example03/Example03.cs create mode 100644 src/UnityFx.Async.Examples/Program.cs create mode 100644 src/UnityFx.Async.Examples/UnityFx.Async.Examples.csproj diff --git a/src/UnityFx.Async.Examples/Example.cs b/src/UnityFx.Async.Examples/Example.cs new file mode 100644 index 0000000..7612f9d --- /dev/null +++ b/src/UnityFx.Async.Examples/Example.cs @@ -0,0 +1,25 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.Examples +{ + internal abstract class Example + { + public abstract string GetName(); + public abstract void Run(); + + public void WriteHeader() + { + Console.WriteLine("=============================================================================="); + Console.WriteLine(GetType().Name + ": " + GetName() + "."); + Console.WriteLine("=============================================================================="); + } + + public override string ToString() + { + return GetName(); + } + } +} diff --git a/src/UnityFx.Async.Examples/Example01/Example01.cs b/src/UnityFx.Async.Examples/Example01/Example01.cs new file mode 100644 index 0000000..240cade --- /dev/null +++ b/src/UnityFx.Async.Examples/Example01/Example01.cs @@ -0,0 +1,23 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.Examples +{ + /// + /// Example01: Introduction. + /// + internal class Example01 : Example + { + public override string GetName() + { + return "Introduction"; + } + + public override void Run() + { + // TODO + } + } +} diff --git a/src/UnityFx.Async.Examples/Example02/Example02.cs b/src/UnityFx.Async.Examples/Example02/Example02.cs new file mode 100644 index 0000000..625fdd2 --- /dev/null +++ b/src/UnityFx.Async.Examples/Example02/Example02.cs @@ -0,0 +1,23 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.Examples +{ + /// + /// Example02: AsyncResult.FromXxx. + /// + internal class Example02 : Example + { + public override string GetName() + { + return "AsyncResult.FromXxx"; + } + + public override void Run() + { + // TODO + } + } +} diff --git a/src/UnityFx.Async.Examples/Example03/Example03.cs b/src/UnityFx.Async.Examples/Example03/Example03.cs new file mode 100644 index 0000000..36414bc --- /dev/null +++ b/src/UnityFx.Async.Examples/Example03/Example03.cs @@ -0,0 +1,23 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.Examples +{ + /// + /// Example03: AsyncCompletionSource. + /// + internal class Example03 : Example + { + public override string GetName() + { + return typeof(AsyncCompletionSource).Name; + } + + public override void Run() + { + // TODO + } + } +} diff --git a/src/UnityFx.Async.Examples/Program.cs b/src/UnityFx.Async.Examples/Program.cs new file mode 100644 index 0000000..2c81c82 --- /dev/null +++ b/src/UnityFx.Async.Examples/Program.cs @@ -0,0 +1,26 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.Examples +{ + public class Program + { + public static void Main(string[] args) + { + var examples = new Example[] + { + new Example01(), + new Example02(), + new Example03(), + }; + + foreach (var example in examples) + { + example.WriteHeader(); + example.Run(); + } + } + } +} diff --git a/src/UnityFx.Async.Examples/UnityFx.Async.Examples.csproj b/src/UnityFx.Async.Examples/UnityFx.Async.Examples.csproj new file mode 100644 index 0000000..0d3e72b --- /dev/null +++ b/src/UnityFx.Async.Examples/UnityFx.Async.Examples.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.0 + Exe + false + 6 + + + + + + + diff --git a/src/UnityFx.Async.sln b/src/UnityFx.Async.sln index ddcf973..81e8dff 100644 --- a/src/UnityFx.Async.sln +++ b/src/UnityFx.Async.sln @@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityFx.Async.Tests", "Unit EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityFx.Async.AssetStore", "UnityFx.Async.AssetStore\UnityFx.Async.AssetStore.csproj", "{6ACDE97B-C722-4135-894A-340F2213514D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityFx.Async.Benchmarks", "UnityFx.Async.Benchmarks\UnityFx.Async.Benchmarks.csproj", "{EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityFx.Async.Benchmarks", "UnityFx.Async.Benchmarks\UnityFx.Async.Benchmarks.csproj", "{EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityFx.Async.Examples", "UnityFx.Async.Examples\UnityFx.Async.Examples.csproj", "{9796CFDC-5BB3-4BC8-9CCA-FFC62EB24ABC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,6 +35,10 @@ Global {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Debug|Any CPU.Build.0 = Debug|Any CPU {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Release|Any CPU.ActiveCfg = Release|Any CPU {EFDC8AF7-6B25-468E-ACDC-4B19AD78940E}.Release|Any CPU.Build.0 = Release|Any CPU + {9796CFDC-5BB3-4BC8-9CCA-FFC62EB24ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9796CFDC-5BB3-4BC8-9CCA-FFC62EB24ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9796CFDC-5BB3-4BC8-9CCA-FFC62EB24ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9796CFDC-5BB3-4BC8-9CCA-FFC62EB24ABC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 98461fef9130f221f8c9f1be406aa6b1276f06f2 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 19 Sep 2018 14:43:05 +0300 Subject: [PATCH 17/57] Changed examples project structure --- src/UnityFx.Async.Examples/{ => Examples}/Example.cs | 0 src/UnityFx.Async.Examples/{Example01 => Examples}/Example01.cs | 0 src/UnityFx.Async.Examples/{Example02 => Examples}/Example02.cs | 0 src/UnityFx.Async.Examples/{Example03 => Examples}/Example03.cs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/UnityFx.Async.Examples/{ => Examples}/Example.cs (100%) rename src/UnityFx.Async.Examples/{Example01 => Examples}/Example01.cs (100%) rename src/UnityFx.Async.Examples/{Example02 => Examples}/Example02.cs (100%) rename src/UnityFx.Async.Examples/{Example03 => Examples}/Example03.cs (100%) diff --git a/src/UnityFx.Async.Examples/Example.cs b/src/UnityFx.Async.Examples/Examples/Example.cs similarity index 100% rename from src/UnityFx.Async.Examples/Example.cs rename to src/UnityFx.Async.Examples/Examples/Example.cs diff --git a/src/UnityFx.Async.Examples/Example01/Example01.cs b/src/UnityFx.Async.Examples/Examples/Example01.cs similarity index 100% rename from src/UnityFx.Async.Examples/Example01/Example01.cs rename to src/UnityFx.Async.Examples/Examples/Example01.cs diff --git a/src/UnityFx.Async.Examples/Example02/Example02.cs b/src/UnityFx.Async.Examples/Examples/Example02.cs similarity index 100% rename from src/UnityFx.Async.Examples/Example02/Example02.cs rename to src/UnityFx.Async.Examples/Examples/Example02.cs diff --git a/src/UnityFx.Async.Examples/Example03/Example03.cs b/src/UnityFx.Async.Examples/Examples/Example03.cs similarity index 100% rename from src/UnityFx.Async.Examples/Example03/Example03.cs rename to src/UnityFx.Async.Examples/Examples/Example03.cs From 2ce20b46414be970b857772a032ca499097ddb8b Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 20 Sep 2018 16:29:01 +0300 Subject: [PATCH 18/57] Updated README with benchmark results --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index ba29456..847022a 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,37 @@ The table below summarizes differences berween *UnityFx.Async* and other popular | Minimum operation data size for 32-bit systems (in bytes) | 32+ | 36+ | 40+ | | Minimum number of allocations per continuation | ~1 | 5+ | 2+ | +The table below shows preformance benchmarks for typical promise use-case compared to adding elements to a standard `List` collection: +```csharp +op.Then(() => { /* N = 1*/ }) + .Then(() => { /* N = 2*/ }) + // ... + .Then(() => { /* N = max*/ }); +``` +``` ini +BenchmarkDotNet=v0.11.1, OS=Windows 8.1 (6.3.9600.0) +Intel Core i5-4670 CPU 3.40GHz (Haswell), 1 CPU, 4 logical and 4 physical cores +Frequency=3312640 Hz, Resolution=301.8740 ns, Timer=TSC + [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0 + DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0 +``` +| Method | N | Mean | Scaled | Allocated | +|------------------ |-- |----------:|-------:|----------:| +| **Then_List** | **1** | **15.74 ns** | **1.00** | **72 B** | +| Then_Async | 1 | 48.04 ns | 3.05 | 152 B | +| Then_RsgPromise | 1 | 112.18 ns | 7.13 | 552 B | +| **Then_List** | **2** | **20.97 ns** | **1.00** | **80 B** | +| Then_Async | 2 | 93.97 ns | 4.48 | 248 B | +| Then_RsgPromise | 2 | 230.64 ns | 11.00 | 1040 B | +| **Then_List** | **4** | **31.44 ns** | **1.00** | **96 B** | +| Then_Async | 4 | 190.19 ns | 6.05 | 440 B | +| Then_RsgPromise | 4 | 439.00 ns | 13.96 | 2016 B | +| **Then_List** | **8** | **51.18 ns** | **1.00** | **128 B** | +| Then_Async | 8 | 361.37 ns | 7.06 | 824 B | +| Then_RsgPromise | 8 | 859.40 ns | 16.79 | 3968 B | + +As you can see, *UnityFx.Async* operations perform quite nice compared to the main competitor ([C-Sharp-Promise](https://github.com/Real-Serious-Games/C-Sharp-Promise)). + ## Getting Started ### Prerequisites You may need the following software installed in order to build/use the library: From d2cc889147de83b984ed958728c1297ec10562bf Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 20 Sep 2018 17:05:57 +0300 Subject: [PATCH 19/57] Added AsyncCompletionSource sample code --- .../Examples/Example03.cs | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/UnityFx.Async.Examples/Examples/Example03.cs b/src/UnityFx.Async.Examples/Examples/Example03.cs index 36414bc..c5505db 100644 --- a/src/UnityFx.Async.Examples/Examples/Example03.cs +++ b/src/UnityFx.Async.Examples/Examples/Example03.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; +using System.Net; namespace UnityFx.Async.Examples { @@ -17,7 +18,59 @@ public override string GetName() public override void Run() { - // TODO + // NOTE: The operation should be disposed because of the Wait() call. + using (var op = DownloadAsTextAsync("http://www.google.com")) + { + op.AddCompletionCallback(o => + { + if (op.IsCompletedSuccessfully) + { + var s = op.Result; + + if (s.Length > 128) + { + s = s.Substring(0, 128) + "..."; + } + + Console.WriteLine("Download result: " + s); + } + }, null); + + op.Wait(); + } + } + + private IAsyncOperation DownloadAsTextAsync(string url) + { + var op = new AsyncCompletionSource(); + var webClient = new WebClient(); + + webClient.DownloadStringCompleted += (sender, args) => + { + webClient.Dispose(); + + if (args.Error != null) + { + Console.WriteLine("Download failed: " + args.Error.Message); + op.SetException(args.Error); + } + else + { + Console.WriteLine("Download completed."); + op.SetResult(args.Result); + } + }; + + webClient.DownloadProgressChanged += (sender, args) => + { + Console.WriteLine("Download progress: " + args.ProgressPercentage + "%."); + op.TrySetProgress(args.ProgressPercentage / 100f); + }; + + Console.WriteLine("Downloading " + url + "."); + webClient.DownloadStringAsync(new Uri(url)); + + return op.Operation; } } } From 136eec420819bc5c3e96fcc7d9f3828758fd7435 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 20 Sep 2018 17:25:47 +0300 Subject: [PATCH 20/57] Comment fixes --- src/UnityFx.Async/Api/Interfaces/IAsyncContinuation.cs | 4 ++-- src/UnityFx.Async/Api/Interfaces/IAsyncOperation.cs | 7 ++++++- src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs | 2 +- .../Api/Interfaces/IAsyncOperation{TResult}.cs | 4 ++-- src/UnityFx.Async/Api/Interfaces/IAsyncUpdatable.cs | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncContinuation.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncContinuation.cs index 35d36ca..b7cc0d5 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncContinuation.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncContinuation.cs @@ -9,8 +9,8 @@ namespace UnityFx.Async /// A generic non-delegate continuation. /// /// - /// This interface allows us to combine functionality and reduce allocations. It especially useful for implementing custom - /// continuation operations. + /// This interface is a great helper for combining functionality and reducing number of allocations. + /// It is especially useful for implementing custom continuation operations. /// /// /// diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncOperation.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncOperation.cs index 90ebf54..231e23a 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncOperation.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncOperation.cs @@ -6,8 +6,13 @@ namespace UnityFx.Async { /// - /// Represents the consumer side of an asynchronous operation. It is basically a disposable/hookable with status information. + /// Represents the consumer side of an asynchronous operation (promise). /// + /// + /// The interface defines a read-only consumer side of an asynchronous operation. Basically + /// it provides the operation state information and completion/progress events. It is cancellable + /// so a cancellation request can be issued at any time (without any guarantees). + /// /// Task /// /// diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs index 7eac539..96c2ed2 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs @@ -8,7 +8,7 @@ namespace UnityFx.Async { /// - /// Manages events and callbacks of . + /// Defines completion/progress callbacks for . /// /// public interface IAsyncOperationEvents diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncOperation{TResult}.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncOperation{TResult}.cs index e3510d4..4772ee3 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncOperation{TResult}.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncOperation{TResult}.cs @@ -6,10 +6,10 @@ namespace UnityFx.Async { /// - /// Represents the consumer side of an asynchronous operation. Extends an + /// Represents the consumer side of an asynchronous operation. Extends /// interface with a result value. /// - /// Type of th operation result value. + /// Type of the operation result value. /// Task /// /// diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncUpdatable.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncUpdatable.cs index 9fb4a34..c79cd3c 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncUpdatable.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncUpdatable.cs @@ -6,7 +6,7 @@ namespace UnityFx.Async { /// - /// An updatable object. + /// Defines an updatable entity. /// /// public interface IAsyncUpdatable From 598b7248a1337606ba7cca414bac3c58cdafefc6 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 17:32:40 +0300 Subject: [PATCH 21/57] Added library initialize code to BeforeSceneLoad Unity event --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 327 +++++++----------- 1 file changed, 134 insertions(+), 193 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index d261388..a1a7f16 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -22,6 +22,12 @@ public static class AsyncUtility { #region data + private static SynchronizationContext _mainThreadContext; +#if NET_4_6 || NET_STANDARD_2_0 + private static ConcurrentQueue _actionQueue; +#else + private static Queue _actionQueue; +#endif private static GameObject _go; #endregion @@ -47,14 +53,6 @@ public static GameObject GetRootGo() return _go; } - /// - /// Initializes the utilities. If skipped the utilities are lazily initialized. - /// - public static void Initialize() - { - GetRootBehaviour(); - } - /// /// Returns an instance of an for Update. /// @@ -109,7 +107,35 @@ public static IAsyncUpdateSource GetEndOfFrameUpdateSource() /// public static void SendToMainThread(SendOrPostCallback d, object state) { - GetRootBehaviour().Send(d, state); + if (d == null) + { + throw new ArgumentNullException("d"); + } + + if (_mainThreadContext == SynchronizationContext.Current) + { + d.Invoke(state); + } + else + { + using (var asyncResult = new InvokeResult(d, state)) + { +#if NET_2_0 || NET_2_0_SUBSET + + lock (_actionQueue) + { + _actionQueue.Enqueue(asyncResult); + } + +#else + + _actionQueue.Enqueue(asyncResult); + +#endif + + asyncResult.Wait(); + } + } } /// @@ -122,7 +148,27 @@ public static void SendToMainThread(SendOrPostCallback d, object state) /// public static IAsyncOperation PostToMainThread(SendOrPostCallback d, object state) { - return GetRootBehaviour().Post(d, state); + if (d == null) + { + throw new ArgumentNullException("d"); + } + + var asyncResult = new InvokeResult(d, state); + +#if NET_2_0 || NET_2_0_SUBSET + + lock (_actionQueue) + { + _actionQueue.Enqueue(asyncResult); + } + +#else + + _actionQueue.Enqueue(asyncResult); + +#endif + + return asyncResult; } /// @@ -135,7 +181,14 @@ public static IAsyncOperation PostToMainThread(SendOrPostCallback d, object stat /// public static IAsyncOperation InvokeOnMainThread(SendOrPostCallback d, object state) { - return GetRootBehaviour().Invoke(d, state); + if (_mainThreadContext == SynchronizationContext.Current) + { + return AsyncResult.FromAction(d, state); + } + else + { + return PostToMainThread(d, state); + } } /// @@ -144,7 +197,7 @@ public static IAsyncOperation InvokeOnMainThread(SendOrPostCallback d, object st /// Returns if current thread is Unity main thread; otherwise. public static bool IsMainThread() { - return GetRootBehaviour().MainThreadContext == SynchronizationContext.Current; + return _mainThreadContext == SynchronizationContext.Current; } /// @@ -353,57 +406,6 @@ public static void AddCompletionCallback(WWW request, Action completionCallback) #region implementation - private sealed class InvokeResult : AsyncResult - { - private readonly SendOrPostCallback _callback; - - public InvokeResult(SendOrPostCallback d, object asyncState) - : base(AsyncOperationStatus.Scheduled, asyncState) - { - _callback = d; - } - - public void SetCompleted() - { - TrySetCompleted(); - } - - public void SetException(Exception e) - { - TrySetException(e); - } - - protected override void OnStarted() - { - _callback.Invoke(AsyncState); - } - } - - private sealed class MainThreadSynchronizationContext : SynchronizationContext - { - private readonly AsyncRootBehaviour _scheduler; - - public MainThreadSynchronizationContext(AsyncRootBehaviour scheduler) - { - _scheduler = scheduler; - } - - public override SynchronizationContext CreateCopy() - { - return new MainThreadSynchronizationContext(_scheduler); - } - - public override void Send(SendOrPostCallback d, object state) - { - _scheduler.Send(d, state); - } - - public override void Post(SendOrPostCallback d, object state) - { - _scheduler.Post(d, state); - } - } - private sealed class AsyncRootBehaviour : MonoBehaviour { #region data @@ -417,26 +419,10 @@ private sealed class AsyncRootBehaviour : MonoBehaviour private AsyncUpdateSource _eofUpdateSource; private WaitForEndOfFrame _eof; - private SynchronizationContext _context; - private SynchronizationContext _mainThreadContext; -#if NET_4_6 || NET_STANDARD_2_0 - private ConcurrentQueue _actionQueue; -#else - private Queue _actionQueue; -#endif - #endregion #region interface - public SynchronizationContext MainThreadContext - { - get - { - return _mainThreadContext; - } - } - public IAsyncUpdateSource UpdateSource { get @@ -502,116 +488,10 @@ public void AddCompletionCallback(object op, Action cb) _ops.Add(op, cb); } - public void Send(SendOrPostCallback d, object state) - { - if (d == null) - { - throw new ArgumentNullException("d"); - } - - if (!this) - { - throw new ObjectDisposedException(GetType().Name); - } - - if (_mainThreadContext == SynchronizationContext.Current) - { - d.Invoke(state); - } - else - { - using (var asyncResult = new InvokeResult(d, state)) - { -#if NET_2_0 || NET_2_0_SUBSET - - lock (_actionQueue) - { - _actionQueue.Enqueue(asyncResult); - } - -#else - - _actionQueue.Enqueue(asyncResult); - -#endif - - asyncResult.Wait(); - } - } - } - - public IAsyncOperation Post(SendOrPostCallback d, object state) - { - if (d == null) - { - throw new ArgumentNullException("d"); - } - - if (!this) - { - throw new ObjectDisposedException(GetType().Name); - } - - var asyncResult = new InvokeResult(d, state); - -#if NET_2_0 || NET_2_0_SUBSET - - lock (_actionQueue) - { - _actionQueue.Enqueue(asyncResult); - } - -#else - - _actionQueue.Enqueue(asyncResult); - -#endif - - return asyncResult; - } - - public IAsyncOperation Invoke(SendOrPostCallback d, object state) - { - if (_mainThreadContext == SynchronizationContext.Current) - { - return AsyncResult.FromAction(d, state); - } - else - { - return Post(d, state); - } - } - #endregion #region MonoBehavoiur - private void Awake() - { - var currentContext = SynchronizationContext.Current; - - if (currentContext == null) - { - var context = new MainThreadSynchronizationContext(this); - SynchronizationContext.SetSynchronizationContext(context); - _context = context; - _mainThreadContext = context; - } - else - { - _mainThreadContext = currentContext; - } - -#if NET_4_6 || NET_STANDARD_2_0 - _actionQueue = new ConcurrentQueue(); -#else - _actionQueue = new Queue(); -#endif - - // Set main thread context as default for all continuations. This saves allocations in many cases. - AsyncResult.DefaultSynchronizationContext = _mainThreadContext; - } - private void Update() { if (_ops != null && _ops.Count > 0) @@ -765,14 +645,6 @@ private void OnDestroy() _eofUpdateSource.Dispose(); _eofUpdateSource = null; } - - if (_context != null && _context == SynchronizationContext.Current) - { - SynchronizationContext.SetSynchronizationContext(null); - } - - _mainThreadContext = null; - _context = null; } #endregion @@ -792,6 +664,50 @@ private IEnumerator EofEnumerator() #endregion } + private sealed class InvokeResult : AsyncResult + { + private readonly SendOrPostCallback _callback; + + public InvokeResult(SendOrPostCallback d, object asyncState) + : base(AsyncOperationStatus.Scheduled, asyncState) + { + _callback = d; + } + + public void SetCompleted() + { + TrySetCompleted(); + } + + public void SetException(Exception e) + { + TrySetException(e); + } + + protected override void OnStarted() + { + _callback.Invoke(AsyncState); + } + } + + private sealed class MainThreadSynchronizationContext : SynchronizationContext + { + public override SynchronizationContext CreateCopy() + { + return new MainThreadSynchronizationContext(); + } + + public override void Send(SendOrPostCallback d, object state) + { + SendToMainThread(d, state); + } + + public override void Post(SendOrPostCallback d, object state) + { + PostToMainThread(d, state); + } + } + private static AsyncRootBehaviour TryGetRootBehaviour() { var go = GetRootGo(); @@ -830,6 +746,31 @@ private static AsyncRootBehaviour GetRootBehaviour() } } + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Initialize() + { + var context = SynchronizationContext.Current; + + if (context == null) + { + context = new MainThreadSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(context); + } + + // Save the main thread context for future use. + _mainThreadContext = context; + + // Initialize delayed action queue. +#if NET_4_6 || NET_STANDARD_2_0 + _actionQueue = new ConcurrentQueue(); +#else + _actionQueue = new Queue(); +#endif + + // Set main thread context as default for all continuations. This saves allocations in many cases. + AsyncResult.DefaultSynchronizationContext = context; + } + #endregion } } From 64b75175fa8c96f4b47bd53e684264cf50b42f6f Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 19:25:13 +0300 Subject: [PATCH 22/57] Minot AsyncUtility optimizations --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 56 ++++++------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index a1a7f16..8e9d04b 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -7,6 +7,7 @@ #if NET_4_6 || NET_STANDARD_2_0 using System.Collections.Concurrent; #endif +using System.Runtime.CompilerServices; using System.Threading; using UnityEngine; #if UNITY_5_4_OR_NEWER @@ -29,6 +30,7 @@ public static class AsyncUtility private static Queue _actionQueue; #endif private static GameObject _go; + private static AsyncRootBehaviour _rootBehaviour; #endregion @@ -267,14 +269,9 @@ public static Coroutine StartCoroutine(IEnumerator enumerator) /// public static void StopCoroutine(Coroutine coroutine) { - if (coroutine != null) + if (coroutine != null && _rootBehaviour) { - var runner = TryGetRootBehaviour(); - - if (runner) - { - runner.StopCoroutine(coroutine); - } + _rootBehaviour.StopCoroutine(coroutine); } } @@ -287,14 +284,9 @@ public static void StopCoroutine(Coroutine coroutine) /// public static void StopCoroutine(IEnumerator enumerator) { - if (enumerator != null) + if (enumerator != null && _rootBehaviour) { - var runner = TryGetRootBehaviour(); - - if (runner) - { - runner.StopCoroutine(enumerator); - } + _rootBehaviour.StopCoroutine(enumerator); } } @@ -306,11 +298,9 @@ public static void StopCoroutine(IEnumerator enumerator) /// public static void StopAllCoroutines() { - var runner = TryGetRootBehaviour(); - - if (runner) + if (_rootBehaviour) { - runner.StopAllCoroutines(); + _rootBehaviour.StopAllCoroutines(); } } @@ -708,37 +698,27 @@ public override void Post(SendOrPostCallback d, object state) } } - private static AsyncRootBehaviour TryGetRootBehaviour() +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + private static AsyncRootBehaviour GetRootBehaviour() { - var go = GetRootGo(); - - if (go) + if (ReferenceEquals(_rootBehaviour, null)) { - var runner = go.GetComponent(); - - if (runner) - { - return runner; - } + InitRootBehaviour(); } - return null; + return _rootBehaviour; } - private static AsyncRootBehaviour GetRootBehaviour() + [MethodImpl(MethodImplOptions.NoInlining)] + private static void InitRootBehaviour() { var go = GetRootGo(); if (go) { - var runner = go.GetComponent(); - - if (!runner) - { - runner = go.AddComponent(); - } - - return runner; + _rootBehaviour = go.AddComponent(); } else { From 259b0343bafb69b5dd3a42b9a6c8be4bbefb6aec Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 19:31:18 +0300 Subject: [PATCH 23/57] Dropped Unity 5.0 support; the minimum version required in now Unity 5.4 --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 8 -- .../Plugins/UnityFx.Async/Scripts/AsyncWww.cs | 83 ++----------------- .../Scripts/Helpers/WebRequestResult{T}.cs | 6 -- .../UnityFx.Async/Scripts/UnityExtensions.cs | 10 --- 4 files changed, 7 insertions(+), 100 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 8e9d04b..0a663dd 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -10,9 +10,7 @@ using System.Runtime.CompilerServices; using System.Threading; using UnityEngine; -#if UNITY_5_4_OR_NEWER using UnityEngine.Networking; -#endif namespace UnityFx.Async { @@ -343,8 +341,6 @@ public static void AddCompletionCallback(AsyncOperation op, Action completionCal } } -#if UNITY_5_4_OR_NEWER - /// /// Register a completion callback for the specified instance. /// @@ -368,8 +364,6 @@ public static void AddCompletionCallback(UnityWebRequest request, Action complet GetRootBehaviour().AddCompletionCallback(request, completionCallback); } -#endif - /// /// Register a completion callback for the specified instance. /// @@ -500,7 +494,6 @@ private void Update() item.Value(); } } -#if UNITY_5_4_OR_NEWER else if (item.Key is UnityWebRequest) { var asyncOp = item.Key as UnityWebRequest; @@ -511,7 +504,6 @@ private void Update() item.Value(); } } -#endif else if (item.Key is WWW) { var asyncOp = item.Key as WWW; diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs index b52ea70..1ec66d4 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs @@ -3,9 +3,7 @@ using System; using UnityEngine; -#if UNITY_5_4_OR_NEWER using UnityEngine.Networking; -#endif namespace UnityFx.Async { @@ -21,18 +19,8 @@ public static class AsyncWww /// An operation that can be used to track the download process. public static IAsyncOperation GetText(string url) { -#if UNITY_5_4_OR_NEWER - var webRequest = UnityWebRequest.Get(url); var result = new Helpers.WebRequestResult(webRequest); - -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - -#endif - result.Start(); return result; } @@ -44,18 +32,8 @@ public static IAsyncOperation GetText(string url) /// An operation that can be used to track the download process. public static IAsyncOperation GetBytes(string url) { -#if UNITY_5_4_OR_NEWER - var webRequest = UnityWebRequest.Get(url); var result = new Helpers.WebRequestResult(webRequest); - -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - -#endif - result.Start(); return result; } @@ -72,16 +50,11 @@ public static IAsyncOperation GetAssetBundle(string url) var webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetAssetBundle(url); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -101,16 +74,11 @@ public static IAsyncOperation GetAssetBundle(string url, Hash128 ha var webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url, hash, 0); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetAssetBundle(url, hash, 0); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = WWW.LoadFromCacheOrDownload(url, hash); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -131,16 +99,11 @@ public static IAsyncOperation GetAssetBundle(string url, Hash128 ha var webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url, hash, crc); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetAssetBundle(url, hash, crc); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = WWW.LoadFromCacheOrDownload(url, hash, crc); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -159,16 +122,11 @@ public static IAsyncOperation GetAudioClip(string url) var webRequest = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.UNKNOWN); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetAudioClip(url, AudioType.UNKNOWN); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -188,16 +146,11 @@ public static IAsyncOperation GetAudioClip(string url, AudioType audi var webRequest = UnityWebRequestMultimedia.GetAudioClip(url, audioType); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetAudioClip(url, audioType); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -216,16 +169,11 @@ public static IAsyncOperation GetTexture(string url) var webRequest = UnityWebRequestTexture.GetTexture(url, false); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetTexture(url); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -245,16 +193,11 @@ public static IAsyncOperation GetTexture(string url, bool nonReadable var webRequest = UnityWebRequestTexture.GetTexture(url, nonReadable); var result = new Helpers.WebRequestResult(webRequest); -#elif UNITY_5_4_OR_NEWER +#else var webRequest = UnityWebRequest.GetTexture(url, nonReadable); var result = new Helpers.WebRequestResult(webRequest); -#else - - var www = new WWW(url); - var result = new Helpers.WwwResult(www); - #endif result.Start(); @@ -288,8 +231,6 @@ public static IAsyncOperation GetMovieTexture(string url) #endif -#if UNITY_5_4_OR_NEWER - /// /// Returns result value of the specified instance. /// @@ -331,8 +272,6 @@ public static T GetResult(UnityWebRequest request) where T : class return default(T); } -#endif - /// /// Returns result value of the specified instance. /// @@ -354,20 +293,12 @@ public static T GetResult(WWW request) where T : class } else if (typeof(T) == typeof(AudioClip)) { -#if UNITY_5_4_OR_NEWER return request.GetAudioClip() as T; -#else - return request.audioClip as T; -#endif } #if !UNITY_2018_2_OR_NEWER else if (typeof(T) == typeof(MovieTexture)) { -#if UNITY_5_4_OR_NEWER return request.GetMovieTexture() as T; -#else - return request.movie as T; -#endif } #endif else if (typeof(T) == typeof(byte[])) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WebRequestResult{T}.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WebRequestResult{T}.cs index 7425930..27b9ef4 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WebRequestResult{T}.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WebRequestResult{T}.cs @@ -4,14 +4,10 @@ using System; using System.Text; using UnityEngine; -#if UNITY_5_4_OR_NEWER using UnityEngine.Networking; -#endif namespace UnityFx.Async.Helpers { -#if UNITY_5_4_OR_NEWER - /// /// A wrapper for with result value. /// @@ -205,6 +201,4 @@ private void SetCompleted() #endregion } - -#endif } diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs index 36b9176..b3bbcff 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs @@ -5,9 +5,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using UnityEngine; -#if UNITY_5_4_OR_NEWER using UnityEngine.Networking; -#endif #if NET_4_6 || NET_STANDARD_2_0 using System.Threading.Tasks; #endif @@ -153,8 +151,6 @@ public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation op) #region UnityWebRequest -#if UNITY_5_4_OR_NEWER - /// /// Creates an wrapper for the specified . /// @@ -245,8 +241,6 @@ public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequest op) return new UnityWebRequestAwaiter(op); } -#endif - #endif #endregion @@ -443,8 +437,6 @@ public static IAsyncOperation WaitAsync(this Animator anim) #if NET_4_6 || NET_STANDARD_2_0 -#if UNITY_5_4_OR_NEWER - private static void OnTaskCompleted(TaskCompletionSource tcs, UnityWebRequest request) where T : class { try @@ -473,8 +465,6 @@ private static void OnTaskCompleted(TaskCompletionSource tcs, UnityWebRequ } } -#endif - private static void OnTaskCompleted(TaskCompletionSource tcs, WWW www) where T : class { try From 31c9854a794b45d292afbace71e2111b02bbf55a Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 19:39:17 +0300 Subject: [PATCH 24/57] README update --- README.md | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 847022a..1cd7717 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Channel | UnityFx.Async | AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/hfmq9vow53al7tpd/branch/master?svg=true)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/branch/master) [![AppVeyor tests](https://img.shields.io/appveyor/tests/Arvtesh/unityFx-async.svg)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/build/tests) NuGet | [![NuGet](https://img.shields.io/nuget/v/UnityFx.Async.svg)](https://www.nuget.org/packages/UnityFx.Async) Github | [![GitHub release](https://img.shields.io/github/release/Arvtesh/UnityFx.Async.svg?logo=github)](https://github.com/Arvtesh/UnityFx.Async/releases) -Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.6-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) +Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.5-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) + +**Required Unity 5.4 or higher.** **If you enjoy using the library - please, [rate and review](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) it on the Asset Store!** @@ -37,42 +39,11 @@ The table below summarizes differences berween *UnityFx.Async* and other popular | Minimum operation data size for 32-bit systems (in bytes) | 32+ | 36+ | 40+ | | Minimum number of allocations per continuation | ~1 | 5+ | 2+ | -The table below shows preformance benchmarks for typical promise use-case compared to adding elements to a standard `List` collection: -```csharp -op.Then(() => { /* N = 1*/ }) - .Then(() => { /* N = 2*/ }) - // ... - .Then(() => { /* N = max*/ }); -``` -``` ini -BenchmarkDotNet=v0.11.1, OS=Windows 8.1 (6.3.9600.0) -Intel Core i5-4670 CPU 3.40GHz (Haswell), 1 CPU, 4 logical and 4 physical cores -Frequency=3312640 Hz, Resolution=301.8740 ns, Timer=TSC - [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0 - DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0 -``` -| Method | N | Mean | Scaled | Allocated | -|------------------ |-- |----------:|-------:|----------:| -| **Then_List** | **1** | **15.74 ns** | **1.00** | **72 B** | -| Then_Async | 1 | 48.04 ns | 3.05 | 152 B | -| Then_RsgPromise | 1 | 112.18 ns | 7.13 | 552 B | -| **Then_List** | **2** | **20.97 ns** | **1.00** | **80 B** | -| Then_Async | 2 | 93.97 ns | 4.48 | 248 B | -| Then_RsgPromise | 2 | 230.64 ns | 11.00 | 1040 B | -| **Then_List** | **4** | **31.44 ns** | **1.00** | **96 B** | -| Then_Async | 4 | 190.19 ns | 6.05 | 440 B | -| Then_RsgPromise | 4 | 439.00 ns | 13.96 | 2016 B | -| **Then_List** | **8** | **51.18 ns** | **1.00** | **128 B** | -| Then_Async | 8 | 361.37 ns | 7.06 | 824 B | -| Then_RsgPromise | 8 | 859.40 ns | 16.79 | 3968 B | - -As you can see, *UnityFx.Async* operations perform quite nice compared to the main competitor ([C-Sharp-Promise](https://github.com/Real-Serious-Games/C-Sharp-Promise)). - ## Getting Started ### Prerequisites You may need the following software installed in order to build/use the library: - [Microsoft Visual Studio 2017](https://www.visualstudio.com/vs/community/). -- [Unity3d](https://store.unity.com/). +- [Unity3d](https://store.unity.com/) (the minimum supported version is **5.4**). ### Getting the code You can get the code by cloning the github repository using your preffered git client UI or you can do it from command line as follows: From fda38d3ccbbb779bab6209d26042d83eb9f44842 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 19:39:27 +0300 Subject: [PATCH 25/57] CHANGELOG update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fca595..5d1734c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj ### Removed - Removed Asset Store samples. +- Dropped Unity 5.0 support (the minimum version supported is now 5.4). ----------------------- ## [0.9.6] - 2018.08.31 From 7676f5d5916cc9484cef2aaf26a6604f1cdbdc76 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Sun, 23 Sep 2018 20:44:24 +0300 Subject: [PATCH 26/57] Optimized SendToMainThread/PostToMainThread/InvokeOnMainThread implementation --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 190 ++++++++---------- 1 file changed, 87 insertions(+), 103 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 0a663dd..e9c9959 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; #if NET_4_6 || NET_STANDARD_2_0 using System.Collections.Concurrent; +using System.Runtime.ExceptionServices; #endif -using System.Runtime.CompilerServices; using System.Threading; using UnityEngine; using UnityEngine.Networking; @@ -44,12 +44,6 @@ public static class AsyncUtility /// public static GameObject GetRootGo() { - if (ReferenceEquals(_go, null)) - { - _go = new GameObject(RootGoName); - GameObject.DontDestroyOnLoad(_go); - } - return _go; } @@ -61,7 +55,7 @@ public static GameObject GetRootGo() /// public static IAsyncUpdateSource GetUpdateSource() { - return GetRootBehaviour().UpdateSource; + return _rootBehaviour.UpdateSource; } /// @@ -72,7 +66,7 @@ public static IAsyncUpdateSource GetUpdateSource() /// public static IAsyncUpdateSource GetLateUpdateSource() { - return GetRootBehaviour().LateUpdateSource; + return _rootBehaviour.LateUpdateSource; } /// @@ -83,7 +77,7 @@ public static IAsyncUpdateSource GetLateUpdateSource() /// public static IAsyncUpdateSource GetFixedUpdateSource() { - return GetRootBehaviour().FixedUpdateSource; + return _rootBehaviour.FixedUpdateSource; } /// @@ -94,7 +88,7 @@ public static IAsyncUpdateSource GetFixedUpdateSource() /// public static IAsyncUpdateSource GetEndOfFrameUpdateSource() { - return GetRootBehaviour().EofUpdateSource; + return _rootBehaviour.EofUpdateSource; } /// @@ -118,23 +112,60 @@ public static void SendToMainThread(SendOrPostCallback d, object state) } else { - using (var asyncResult = new InvokeResult(d, state)) + var completed = false; + var exception = default(Exception); + var asyncResult = new InvokeResult( + args => + { + try + { + d.Invoke(args); + } + catch (Exception e) + { + exception = e; + } + finally + { + completed = true; + } + }, + state); + +#if NET_4_6 || NET_STANDARD_2_0 + + _actionQueue.Enqueue(asyncResult); + + var sw = new SpinWait(); + + while (!completed) { -#if NET_2_0 || NET_2_0_SUBSET + sw.SpinOnce(); + } - lock (_actionQueue) - { - _actionQueue.Enqueue(asyncResult); - } + if (exception != null) + { + ExceptionDispatchInfo.Capture(exception).Throw(); + } #else + lock (_actionQueue) + { _actionQueue.Enqueue(asyncResult); + } -#endif + while (!completed) + { + Thread.SpinWait(1); + } - asyncResult.Wait(); + if (exception != null) + { + throw exception; } + +#endif } } @@ -146,7 +177,7 @@ public static void SendToMainThread(SendOrPostCallback d, object state) /// Thrown if is . /// /// - public static IAsyncOperation PostToMainThread(SendOrPostCallback d, object state) + public static void PostToMainThread(SendOrPostCallback d, object state) { if (d == null) { @@ -155,20 +186,18 @@ public static IAsyncOperation PostToMainThread(SendOrPostCallback d, object stat var asyncResult = new InvokeResult(d, state); -#if NET_2_0 || NET_2_0_SUBSET +#if NET_4_6 || NET_STANDARD_2_0 + + _actionQueue.Enqueue(asyncResult); + +#else lock (_actionQueue) { _actionQueue.Enqueue(asyncResult); } -#else - - _actionQueue.Enqueue(asyncResult); - #endif - - return asyncResult; } /// @@ -179,15 +208,15 @@ public static IAsyncOperation PostToMainThread(SendOrPostCallback d, object stat /// Thrown if is . /// /// - public static IAsyncOperation InvokeOnMainThread(SendOrPostCallback d, object state) + public static void InvokeOnMainThread(SendOrPostCallback d, object state) { if (_mainThreadContext == SynchronizationContext.Current) { - return AsyncResult.FromAction(d, state); + d.Invoke(state); } else { - return PostToMainThread(d, state); + PostToMainThread(d, state); } } @@ -210,7 +239,7 @@ public static bool IsMainThread() /// public static IAsyncOperation Delay(int millisecondsDelay) { - return AsyncResult.Delay(millisecondsDelay, GetRootBehaviour().UpdateSource); + return AsyncResult.Delay(millisecondsDelay, _rootBehaviour.UpdateSource); } /// @@ -223,7 +252,7 @@ public static IAsyncOperation Delay(int millisecondsDelay) /// public static IAsyncOperation Delay(float secondsDelay) { - return AsyncResult.Delay(secondsDelay, GetRootBehaviour().UpdateSource); + return AsyncResult.Delay(secondsDelay, _rootBehaviour.UpdateSource); } /// @@ -236,7 +265,7 @@ public static IAsyncOperation Delay(float secondsDelay) /// public static IAsyncOperation Delay(TimeSpan delay) { - return AsyncResult.Delay(delay, GetRootBehaviour().UpdateSource); + return AsyncResult.Delay(delay, _rootBehaviour.UpdateSource); } /// @@ -255,7 +284,7 @@ public static Coroutine StartCoroutine(IEnumerator enumerator) throw new ArgumentNullException("enumerator"); } - return GetRootBehaviour().StartCoroutine(enumerator); + return _rootBehaviour.StartCoroutine(enumerator); } /// @@ -361,7 +390,7 @@ public static void AddCompletionCallback(UnityWebRequest request, Action complet throw new ArgumentNullException("completionCallback"); } - GetRootBehaviour().AddCompletionCallback(request, completionCallback); + _rootBehaviour.AddCompletionCallback(request, completionCallback); } /// @@ -383,7 +412,7 @@ public static void AddCompletionCallback(WWW request, Action completionCallback) throw new ArgumentNullException("completionCallback"); } - GetRootBehaviour().AddCompletionCallback(request, completionCallback); + _rootBehaviour.AddCompletionCallback(request, completionCallback); } #endregion @@ -547,16 +576,7 @@ private void Update() while (_actionQueue.TryDequeue(out invokeResult)) { - try - { - invokeResult.Start(); - invokeResult.SetCompleted(); - } - catch (Exception e) - { - invokeResult.SetException(e); - Debug.LogException(e, this); - } + invokeResult.Invoke(this); } #else @@ -567,18 +587,7 @@ private void Update() { while (_actionQueue.Count > 0) { - var asyncResult = _actionQueue.Dequeue(); - - try - { - asyncResult.Start(); - asyncResult.SetCompleted(); - } - catch (Exception e) - { - asyncResult.SetException(e); - Debug.LogException(e, this); - } + _actionQueue.Dequeue().Invoke(this); } } } @@ -646,29 +655,27 @@ private IEnumerator EofEnumerator() #endregion } - private sealed class InvokeResult : AsyncResult + private struct InvokeResult { private readonly SendOrPostCallback _callback; + private readonly object _userState; - public InvokeResult(SendOrPostCallback d, object asyncState) - : base(AsyncOperationStatus.Scheduled, asyncState) + public InvokeResult(SendOrPostCallback d, object userState) { _callback = d; + _userState = userState; } - public void SetCompleted() + public void Invoke(UnityEngine.Object context) { - TrySetCompleted(); - } - - public void SetException(Exception e) - { - TrySetException(e); - } - - protected override void OnStarted() - { - _callback.Invoke(AsyncState); + try + { + _callback.Invoke(_userState); + } + catch (Exception e) + { + Debug.LogException(e, context); + } } } @@ -690,34 +697,6 @@ public override void Post(SendOrPostCallback d, object state) } } -#if !NET35 - [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - private static AsyncRootBehaviour GetRootBehaviour() - { - if (ReferenceEquals(_rootBehaviour, null)) - { - InitRootBehaviour(); - } - - return _rootBehaviour; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void InitRootBehaviour() - { - var go = GetRootGo(); - - if (go) - { - _rootBehaviour = go.AddComponent(); - } - else - { - throw new ObjectDisposedException(RootGoName); - } - } - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void Initialize() { @@ -732,6 +711,9 @@ private static void Initialize() // Save the main thread context for future use. _mainThreadContext = context; + // Set main thread context as default for all continuations. This saves allocations in many cases. + AsyncResult.DefaultSynchronizationContext = context; + // Initialize delayed action queue. #if NET_4_6 || NET_STANDARD_2_0 _actionQueue = new ConcurrentQueue(); @@ -739,8 +721,10 @@ private static void Initialize() _actionQueue = new Queue(); #endif - // Set main thread context as default for all continuations. This saves allocations in many cases. - AsyncResult.DefaultSynchronizationContext = context; + // Initialize library components. + _go = new GameObject(RootGoName); + _rootBehaviour = _go.AddComponent(); + GameObject.DontDestroyOnLoad(_go); } #endregion From a20313e8069dfb7209d8a1d9616b6be166b421aa Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Mon, 24 Sep 2018 13:00:42 +0300 Subject: [PATCH 27/57] Added MainThreadSynchronizationContext class --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 169 +-------------- .../MainThreadSynchronizationContext.cs | 194 ++++++++++++++++++ 2 files changed, 201 insertions(+), 162 deletions(-) create mode 100644 src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/MainThreadSynchronizationContext.cs diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index e9c9959..9fefffd 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -22,11 +22,6 @@ public static class AsyncUtility #region data private static SynchronizationContext _mainThreadContext; -#if NET_4_6 || NET_STANDARD_2_0 - private static ConcurrentQueue _actionQueue; -#else - private static Queue _actionQueue; -#endif private static GameObject _go; private static AsyncRootBehaviour _rootBehaviour; @@ -101,72 +96,7 @@ public static IAsyncUpdateSource GetEndOfFrameUpdateSource() /// public static void SendToMainThread(SendOrPostCallback d, object state) { - if (d == null) - { - throw new ArgumentNullException("d"); - } - - if (_mainThreadContext == SynchronizationContext.Current) - { - d.Invoke(state); - } - else - { - var completed = false; - var exception = default(Exception); - var asyncResult = new InvokeResult( - args => - { - try - { - d.Invoke(args); - } - catch (Exception e) - { - exception = e; - } - finally - { - completed = true; - } - }, - state); - -#if NET_4_6 || NET_STANDARD_2_0 - - _actionQueue.Enqueue(asyncResult); - - var sw = new SpinWait(); - - while (!completed) - { - sw.SpinOnce(); - } - - if (exception != null) - { - ExceptionDispatchInfo.Capture(exception).Throw(); - } - -#else - - lock (_actionQueue) - { - _actionQueue.Enqueue(asyncResult); - } - - while (!completed) - { - Thread.SpinWait(1); - } - - if (exception != null) - { - throw exception; - } - -#endif - } + _mainThreadContext.Send(d, state); } /// @@ -179,25 +109,7 @@ public static void SendToMainThread(SendOrPostCallback d, object state) /// public static void PostToMainThread(SendOrPostCallback d, object state) { - if (d == null) - { - throw new ArgumentNullException("d"); - } - - var asyncResult = new InvokeResult(d, state); - -#if NET_4_6 || NET_STANDARD_2_0 - - _actionQueue.Enqueue(asyncResult); - -#else - - lock (_actionQueue) - { - _actionQueue.Enqueue(asyncResult); - } - -#endif + _mainThreadContext.Post(d, state); } /// @@ -216,7 +128,7 @@ public static void InvokeOnMainThread(SendOrPostCallback d, object state) } else { - PostToMainThread(d, state); + _mainThreadContext.Post(d, state); } } @@ -570,29 +482,10 @@ private void Update() } } -#if NET_4_6 || NET_STANDARD_2_0 - - InvokeResult invokeResult; - - while (_actionQueue.TryDequeue(out invokeResult)) + if (_mainThreadContext is Helpers.MainThreadSynchronizationContext) { - invokeResult.Invoke(this); + (_mainThreadContext as Helpers.MainThreadSynchronizationContext).Update(this); } - -#else - - if (_actionQueue.Count > 0) - { - lock (_actionQueue) - { - while (_actionQueue.Count > 0) - { - _actionQueue.Dequeue().Invoke(this); - } - } - } - -#endif } private void LateUpdate() @@ -655,48 +548,6 @@ private IEnumerator EofEnumerator() #endregion } - private struct InvokeResult - { - private readonly SendOrPostCallback _callback; - private readonly object _userState; - - public InvokeResult(SendOrPostCallback d, object userState) - { - _callback = d; - _userState = userState; - } - - public void Invoke(UnityEngine.Object context) - { - try - { - _callback.Invoke(_userState); - } - catch (Exception e) - { - Debug.LogException(e, context); - } - } - } - - private sealed class MainThreadSynchronizationContext : SynchronizationContext - { - public override SynchronizationContext CreateCopy() - { - return new MainThreadSynchronizationContext(); - } - - public override void Send(SendOrPostCallback d, object state) - { - SendToMainThread(d, state); - } - - public override void Post(SendOrPostCallback d, object state) - { - PostToMainThread(d, state); - } - } - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void Initialize() { @@ -704,7 +555,8 @@ private static void Initialize() if (context == null) { - context = new MainThreadSynchronizationContext(); + // Create custom SynchronizationContext for the main thread. + context = new Helpers.MainThreadSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(context); } @@ -714,13 +566,6 @@ private static void Initialize() // Set main thread context as default for all continuations. This saves allocations in many cases. AsyncResult.DefaultSynchronizationContext = context; - // Initialize delayed action queue. -#if NET_4_6 || NET_STANDARD_2_0 - _actionQueue = new ConcurrentQueue(); -#else - _actionQueue = new Queue(); -#endif - // Initialize library components. _go = new GameObject(RootGoName); _rootBehaviour = _go.AddComponent(); diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/MainThreadSynchronizationContext.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/MainThreadSynchronizationContext.cs new file mode 100644 index 0000000..cc35665 --- /dev/null +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/MainThreadSynchronizationContext.cs @@ -0,0 +1,194 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +#if NET_4_6 || NET_STANDARD_2_0 +using System.Collections.Concurrent; +using System.Runtime.ExceptionServices; +#endif +using System.Threading; +using UnityEngine; + +namespace UnityFx.Async.Helpers +{ + /// + /// Implementation of for Unity. + /// + public sealed class MainThreadSynchronizationContext : SynchronizationContext + { + #region data + + private struct InvokeResult + { + private readonly SendOrPostCallback _callback; + private readonly object _userState; + + public InvokeResult(SendOrPostCallback d, object userState) + { + _callback = d; + _userState = userState; + } + + public void Invoke(UnityEngine.Object context) + { + try + { + _callback.Invoke(_userState); + } + catch (Exception e) + { + Debug.LogException(e, context); + } + } + } + +#if NET_4_6 || NET_STANDARD_2_0 + private readonly ConcurrentQueue _actionQueue = new ConcurrentQueue(); +#else + private readonly Queue _actionQueue = new Queue(); +#endif + + #endregion + + #region interface + + /// + /// Calls all delegates scheduled to execute on the main thread. + /// + public void Update(UnityEngine.Object context) + { +#if NET_4_6 || NET_STANDARD_2_0 + + InvokeResult invokeResult; + + while (_actionQueue.TryDequeue(out invokeResult)) + { + invokeResult.Invoke(context); + } + +#else + + if (_actionQueue.Count > 0) + { + lock (_actionQueue) + { + while (_actionQueue.Count > 0) + { + _actionQueue.Dequeue().Invoke(context); + } + } + } + +#endif + } + + #endregion + + #region SynchronizationContext + + /// + public override SynchronizationContext CreateCopy() + { + return new MainThreadSynchronizationContext(); + } + + /// + public override void Send(SendOrPostCallback d, object state) + { + if (d == null) + { + throw new ArgumentNullException("d"); + } + + if (this == Current) + { + d.Invoke(state); + } + else + { + var completed = false; + var exception = default(Exception); + var asyncResult = new InvokeResult( + args => + { + try + { + d.Invoke(args); + } + catch (Exception e) + { + exception = e; + } + finally + { + completed = true; + } + }, + state); + +#if NET_4_6 || NET_STANDARD_2_0 + + _actionQueue.Enqueue(asyncResult); + + var sw = new SpinWait(); + + while (!completed) + { + sw.SpinOnce(); + } + + if (exception != null) + { + ExceptionDispatchInfo.Capture(exception).Throw(); + } + +#else + + lock (_actionQueue) + { + _actionQueue.Enqueue(asyncResult); + } + + while (!completed) + { + Thread.SpinWait(1); + } + + if (exception != null) + { + throw exception; + } + +#endif + } + } + + /// + public override void Post(SendOrPostCallback d, object state) + { + if (d == null) + { + throw new ArgumentNullException("d"); + } + + var asyncResult = new InvokeResult(d, state); + +#if NET_4_6 || NET_STANDARD_2_0 + + _actionQueue.Enqueue(asyncResult); + +#else + + lock (_actionQueue) + { + _actionQueue.Enqueue(asyncResult); + } + +#endif + } + + #endregion + } +} From 0cfc61d7abd1faac2b2a6c5c49d84b7e66d4b2f9 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Mon, 24 Sep 2018 16:05:07 +0300 Subject: [PATCH 28/57] Moved some IAsyncOperationEvents methods to extensions --- .../Api/Extensions/AsyncExtensions.cs | 72 +++++++++++++++++++ .../Api/Interfaces/IAsyncOperationEvents.cs | 64 ----------------- .../Public}/AsyncLazy.cs | 0 .../Public/AsyncResult.Events.cs | 60 ---------------- 4 files changed, 72 insertions(+), 124 deletions(-) rename src/UnityFx.Async/{Api => Implementation/Public}/AsyncLazy.cs (100%) diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs index 41d8bc9..03cc5d1 100644 --- a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs @@ -240,6 +240,78 @@ public static IAsyncOperation WithCancellation(this IAsyncOperation op, Cancella return op; } +#endif + + #endregion + + #region IAsyncOperationEvents + + /// + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. + /// + /// + /// The is invoked on a thread that registered the continuation (if it has a attached). + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation has completed. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback) + { + op.AddCompletionCallback(callback, SynchronizationContext.Current); + } + + /// + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. + /// + /// + /// The is invoked on a thread that registered the continuation (if it has a attached). + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation has completed. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback) + { + op.AddCompletionCallback(callback, SynchronizationContext.Current); + } + + /// + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. + /// + /// + /// The is invoked on a thread that registered the callback (if it has a attached). + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation progress has changed. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback) + { + op.AddProgressCallback(callback, SynchronizationContext.Current); + } + +#if !NET35 + + /// + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. + /// + /// + /// The is invoked on a thread that registered the callback (if it has a attached). + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation progress has changed. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback) + { + op.AddProgressCallback(callback, SynchronizationContext.Current); + } + #endif #endregion diff --git a/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs b/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs index 96c2ed2..195007e 100644 --- a/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs +++ b/src/UnityFx.Async/Api/Interfaces/IAsyncOperationEvents.cs @@ -39,20 +39,6 @@ public interface IAsyncOperationEvents /// event AsyncCompletedEventHandler Completed; - /// - /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the continuation (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation has completed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - /// - /// - void AddCompletionCallback(Action callback); - /// /// Adds a completion callback to be executed after the operation has completed. If the operation is completed is invoked /// on the specified. @@ -66,7 +52,6 @@ public interface IAsyncOperationEvents /// /// Thrown if is . /// Thrown is the operation has been disposed. - /// /// void AddCompletionCallback(Action callback, SynchronizationContext syncContext); @@ -75,24 +60,9 @@ public interface IAsyncOperationEvents /// /// The callback to remove. Can be . /// Returns if was removed; otherwise. - /// /// bool RemoveCompletionCallback(Action callback); - /// - /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the continuation (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation has completed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - /// - /// - void AddCompletionCallback(IAsyncContinuation callback); - /// /// Adds a completion callback to be executed after the operation has completed. If the operation is completed is invoked /// on the specified. @@ -106,7 +76,6 @@ public interface IAsyncOperationEvents /// /// Thrown if is . /// Thrown is the operation has been disposed. - /// /// void AddCompletionCallback(IAsyncContinuation callback, SynchronizationContext syncContext); @@ -115,24 +84,9 @@ public interface IAsyncOperationEvents /// /// The callback to remove. Can be . /// Returns if was removed; otherwise. - /// /// bool RemoveCompletionCallback(IAsyncContinuation callback); - /// - /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the callback (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation progress has changed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - /// - /// - void AddProgressCallback(Action callback); - /// /// Adds a callback to be executed when the operation progress has changed. If the operation is completed is invoked /// on the specified. @@ -146,7 +100,6 @@ public interface IAsyncOperationEvents /// /// Thrown if is . /// Thrown is the operation has been disposed. - /// /// void AddProgressCallback(Action callback, SynchronizationContext syncContext); @@ -155,26 +108,11 @@ public interface IAsyncOperationEvents /// /// The callback to remove. Can be . /// Returns if was removed; otherwise. - /// /// bool RemoveProgressCallback(Action callback); #if !NET35 - /// - /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the callback (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation progress has changed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - /// - /// - void AddProgressCallback(IProgress callback); - /// /// Adds a callback to be executed when the operation progress has changed. If the operation is completed is invoked /// on the specified. @@ -188,7 +126,6 @@ public interface IAsyncOperationEvents /// /// Thrown if is . /// Thrown is the operation has been disposed. - /// /// void AddProgressCallback(IProgress callback, SynchronizationContext syncContext); @@ -197,7 +134,6 @@ public interface IAsyncOperationEvents /// /// The callback to remove. Can be . /// Returns if was removed; otherwise. - /// /// bool RemoveProgressCallback(IProgress callback); diff --git a/src/UnityFx.Async/Api/AsyncLazy.cs b/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs similarity index 100% rename from src/UnityFx.Async/Api/AsyncLazy.cs rename to src/UnityFx.Async/Implementation/Public/AsyncLazy.cs diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs index c883143..bdce2e4 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.Events.cs @@ -105,21 +105,6 @@ public event AsyncCompletedEventHandler Completed } } - /// - /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the continuation (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation has completed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - public void AddCompletionCallback(Action action) - { - AddCompletionCallback(action, SynchronizationContext.Current); - } - /// /// Adds a completion callback to be executed after the operation has completed. If the operation is completed is invoked /// on the specified. @@ -159,21 +144,6 @@ public bool RemoveCompletionCallback(Action action) return TryRemoveCallback(action); } - /// - /// Adds a continuation to be executed after the operation has completed. If the operation is completed is invoked synchronously. - /// - /// - /// The is invoked on a thread that registered the continuation (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation has completed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - public void AddCompletionCallback(IAsyncContinuation continuation) - { - AddCompletionCallback(continuation, SynchronizationContext.Current); - } - /// /// Adds a continuation to be executed after the operation has completed. If the operation is completed /// is invoked on the specified. @@ -213,21 +183,6 @@ public bool RemoveCompletionCallback(IAsyncContinuation continuation) return TryRemoveCallback(continuation); } - /// - /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. - /// - /// - /// The is invoked on a thread that registered the callback (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation progress has changed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - public void AddProgressCallback(Action action) - { - AddProgressCallback(action, SynchronizationContext.Current); - } - /// /// Adds a callback to be executed when the operation progress has changed. If the operation is completed is invoked /// on the specified. @@ -268,21 +223,6 @@ public bool RemoveProgressCallback(Action action) #if !NET35 - /// - /// Adds a callback to be executed each time progress value changes. If the operation is completed is invoked synchronously. - /// - /// - /// The is invoked on a thread that registered it (if it has a attached). - /// Throwing an exception from the callback might cause unspecified behaviour. - /// - /// The callback to be executed when the operation progress value has changed. - /// Thrown if is . - /// Thrown is the operation has been disposed. - public void AddProgressCallback(IProgress callback) - { - AddProgressCallback(callback, SynchronizationContext.Current); - } - /// /// Adds a callback to be executed each time progress value changes. If the operation is completed /// is invoked on the specified. From ac7748d397eab48aafba5fff3707d8cae8946ffc Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Mon, 24 Sep 2018 16:52:37 +0300 Subject: [PATCH 29/57] Added new overloads for Send/Post/Invoke helpers --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 9fefffd..d7b353f 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -24,6 +24,7 @@ public static class AsyncUtility private static SynchronizationContext _mainThreadContext; private static GameObject _go; private static AsyncRootBehaviour _rootBehaviour; + private static SendOrPostCallback _actionCallback; #endregion @@ -86,12 +87,36 @@ public static IAsyncUpdateSource GetEndOfFrameUpdateSource() return _rootBehaviour.EofUpdateSource; } + /// + /// Dispatches a synchronous message to the main thread. + /// + /// The delegate to invoke. + /// Thrown if is . + /// + /// + /// + public static void SendToMainThread(Action action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_actionCallback == null) + { + _actionCallback = ActionCallback; + } + + _mainThreadContext.Send(_actionCallback, action); + } + /// /// Dispatches a synchronous message to the main thread. /// /// The delegate to invoke. /// The object passed to the delegate. /// Thrown if is . + /// /// /// public static void SendToMainThread(SendOrPostCallback d, object state) @@ -99,12 +124,36 @@ public static void SendToMainThread(SendOrPostCallback d, object state) _mainThreadContext.Send(d, state); } + /// + /// Dispatches an asynchronous message to the main thread. + /// + /// The delegate to invoke. + /// Thrown if is . + /// + /// + /// + public static void PostToMainThread(Action action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_actionCallback == null) + { + _actionCallback = ActionCallback; + } + + _mainThreadContext.Post(_actionCallback, action); + } + /// /// Dispatches an asynchronous message to the main thread. /// /// The delegate to invoke. /// The object passed to the delegate. /// Thrown if is . + /// /// /// public static void PostToMainThread(SendOrPostCallback d, object state) @@ -112,18 +161,54 @@ public static void PostToMainThread(SendOrPostCallback d, object state) _mainThreadContext.Post(d, state); } + /// + /// Dispatches the specified delegate on the main thread. + /// + /// The delegate to invoke. + /// Thrown if is . + /// + /// + /// + public static void InvokeOnMainThread(Action action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_mainThreadContext == SynchronizationContext.Current) + { + action.Invoke(); + } + else + { + if (_actionCallback == null) + { + _actionCallback = ActionCallback; + } + + _mainThreadContext.Post(_actionCallback, action); + } + } + /// /// Dispatches the specified delegate on the main thread. /// /// The delegate to invoke. /// The object passed to the delegate. /// Thrown if is . + /// /// /// public static void InvokeOnMainThread(SendOrPostCallback d, object state) { if (_mainThreadContext == SynchronizationContext.Current) { + if (d == null) + { + throw new ArgumentNullException(nameof(d)); + } + d.Invoke(state); } else @@ -572,6 +657,11 @@ private static void Initialize() GameObject.DontDestroyOnLoad(_go); } + private static void ActionCallback(object args) + { + ((Action)args).Invoke(); + } + #endregion } } From ca6529228acaba63530d0445706eba903ae54a30 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 11:24:02 +0300 Subject: [PATCH 30/57] Added AddFrameCallback utility method --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 123 ++++++++++++++++++ .../UnityFx.Async/Scripts/FrameTiming.cs | 28 ++++ 2 files changed, 151 insertions(+) create mode 100644 src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/FrameTiming.cs diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index d7b353f..defa6df 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -412,6 +412,22 @@ public static void AddCompletionCallback(WWW request, Action completionCallback) _rootBehaviour.AddCompletionCallback(request, completionCallback); } + /// + /// Register a completion callback that is triggered on a specific time during next frame. + /// + /// A delegate to be called on the next frame. + /// Time to call the . + /// Thrown if is . + public static void AddFrameCallback(Action callback, FrameTiming timing) + { + if (callback == null) + { + throw new ArgumentNullException("callback"); + } + + _rootBehaviour.AddFrameCallback(callback, timing); + } + #endregion #region implementation @@ -429,6 +445,20 @@ private sealed class AsyncRootBehaviour : MonoBehaviour private AsyncUpdateSource _eofUpdateSource; private WaitForEndOfFrame _eof; +#if NET_4_6 || NET_STANDARD_2_0 + + private ConcurrentQueue _updateActions; + private ConcurrentQueue _lateUpdateActions; + private ConcurrentQueue _fixedUpdateActions; + +#else + + private Queue _updateActions; + private Queue _lateUpdateActions; + private Queue _fixedUpdateActions; + +#endif + #endregion #region interface @@ -498,6 +528,24 @@ public void AddCompletionCallback(object op, Action cb) _ops.Add(op, cb); } + public void AddFrameCallback(Action callback, FrameTiming timing) + { + switch (timing) + { + case FrameTiming.FixedUpdate: + AddFrameCallback(ref _fixedUpdateActions, callback); + break; + + case FrameTiming.Update: + AddFrameCallback(ref _updateActions, callback); + break; + + case FrameTiming.LateUpdate: + AddFrameCallback(ref _lateUpdateActions, callback); + break; + } + } + #endregion #region MonoBehavoiur @@ -567,6 +615,11 @@ private void Update() } } + if (_updateActions != null) + { + InvokeFrameCallbacks(_updateActions, this); + } + if (_mainThreadContext is Helpers.MainThreadSynchronizationContext) { (_mainThreadContext as Helpers.MainThreadSynchronizationContext).Update(this); @@ -579,6 +632,11 @@ private void LateUpdate() { _lateUpdateSource.OnNext(Time.deltaTime); } + + if (_lateUpdateActions != null) + { + InvokeFrameCallbacks(_lateUpdateActions, this); + } } private void FixedUpdate() @@ -587,6 +645,11 @@ private void FixedUpdate() { _fixedUpdateSource.OnNext(Time.fixedDeltaTime); } + + if (_fixedUpdateActions != null) + { + InvokeFrameCallbacks(_fixedUpdateActions, this); + } } private void OnDestroy() @@ -620,6 +683,66 @@ private void OnDestroy() #region implementation +#if NET_4_6 || NET_STANDARD_2_0 + + private static void AddFrameCallback(ref ConcurrentQueue actionQueue, Action callback) + { + Interlocked.CompareExchange(ref actionQueue, new ConcurrentQueue(), null); + actionQueue.Enqueue(callback); + } + + private static void InvokeFrameCallbacks(ConcurrentQueue actionQueue, UnityEngine.Object context) + { + Action action; + + while (actionQueue.TryDequeue(out action)) + { + try + { + action.Invoke(); + } + catch (Exception e) + { + Debug.LogException(e, context); + } + } + } + +#else + + private void AddFrameCallback(ref Queue actionQueue, Action callback) + { + Interlocked.CompareExchange(ref actionQueue, new Queue(), null); + + lock (actionQueue) + { + actionQueue.Enqueue(callback); + } + } + + private static void InvokeFrameCallbacks(Queue actionQueue, UnityEngine.Object context) + { + if (actionQueue.Count > 0) + { + lock (actionQueue) + { + while (actionQueue.Count > 0) + { + try + { + actionQueue.Dequeue().Invoke(); + } + catch (Exception e) + { + Debug.LogException(e, context); + } + } + } + } + } + +#endif + private IEnumerator EofEnumerator() { yield return _eof; diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/FrameTiming.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/FrameTiming.cs new file mode 100644 index 0000000..68791b9 --- /dev/null +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/FrameTiming.cs @@ -0,0 +1,28 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async +{ + /// + /// Enumerates time points during a frame. + /// + public enum FrameTiming + { + /// + /// FixedUpdate. + /// + FixedUpdate, + + /// + /// Update. + /// + Update, + + /// + /// LateUpdate. + /// + LateUpdate + } +} From 7ec6db0e3ebdea7b7cce15844304e27b6244628d Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 11:25:13 +0300 Subject: [PATCH 31/57] Changed project structure --- .../Public}/Extensions/AsyncExtensions.Continuations.cs | 0 .../Public}/Extensions/AsyncExtensions.Observables.cs | 0 .../Public}/Extensions/AsyncExtensions.Promises.cs | 0 .../Public}/Extensions/AsyncExtensions.Tasks.cs | 0 .../Public}/Extensions/AsyncExtensions.Wait.cs | 0 .../{Api => Implementation/Public}/Extensions/AsyncExtensions.cs | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.Continuations.cs (100%) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.Observables.cs (100%) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.Promises.cs (100%) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.Tasks.cs (100%) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.Wait.cs (100%) rename src/UnityFx.Async/{Api => Implementation/Public}/Extensions/AsyncExtensions.cs (100%) diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.Continuations.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Continuations.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.Continuations.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Continuations.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.Observables.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Observables.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.Observables.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Observables.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.Promises.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Promises.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.Promises.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Promises.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.Tasks.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.Wait.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Wait.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.Wait.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Wait.cs diff --git a/src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs similarity index 100% rename from src/UnityFx.Async/Api/Extensions/AsyncExtensions.cs rename to src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs From 6080b57d9a4d112875e49968e16e838fe55cbf29 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 14:09:58 +0300 Subject: [PATCH 32/57] Added AsyncResult.Yield() --- .../Public/AsyncResult.Helpers.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs index bd6e214..8a3a6fc 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Threading; #if !NET35 using System.Threading.Tasks; @@ -84,6 +85,23 @@ public static AsyncResult CanceledOperation } } +#if !NET35 + + /// + /// Creates an awaitable that asynchronously yields back to the current context when awaited (works the same as ). + /// + /// + /// A context that, when awaited, will asynchronously transition back into the current context at the + /// time of the await. If the current is non-, + /// that is treated as the current context. Otherwise, the continuation is executed on the . + /// + public static YieldAwaitable Yield() + { + return new YieldAwaitable(); + } + +#endif + #region From* /// From 0879cd47efdb8436804f800e7f5215dbda254ed1 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 14:16:44 +0300 Subject: [PATCH 33/57] Added SynchronizationContext extensions --- .../UnityFx.Async/Scripts/AsyncUtility.cs | 63 +---------- .../Public/Extensions/AsyncExtensions.cs | 100 ++++++++++++++++++ 2 files changed, 104 insertions(+), 59 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index defa6df..19eea99 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -24,7 +24,6 @@ public static class AsyncUtility private static SynchronizationContext _mainThreadContext; private static GameObject _go; private static AsyncRootBehaviour _rootBehaviour; - private static SendOrPostCallback _actionCallback; #endregion @@ -97,17 +96,7 @@ public static IAsyncUpdateSource GetEndOfFrameUpdateSource() /// public static void SendToMainThread(Action action) { - if (action == null) - { - throw new ArgumentNullException(nameof(action)); - } - - if (_actionCallback == null) - { - _actionCallback = ActionCallback; - } - - _mainThreadContext.Send(_actionCallback, action); + _mainThreadContext.Send(action); } /// @@ -134,17 +123,7 @@ public static void SendToMainThread(SendOrPostCallback d, object state) /// public static void PostToMainThread(Action action) { - if (action == null) - { - throw new ArgumentNullException(nameof(action)); - } - - if (_actionCallback == null) - { - _actionCallback = ActionCallback; - } - - _mainThreadContext.Post(_actionCallback, action); + _mainThreadContext.Post(action); } /// @@ -171,24 +150,7 @@ public static void PostToMainThread(SendOrPostCallback d, object state) /// public static void InvokeOnMainThread(Action action) { - if (action == null) - { - throw new ArgumentNullException(nameof(action)); - } - - if (_mainThreadContext == SynchronizationContext.Current) - { - action.Invoke(); - } - else - { - if (_actionCallback == null) - { - _actionCallback = ActionCallback; - } - - _mainThreadContext.Post(_actionCallback, action); - } + _mainThreadContext.Invoke(action); } /// @@ -202,19 +164,7 @@ public static void InvokeOnMainThread(Action action) /// public static void InvokeOnMainThread(SendOrPostCallback d, object state) { - if (_mainThreadContext == SynchronizationContext.Current) - { - if (d == null) - { - throw new ArgumentNullException(nameof(d)); - } - - d.Invoke(state); - } - else - { - _mainThreadContext.Post(d, state); - } + _mainThreadContext.Invoke(d, state); } /// @@ -780,11 +730,6 @@ private static void Initialize() GameObject.DontDestroyOnLoad(_go); } - private static void ActionCallback(object args) - { - ((Action)args).Invoke(); - } - #endregion } } diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs index 03cc5d1..fdb1095 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs @@ -17,6 +17,8 @@ public static partial class AsyncExtensions { #region data + private static SendOrPostCallback _actionCallback; + #if !NET35 private static Action _cancelHandler; @@ -244,6 +246,99 @@ public static IAsyncOperation WithCancellation(this IAsyncOperation op, Cancella #endregion + #region SynchronizationContext + + /// + /// Dispatches an synchronous message to a synchronization context. + /// + /// The target context. + /// The delegate to invoke. + /// Thrown if is . + public static void Send(this SynchronizationContext context, Action action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_actionCallback == null) + { + _actionCallback = ActionCallback; + } + + context.Post(_actionCallback, action); + } + + /// + /// Dispatches an asynchronous message to a synchronization context. + /// + /// The target context. + /// The delegate to invoke. + /// Thrown if is . + public static void Post(this SynchronizationContext context, Action action) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (_actionCallback == null) + { + _actionCallback = ActionCallback; + } + + context.Post(_actionCallback, action); + } + + /// + /// Dispatches a message to a synchronization context. + /// + /// The target context. + /// The delegate to invoke. + /// Thrown if is . + public static void Invoke(this SynchronizationContext context, Action action) + { + if (context == SynchronizationContext.Current) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + action.Invoke(); + } + else + { + context.Post(_actionCallback, action); + } + } + + /// + /// Dispatches a message to a synchronization context. + /// + /// The target context. + /// The delegate to invoke. + /// User-defined state. + /// Thrown if is . + public static void Invoke(this SynchronizationContext context, SendOrPostCallback d, object state) + { + if (context == SynchronizationContext.Current) + { + if (d == null) + { + throw new ArgumentNullException(nameof(d)); + } + + d.Invoke(state); + } + else + { + context.Post(d, state); + } + } + + #endregion + #region IAsyncOperationEvents /// @@ -639,6 +734,11 @@ private static bool SpinUntilCompletedInternal(IAsyncResult op, TimeSpan timeout return true; } + private static void ActionCallback(object args) + { + ((Action)args).Invoke(); + } + #endregion } } From f069dd452209bc4945fe150d45da82640e800961 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 17:31:29 +0300 Subject: [PATCH 34/57] Added ConfigureAwait overloads accepting continuation options --- src/UnityFx.Async/Api/AsyncCallbackOptions.cs | 32 +++++++++ .../Api/AsyncContinuationOptions.cs | 8 +-- .../Extensions/AsyncExtensions.Tasks.cs | 71 ++++++++++++++----- 3 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 src/UnityFx.Async/Api/AsyncCallbackOptions.cs diff --git a/src/UnityFx.Async/Api/AsyncCallbackOptions.cs b/src/UnityFx.Async/Api/AsyncCallbackOptions.cs new file mode 100644 index 0000000..b3ed381 --- /dev/null +++ b/src/UnityFx.Async/Api/AsyncCallbackOptions.cs @@ -0,0 +1,32 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async +{ + /// + /// Specifies the behavior for an operation callbacks. + /// + public enum AsyncCallbackOptions + { + /// + /// Specifies that the continuation should be executed on the same thread that scheduled it. + /// That is the default behaviour. + /// + ExecuteOnCapturedContext, + + /// + /// Specifies that the continuation should be executed on the default thread. Please see + /// for more information. + /// + ExecuteOnDefaultContext, + + /// + /// Specifies that the continuation should be executed synchronously. With this option specified, + /// the continuation runs on the same thread that causes the antecedent operation to transition + /// into its final state. + /// + ExecuteSynchronously + } +} diff --git a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs index 38428dd..377ef5c 100644 --- a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs +++ b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs @@ -2,20 +2,18 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; -using System.Threading; namespace UnityFx.Async { /// - /// Specifies behavior of an asynchronous opration continuation. + /// Specifies the behavior of an asynchronous operation continuation. /// - /// [Flags] public enum AsyncContinuationOptions { /// - /// When no continuation options are specified, specifies that default behavior should be used when executing a continuation. - /// I.e. continuation is scheduled оn the same that was active when the continuation was created. + /// When no continuation options are specified, default behavior should be used when executing a continuation. + /// I.e. continuation is executed on the same thread that scheduled it. /// None = 0, diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs index 0c43053..88e6f2e 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs @@ -23,15 +23,15 @@ partial class AsyncExtensions public struct AsyncAwaiter : INotifyCompletion { private readonly IAsyncOperation _op; - private readonly bool _continueOnCapturedContext; + private readonly AsyncCallbackOptions _options; /// /// Initializes a new instance of the struct. /// - public AsyncAwaiter(IAsyncOperation op, bool continueOnCapturedContext) + public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) { _op = op; - _continueOnCapturedContext = continueOnCapturedContext; + _options = options; } /// @@ -54,7 +54,7 @@ public void GetResult() /// public void OnCompleted(Action continuation) { - SetAwaitContiniation(_op, continuation, _continueOnCapturedContext); + SetAwaitContinuation(_op, continuation, _options); } } @@ -65,15 +65,15 @@ public void OnCompleted(Action continuation) public struct AsyncAwaiter : INotifyCompletion { private readonly IAsyncOperation _op; - private readonly bool _continueOnCapturedContext; + private readonly AsyncCallbackOptions _options; /// /// Initializes a new instance of the struct. /// - public AsyncAwaiter(IAsyncOperation op, bool continueOnCapturedContext) + public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) { _op = op; - _continueOnCapturedContext = continueOnCapturedContext; + _options = options; } /// @@ -99,7 +99,7 @@ public T GetResult() /// public void OnCompleted(Action continuation) { - SetAwaitContiniation(_op, continuation, _continueOnCapturedContext); + SetAwaitContinuation(_op, continuation, _options); } } @@ -114,9 +114,9 @@ public struct ConfiguredAsyncAwaitable /// /// Initializes a new instance of the struct. /// - public ConfiguredAsyncAwaitable(IAsyncOperation op, bool continueOnCapturedContext) + public ConfiguredAsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) { - _awaiter = new AsyncAwaiter(op, continueOnCapturedContext); + _awaiter = new AsyncAwaiter(op, options); } /// @@ -136,9 +136,9 @@ public struct ConfiguredAsyncAwaitable /// /// Initializes a new instance of the struct. /// - public ConfiguredAsyncAwaitable(IAsyncOperation op, bool continueOnCapturedContext) + public ConfiguredAsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) { - _awaiter = new AsyncAwaiter(op, continueOnCapturedContext); + _awaiter = new AsyncAwaiter(op, options); } /// @@ -154,7 +154,7 @@ public ConfiguredAsyncAwaitable(IAsyncOperation op, bool continueOnCapturedCo /// public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new AsyncAwaiter(op, true); + return new AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); } /// @@ -164,7 +164,7 @@ public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) /// public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new AsyncAwaiter(op, true); + return new AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); } /// @@ -175,7 +175,7 @@ public static AsyncAwaiter GetAwaiter(this IAsyncOperationAn object used to await the operation. public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext); + return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); } /// @@ -186,7 +186,29 @@ public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, b /// An object used to await the operation. public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext); + return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); + } + + /// + /// Configures an awaiter used to await this operation. + /// + /// The operation to await. + /// Specifies continuation options. + /// An object used to await the operation. + public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + { + return new ConfiguredAsyncAwaitable(op, continuationOptions); + } + + /// + /// Configures an awaiter used to await this operation. + /// + /// The operation to await. + /// Specifies continuation options. + /// An object used to await the operation. + public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + { + return new ConfiguredAsyncAwaitable(op, continuationOptions); } #endregion @@ -319,9 +341,22 @@ public static AsyncResult ToAsync(this Task task) #region implementation - private static void SetAwaitContiniation(IAsyncOperation op, Action continuation, bool captureSynchronizationContext) + private static void SetAwaitContinuation(IAsyncOperation op, Action continuation, AsyncCallbackOptions options) { - var syncContext = captureSynchronizationContext ? SynchronizationContext.Current : null; + SynchronizationContext syncContext; + + if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) + { + syncContext = SynchronizationContext.Current; + } + else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) + { + syncContext = AsyncResult.DefaultSynchronizationContext; + } + else + { + syncContext = null; + } if (op is AsyncResult ar) { From 92e9b193cb714ea69c1dfd7d4bb3d8b90b8e7814 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 19:05:04 +0300 Subject: [PATCH 35/57] CHANGELOG update --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d1734c..05e11b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj ### Added - Added convenience overloads for `SetException`-like methods accepting as error message string. - Added allocation optimizations for single-threaded applications (particularly for Unity3d). See `AsyncResult.DefaultSynchronizationContext` for more info. +- Added new overloads for `ConfigureAwait` extensions accepting continuation options instead of boolean flag. +- Added `SynchronizationContext` extension methods for `Send`/`Post` accepting `Action` as the delegate. +- Added `AsyncResult.Yield` static method (workd exactly as `Task.Yield`). +- Added `AsyncUtility.AddFrameCallback` helper for scheduling delegates for `MonoBehaviour` update loop. - Added performance benchmarks. +### Changed +- Moved several of `IAsyncOperationEvents` methods to the interface extensions. + ### Fixed - Fixed error handling in `AsyncOperationResult`. From 05e4150f9d6178bf7ccedf19520034ae8fcc11d3 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 21:05:06 +0300 Subject: [PATCH 36/57] Added new overloads for AddCompletionCallback/AddProgressCallback extensions --- .../Extensions/AsyncExtensions.Tasks.cs | 15 +-- .../Public/Extensions/AsyncExtensions.cs | 104 +++++++++++++++++- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs index 88e6f2e..3afe8a1 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs @@ -343,20 +343,7 @@ public static AsyncResult ToAsync(this Task task) private static void SetAwaitContinuation(IAsyncOperation op, Action continuation, AsyncCallbackOptions options) { - SynchronizationContext syncContext; - - if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) - { - syncContext = SynchronizationContext.Current; - } - else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) - { - syncContext = AsyncResult.DefaultSynchronizationContext; - } - else - { - syncContext = null; - } + var syncContext = GetContext(options); if (op is AsyncResult ar) { diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs index fdb1095..6911ad3 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs @@ -342,7 +342,8 @@ public static void Invoke(this SynchronizationContext context, SendOrPostCallbac #region IAsyncOperationEvents /// - /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed + /// the is called synchronously. /// /// /// The is invoked on a thread that registered the continuation (if it has a attached). @@ -358,7 +359,26 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, Action - /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed the is called synchronously. + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed + /// the is invoked on a context specified via . + /// + /// + /// The is invoked on a specified. + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation has completed. + /// The callback options. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) + { + op.AddCompletionCallback(callback, GetContext(options)); + } + + /// + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed + /// the is called synchronously. /// /// /// The is invoked on a thread that registered the continuation (if it has a attached). @@ -374,7 +394,26 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncCo } /// - /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. + /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed + /// the is invoked on a context specified via . + /// + /// + /// The is invoked on a specified. + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation has completed. + /// The callback options. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback, AsyncCallbackOptions options) + { + op.AddCompletionCallback(callback, GetContext(options)); + } + + /// + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed + /// the is called synchronously. /// /// /// The is invoked on a thread that registered the callback (if it has a attached). @@ -389,10 +428,29 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, Action + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed + /// the is invoked on a context specified via . + /// + /// + /// The is invoked on a specified. + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation progress has changed. + /// The callback options. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) + { + op.AddProgressCallback(callback, GetContext(options)); + } + #if !NET35 /// - /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed the is called synchronously. + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed + /// the is called synchronously. /// /// /// The is invoked on a thread that registered the callback (if it has a attached). @@ -407,6 +465,24 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress< op.AddProgressCallback(callback, SynchronizationContext.Current); } + /// + /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed + /// the is invoked on a context specified via . + /// + /// + /// The is invoked on a specified. + /// Throwing an exception from the callback might cause unspecified behaviour. + /// + /// The operation to schedule continuation for. + /// The callback to be executed when the operation progress has changed. + /// The callback options. + /// Thrown if is . + /// Thrown is the operation has been disposed. + public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback, AsyncCallbackOptions options) + { + op.AddProgressCallback(callback, GetContext(options)); + } + #endif #endregion @@ -734,6 +810,26 @@ private static bool SpinUntilCompletedInternal(IAsyncResult op, TimeSpan timeout return true; } + private static SynchronizationContext GetContext(AsyncCallbackOptions options) + { + SynchronizationContext syncContext; + + if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) + { + syncContext = SynchronizationContext.Current; + } + else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) + { + syncContext = AsyncResult.DefaultSynchronizationContext; + } + else + { + syncContext = null; + } + + return syncContext; + } + private static void ActionCallback(object args) { ((Action)args).Invoke(); From 3bab063f6671b9fb74205864b01ed65e02513851 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 21:34:56 +0300 Subject: [PATCH 37/57] Added Unity sandbox project --- .gitignore | 4 + BuildSandbox.bat | 3 + unity/Sandbox/Assets/Plugins.meta | 8 + unity/Sandbox/Assets/Scenes.meta | 8 + unity/Sandbox/Assets/Scenes/Main.unity | 196 ++++++ unity/Sandbox/Assets/Scenes/Main.unity.meta | 7 + unity/Sandbox/Assets/Scripts.meta | 8 + unity/Sandbox/Assets/Scripts/MainBehaviour.cs | 16 + .../Assets/Scripts/MainBehaviour.cs.meta | 11 + unity/Sandbox/Packages/manifest.json | 39 ++ .../ProjectSettings/AudioManager.asset | 17 + .../ProjectSettings/ClusterInputManager.asset | 6 + .../ProjectSettings/DynamicsManager.asset | 29 + .../ProjectSettings/EditorBuildSettings.asset | 8 + .../ProjectSettings/EditorSettings.asset | 22 + .../ProjectSettings/GraphicsSettings.asset | 61 ++ .../ProjectSettings/InputManager.asset | 295 +++++++++ .../ProjectSettings/NavMeshAreas.asset | 91 +++ .../ProjectSettings/Physics2DSettings.asset | 55 ++ .../ProjectSettings/PresetManager.asset | 6 + .../ProjectSettings/ProjectSettings.asset | 623 ++++++++++++++++++ .../ProjectSettings/ProjectVersion.txt | 1 + .../ProjectSettings/QualitySettings.asset | 224 +++++++ .../Sandbox/ProjectSettings/TagManager.asset | 43 ++ .../Sandbox/ProjectSettings/TimeManager.asset | 9 + .../UnityConnectSettings.asset | 34 + 26 files changed, 1824 insertions(+) create mode 100644 BuildSandbox.bat create mode 100644 unity/Sandbox/Assets/Plugins.meta create mode 100644 unity/Sandbox/Assets/Scenes.meta create mode 100644 unity/Sandbox/Assets/Scenes/Main.unity create mode 100644 unity/Sandbox/Assets/Scenes/Main.unity.meta create mode 100644 unity/Sandbox/Assets/Scripts.meta create mode 100644 unity/Sandbox/Assets/Scripts/MainBehaviour.cs create mode 100644 unity/Sandbox/Assets/Scripts/MainBehaviour.cs.meta create mode 100644 unity/Sandbox/Packages/manifest.json create mode 100644 unity/Sandbox/ProjectSettings/AudioManager.asset create mode 100644 unity/Sandbox/ProjectSettings/ClusterInputManager.asset create mode 100644 unity/Sandbox/ProjectSettings/DynamicsManager.asset create mode 100644 unity/Sandbox/ProjectSettings/EditorBuildSettings.asset create mode 100644 unity/Sandbox/ProjectSettings/EditorSettings.asset create mode 100644 unity/Sandbox/ProjectSettings/GraphicsSettings.asset create mode 100644 unity/Sandbox/ProjectSettings/InputManager.asset create mode 100644 unity/Sandbox/ProjectSettings/NavMeshAreas.asset create mode 100644 unity/Sandbox/ProjectSettings/Physics2DSettings.asset create mode 100644 unity/Sandbox/ProjectSettings/PresetManager.asset create mode 100644 unity/Sandbox/ProjectSettings/ProjectSettings.asset create mode 100644 unity/Sandbox/ProjectSettings/ProjectVersion.txt create mode 100644 unity/Sandbox/ProjectSettings/QualitySettings.asset create mode 100644 unity/Sandbox/ProjectSettings/TagManager.asset create mode 100644 unity/Sandbox/ProjectSettings/TimeManager.asset create mode 100644 unity/Sandbox/ProjectSettings/UnityConnectSettings.asset diff --git a/.gitignore b/.gitignore index a117284..40da59b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ [Bb]uild/ [Bb]uilds/ +# Unity sandbox +/unity/Sandbox/Assets/Plugins/ +/unity/Sandbox/*.* + # Visual Studio cache directory .vs/ .vscode/ diff --git a/BuildSandbox.bat b/BuildSandbox.bat new file mode 100644 index 0000000..22b6119 --- /dev/null +++ b/BuildSandbox.bat @@ -0,0 +1,3 @@ +powershell .\src\Build.ps1 Release +rd unity\Sandbox\Assets\Plugins /S /Q +xcopy bin\AssetStore\netstandard2.0 unity\Sandbox /S diff --git a/unity/Sandbox/Assets/Plugins.meta b/unity/Sandbox/Assets/Plugins.meta new file mode 100644 index 0000000..cc089cd --- /dev/null +++ b/unity/Sandbox/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23e3c25ef357701448d443d61ea39944 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox/Assets/Scenes.meta b/unity/Sandbox/Assets/Scenes.meta new file mode 100644 index 0000000..088efb7 --- /dev/null +++ b/unity/Sandbox/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c606bc6a077d66a4eab7086ae54dab15 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox/Assets/Scenes/Main.unity b/unity/Sandbox/Assets/Scenes/Main.unity new file mode 100644 index 0000000..406d84a --- /dev/null +++ b/unity/Sandbox/Assets/Scenes/Main.unity @@ -0,0 +1,196 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.37311992, g: 0.38074034, b: 0.35872713, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1712355737 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1712355740} + - component: {fileID: 1712355739} + - component: {fileID: 1712355738} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1712355738 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1712355737} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0861e138486c9174d85ee359951f5762, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!20 &1712355739 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1712355737} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1712355740 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1712355737} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/unity/Sandbox/Assets/Scenes/Main.unity.meta b/unity/Sandbox/Assets/Scenes/Main.unity.meta new file mode 100644 index 0000000..58134d9 --- /dev/null +++ b/unity/Sandbox/Assets/Scenes/Main.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8b5b3c069aaf76d43bedb5862e2bf669 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox/Assets/Scripts.meta b/unity/Sandbox/Assets/Scripts.meta new file mode 100644 index 0000000..ca1f403 --- /dev/null +++ b/unity/Sandbox/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b12d9b9e6f9f247b2ed316c10de51e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox/Assets/Scripts/MainBehaviour.cs b/unity/Sandbox/Assets/Scripts/MainBehaviour.cs new file mode 100644 index 0000000..66a6ea6 --- /dev/null +++ b/unity/Sandbox/Assets/Scripts/MainBehaviour.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class MainBehaviour : MonoBehaviour { + + // Use this for initialization + void Start () { + + } + + // Update is called once per frame + void Update () { + + } +} diff --git a/unity/Sandbox/Assets/Scripts/MainBehaviour.cs.meta b/unity/Sandbox/Assets/Scripts/MainBehaviour.cs.meta new file mode 100644 index 0000000..49b7ea5 --- /dev/null +++ b/unity/Sandbox/Assets/Scripts/MainBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0861e138486c9174d85ee359951f5762 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox/Packages/manifest.json b/unity/Sandbox/Packages/manifest.json new file mode 100644 index 0000000..1342d0a --- /dev/null +++ b/unity/Sandbox/Packages/manifest.json @@ -0,0 +1,39 @@ +{ + "dependencies": { + "com.unity.ads": "2.0.8", + "com.unity.analytics": "2.0.16", + "com.unity.package-manager-ui": "1.9.11", + "com.unity.purchasing": "2.0.3", + "com.unity.textmeshpro": "1.2.4", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/unity/Sandbox/ProjectSettings/AudioManager.asset b/unity/Sandbox/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..4f31e74 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/AudioManager.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 diff --git a/unity/Sandbox/ProjectSettings/ClusterInputManager.asset b/unity/Sandbox/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/unity/Sandbox/ProjectSettings/DynamicsManager.asset b/unity/Sandbox/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..78992f0 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,29 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 7 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 diff --git a/unity/Sandbox/ProjectSettings/EditorBuildSettings.asset b/unity/Sandbox/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..0147887 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] + m_configObjects: {} diff --git a/unity/Sandbox/ProjectSettings/EditorSettings.asset b/unity/Sandbox/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..1666f77 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/EditorSettings.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 7 + m_ExternalVersionControlSupport: Hidden Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 0 + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp + m_ProjectGenerationRootNamespace: + m_UserGeneratedProjectSuffix: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInPlayMode: 1 diff --git a/unity/Sandbox/ProjectSettings/GraphicsSettings.asset b/unity/Sandbox/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..74d7b53 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,61 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 diff --git a/unity/Sandbox/ProjectSettings/InputManager.asset b/unity/Sandbox/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/unity/Sandbox/ProjectSettings/NavMeshAreas.asset b/unity/Sandbox/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/unity/Sandbox/ProjectSettings/Physics2DSettings.asset b/unity/Sandbox/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..8e9e021 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 3 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_AutoSyncTransforms: 1 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/unity/Sandbox/ProjectSettings/PresetManager.asset b/unity/Sandbox/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..636a595 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/PresetManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + m_DefaultList: [] diff --git a/unity/Sandbox/ProjectSettings/ProjectSettings.asset b/unity/Sandbox/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..a5ff07e --- /dev/null +++ b/unity/Sandbox/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,623 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 15 + productGUID: 8f61f43e5bb6f824f836567728287460 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: Sandbox + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosAppInBackgroundBehavior: 0 + displayResolutionDialog: 1 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidBlitType: 0 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 0 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 0 + graphicsJobs: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + graphicsJobMode: 0 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + n3dsDisableStereoscopicView: 0 + n3dsEnableSharedListOpt: 1 + n3dsEnableVSync: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + videoMemoryForVertexBuffers: 0 + psp2PowerMode: 0 + psp2AcquireBGM: 1 + vulkanEnableSetSRGBWrite: 0 + vulkanUseSWCommandBuffers: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 1.0 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 0 + xboxOneEnable7thCore: 1 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + minimumSupportedHeadTracking: 0 + maximumSupportedHeadTracking: 1 + hololens: + depthFormat: 1 + depthBufferSharingEnabled: 0 + oculus: + sharedDepthBuffer: 0 + dashSupport: 0 + enable360StereoCapture: 0 + protectGraphicsMemory: 0 + useHDRDisplay: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 16 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 8.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 9.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPhone47inSplashScreen: {fileID: 0} + iPhone55inPortraitSplashScreen: {fileID: 0} + iPhone55inLandscapeSplashScreen: {fileID: 0} + iPhone58inPortraitSplashScreen: {fileID: 0} + iPhone58inLandscapeSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSUseLaunchScreenStoryboard: 0 + iOSLaunchScreenCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + appleEnableProMotion: 0 + vulkanEditorSupport: 0 + clonedFromGUID: 00000000000000000000000000000000 + templatePackageId: + templateDefaultScene: + AndroidTargetArchitectures: 1 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 1 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + resolutionDialogBanner: {fileID: 0} + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: [] + m_BuildTargetGraphicsAPIs: [] + m_BuildTargetVRSettings: [] + m_BuildTargetEnableVuforiaSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchSupportedNpadStyles: 3 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 2 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 2 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + monoEnv: + psp2Splashimage: {fileID: 0} + psp2NPTrophyPackPath: + psp2NPSupportGBMorGJP: 0 + psp2NPAgeRating: 12 + psp2NPTitleDatPath: + psp2NPCommsID: + psp2NPCommunicationsID: + psp2NPCommsPassphrase: + psp2NPCommsSig: + psp2ParamSfxPath: + psp2ManualPath: + psp2LiveAreaGatePath: + psp2LiveAreaBackroundPath: + psp2LiveAreaPath: + psp2LiveAreaTrialPath: + psp2PatchChangeInfoPath: + psp2PatchOriginalPackage: + psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui + psp2KeystoneFile: + psp2MemoryExpansionMode: 0 + psp2DRMType: 0 + psp2StorageType: 0 + psp2MediaCapacity: 0 + psp2DLCConfigPath: + psp2ThumbnailPath: + psp2BackgroundPath: + psp2SoundPath: + psp2TrophyCommId: + psp2TrophyPackagePath: + psp2PackagedResourcesPath: + psp2SaveDataQuota: 10240 + psp2ParentalLevel: 1 + psp2ShortTitle: Not Set + psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF + psp2Category: 0 + psp2MasterVersion: 01.00 + psp2AppVersion: 01.00 + psp2TVBootMode: 0 + psp2EnterButtonAssignment: 2 + psp2TVDisableEmu: 0 + psp2AllowTwitterDialog: 1 + psp2Upgradable: 0 + psp2HealthWarning: 0 + psp2UseLibLocation: 0 + psp2InfoBarOnStartup: 0 + psp2InfoBarColor: 0 + psp2ScriptOptimizationLevel: 2 + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + spritePackerPolicy: + webGLMemorySize: 256 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLLinkerTarget: 1 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + incrementalIl2cppBuild: {} + allowUnsafeCode: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Sandbox + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Sandbox + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + metroCompilationOverrides: 1 + n3dsUseExtSaveData: 0 + n3dsCompressStaticMem: 1 + n3dsExtSaveDataNumber: 0x12345 + n3dsStackSize: 131072 + n3dsTargetPlatform: 2 + n3dsRegion: 7 + n3dsMediaSize: 0 + n3dsLogoStyle: 3 + n3dsTitle: GameName + n3dsProductCode: + n3dsApplicationId: 0xFF3FF + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + xboxOneScriptCompiler: 0 + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: {} + facebookSdkVersion: 7.9.4 + apiCompatibilityLevel: 3 + cloudProjectId: + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 diff --git a/unity/Sandbox/ProjectSettings/ProjectVersion.txt b/unity/Sandbox/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..0498f4d --- /dev/null +++ b/unity/Sandbox/ProjectSettings/ProjectVersion.txt @@ -0,0 +1 @@ +m_EditorVersion: 2018.2.0f2 diff --git a/unity/Sandbox/ProjectSettings/QualitySettings.asset b/unity/Sandbox/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..e3cf353 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/QualitySettings.asset @@ -0,0 +1,224 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSP2: 2 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/unity/Sandbox/ProjectSettings/TagManager.asset b/unity/Sandbox/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/unity/Sandbox/ProjectSettings/TimeManager.asset b/unity/Sandbox/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/unity/Sandbox/ProjectSettings/UnityConnectSettings.asset b/unity/Sandbox/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..3da14d5 --- /dev/null +++ b/unity/Sandbox/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + m_Enabled: 0 + m_TestMode: 0 + m_TestEventUrl: + m_TestConfigUrl: + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes + m_NativeEventUrl: https://perf-events.cloud.unity3d.com/symbolicate + m_Enabled: 0 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_TestEventUrl: + m_TestConfigUrl: + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 From d18f4423c6d5727cf46dc0ed5cf6ecdfe0aad9cd Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 21:35:14 +0300 Subject: [PATCH 38/57] Removed Build.ps1 --- Build.bat | 2 +- Build.ps1 | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 Build.ps1 diff --git a/Build.bat b/Build.bat index 20555ad..2a0d942 100644 --- a/Build.bat +++ b/Build.bat @@ -1 +1 @@ -powershell .\Build.ps1 \ No newline at end of file +powershell .\src\Build.ps1 Release \ No newline at end of file diff --git a/Build.ps1 b/Build.ps1 deleted file mode 100644 index 2b8e6bb..0000000 --- a/Build.ps1 +++ /dev/null @@ -1 +0,0 @@ -.\src\Build.ps1 Release \ No newline at end of file From 840a87ba97fc6b2647611ed12b09a1a62d75b890 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Tue, 25 Sep 2018 21:41:03 +0300 Subject: [PATCH 39/57] Moved Unity dependency DLLs to more suitable location --- .../UnityFx.Async.AssetStore.csproj | 4 ++-- .../Implementation/Public/AsyncResult.Helpers.cs | 2 +- src/UnityFx.Async/UnityFx.Async.csproj | 2 +- {src => unity}/Dependencies/UnityEngine.dll | Bin {src => unity}/Dependencies/UnityEngine.xml | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename {src => unity}/Dependencies/UnityEngine.dll (100%) rename {src => unity}/Dependencies/UnityEngine.xml (100%) diff --git a/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj b/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj index d193d6b..43552dc 100644 --- a/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj +++ b/src/UnityFx.Async.AssetStore/UnityFx.Async.AssetStore.csproj @@ -30,13 +30,13 @@ - ..\Dependencies\UnityEngine.dll + ..\..\unity\Dependencies\UnityEngine.dll - + diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs index 8a3a6fc..a33adc3 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.Helpers.cs @@ -91,7 +91,7 @@ public static AsyncResult CanceledOperation /// Creates an awaitable that asynchronously yields back to the current context when awaited (works the same as ). /// /// - /// A context that, when awaited, will asynchronously transition back into the current context at the + /// A context that, when awaited, will asynchronously transition back into the current context at the /// time of the await. If the current is non-, /// that is treated as the current context. Otherwise, the continuation is executed on the . /// diff --git a/src/UnityFx.Async/UnityFx.Async.csproj b/src/UnityFx.Async/UnityFx.Async.csproj index 7b1f36e..134f79a 100644 --- a/src/UnityFx.Async/UnityFx.Async.csproj +++ b/src/UnityFx.Async/UnityFx.Async.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/Dependencies/UnityEngine.dll b/unity/Dependencies/UnityEngine.dll similarity index 100% rename from src/Dependencies/UnityEngine.dll rename to unity/Dependencies/UnityEngine.dll diff --git a/src/Dependencies/UnityEngine.xml b/unity/Dependencies/UnityEngine.xml similarity index 100% rename from src/Dependencies/UnityEngine.xml rename to unity/Dependencies/UnityEngine.xml From edfad65ce0fd5bf6fd7baf82c699c31bb17acacd Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 12:26:08 +0300 Subject: [PATCH 40/57] Added support for default context via AsyncContinuationOptions --- src/UnityFx.Async/Api/AsyncContinuationOptions.cs | 8 +++++++- .../Private/Continuations/ContinueWithResult{T,U}.cs | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs index 377ef5c..ea78d45 100644 --- a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs +++ b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs @@ -51,6 +51,12 @@ public enum AsyncContinuationOptions /// Specifies that the continuation should be executed synchronously. With this option specified, the continuation runs on /// the same thread that causes the antecedent operation to transition into its final state. /// - ExecuteSynchronously = 8 + ExecuteSynchronously = 8, + + /// + /// Specifies that the continuation should be executed on the default thread. Please see + /// for more information. + /// + ExecuteOnDefaultContext = 16, } } diff --git a/src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs b/src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs index 98f9bd2..5c86ae3 100644 --- a/src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs +++ b/src/UnityFx.Async/Implementation/Private/Continuations/ContinueWithResult{T,U}.cs @@ -32,6 +32,10 @@ internal ContinueWithResult(IAsyncOperation op, AsyncContinuationOptions options { op.AddCompletionCallback(this, null); } + else if ((options & AsyncContinuationOptions.ExecuteOnDefaultContext) != 0) + { + op.AddCompletionCallback(this, DefaultSynchronizationContext); + } else { op.AddCompletionCallback(this); From 3117bf3f39deb585864345ef7b7cc4e7b65cd1cc Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 12:57:37 +0300 Subject: [PATCH 41/57] Removed WWW-related stuff for Unity 2018.3+ (it has been deprecated) --- .../Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs | 8 ++++++-- .../Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs | 4 ++++ .../UnityFx.Async/Scripts/Helpers/WwwResult{T}.cs | 4 ++++ .../Plugins/UnityFx.Async/Scripts/UnityExtensions.cs | 9 ++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 19eea99..2ffac4a 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -285,7 +285,6 @@ public static void StopAllCoroutines() /// The request to register completion callback for. /// A delegate to be called when the has completed. /// Thrown if or is . - /// public static void AddCompletionCallback(AsyncOperation op, Action completionCallback) { if (op == null) @@ -324,7 +323,6 @@ public static void AddCompletionCallback(AsyncOperation op, Action completionCal /// A delegate to be called when the has completed. /// Thrown if or is . /// - /// public static void AddCompletionCallback(UnityWebRequest request, Action completionCallback) { if (request == null) @@ -340,6 +338,8 @@ public static void AddCompletionCallback(UnityWebRequest request, Action complet _rootBehaviour.AddCompletionCallback(request, completionCallback); } +#if !UNITY_2018_3_OR_NEWER + /// /// Register a completion callback for the specified instance. /// @@ -362,6 +362,8 @@ public static void AddCompletionCallback(WWW request, Action completionCallback) _rootBehaviour.AddCompletionCallback(request, completionCallback); } +#endif + /// /// Register a completion callback that is triggered on a specific time during next frame. /// @@ -528,6 +530,7 @@ private void Update() item.Value(); } } +#if !UNITY_2018_3_OR_NEWER else if (item.Key is WWW) { var asyncOp = item.Key as WWW; @@ -538,6 +541,7 @@ private void Update() item.Value(); } } +#endif } } catch (Exception e) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs index 1ec66d4..2705803 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs @@ -272,6 +272,8 @@ public static T GetResult(UnityWebRequest request) where T : class return default(T); } +#if !UNITY_2018_3_OR_NEWER + /// /// Returns result value of the specified instance. /// @@ -312,5 +314,7 @@ public static T GetResult(WWW request) where T : class return null; } + +#endif } } diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WwwResult{T}.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WwwResult{T}.cs index 048b97f..2978c03 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WwwResult{T}.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/Helpers/WwwResult{T}.cs @@ -7,6 +7,8 @@ namespace UnityFx.Async.Helpers { +#if !UNITY_2018_3_OR_NEWER + /// /// A wrapper for with result value. /// @@ -155,4 +157,6 @@ private void SetCompleted() #endregion } + +#endif } diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs index b3bbcff..fcb9693 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs @@ -247,6 +247,8 @@ public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequest op) #region WWW +#if !UNITY_2018_3_OR_NEWER + /// /// Creates an wrapper for the specified . /// @@ -337,6 +339,7 @@ public static WwwAwaiter GetAwaiter(this WWW op) return new WwwAwaiter(op); } +#endif #endif #endregion @@ -433,7 +436,7 @@ public static IAsyncOperation WaitAsync(this Animator anim) #endregion - #region implementation +#region implementation #if NET_4_6 || NET_STANDARD_2_0 @@ -465,6 +468,8 @@ private static void OnTaskCompleted(TaskCompletionSource tcs, UnityWebRequ } } +#if !UNITY_2018_3_OR_NEWER + private static void OnTaskCompleted(TaskCompletionSource tcs, WWW www) where T : class { try @@ -485,6 +490,8 @@ private static void OnTaskCompleted(TaskCompletionSource tcs, WWW www) whe } } +#endif + #endif #endregion From 0050fb0830d6eb4e5654fe83dfe7412805d73272 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 13:00:05 +0300 Subject: [PATCH 42/57] CHANGELOG update --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05e11b3..1c9352a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj - Added `AsyncResult.Yield` static method (workd exactly as `Task.Yield`). - Added `AsyncUtility.AddFrameCallback` helper for scheduling delegates for `MonoBehaviour` update loop. - Added performance benchmarks. +- Added sandbox Unity project. ### Changed - Moved several of `IAsyncOperationEvents` methods to the interface extensions. @@ -24,6 +25,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj ### Removed - Removed Asset Store samples. - Dropped Unity 5.0 support (the minimum version supported is now 5.4). +- Dropped `WWW` support for Unity 2018.3+ (it has been deprecated in Unity). ----------------------- ## [0.9.6] - 2018.08.31 From 86d4aac83d58744e5806f3b18b0b4c72fb793bb1 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 13:12:40 +0300 Subject: [PATCH 43/57] Comment fixes --- .../Public/AsyncCompletionSource.cs | 41 +++++++++++++++--- .../Public/AsyncCompletionSource{TResult}.cs | 42 ++++++++++++++++--- .../Implementation/Public/AsyncLazy.cs | 11 ----- .../Implementation/Public/AsyncResult.cs | 12 +++--- 4 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs index 0e142c0..511bb7e 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource.cs @@ -207,10 +207,19 @@ protected override void OnCancel() #region IAsyncCompletionSource - /// + /// + /// Gets the operation being controller by the source. + /// + /// The underlying operation instance. public IAsyncOperation Operation => this; - /// + /// + /// Attempts to set the operation progress value in range [0, 1]. + /// + /// The operation progress in range [0, 1]. + /// Thrown if is not in range [0, 1]. + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public bool TrySetProgress(float progress) { if (progress < 0 || progress > 1) @@ -230,16 +239,36 @@ public bool TrySetProgress(float progress) return false; } - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetCanceled() => TrySetCanceled(false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetCompleted() => TrySetCompleted(false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// An exception that caused the operation to end prematurely. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetException(Exception exception) => TrySetException(exception, false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// Exceptions that caused the operation to end prematurely. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetExceptions(IEnumerable exceptions) => TrySetExceptions(exceptions, false); #endregion diff --git a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs index 0398621..2df428f 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncCompletionSource{TResult}.cs @@ -208,10 +208,19 @@ protected override void OnCancel() #region IAsyncCompletionSource - /// + /// + /// Gets the operation being controller by the source. + /// + /// The underlying operation instance. public IAsyncOperation Operation => this; - /// + /// + /// Attempts to set the operation progress value in range [0, 1]. + /// + /// The operation progress in range [0, 1]. + /// Thrown if is not in range [0, 1]. + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public bool TrySetProgress(float progress) { if (progress < 0 || progress > 1) @@ -231,16 +240,37 @@ public bool TrySetProgress(float progress) return false; } - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetCanceled() => TrySetCanceled(false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// An exception that caused the operation to end prematurely. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetException(Exception exception) => TrySetException(exception, false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// An exception that caused the operation to end prematurely. + /// Thrown if is . + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetExceptions(IEnumerable exceptions) => TrySetExceptions(exceptions, false); - /// + /// + /// Attempts to transition the underlying into the state. + /// + /// The operation result. + /// Thrown is the operation is disposed. + /// Returns if the attemp was successfull; otherwise. public new bool TrySetResult(TResult result) => TrySetResult(result, false); #endregion diff --git a/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs b/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs index 5f1ec8b..745b1f5 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs @@ -98,17 +98,6 @@ public IAsyncOperation StartOrUpdate() return _op; } - /// - /// Schedules a continuation to run after the lazy operation succeeds. - /// - /// A continuation to schedule after this operation completes. - /// Thrown if value is . - /// Thrown if is . - public void Schedule(IAsyncContinuation continuation) - { - StartOrUpdate().AddCompletionCallback(continuation); - } - /// /// Resets state of the instance to default. /// diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index 45e6ebe..7d92dcd 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -20,13 +20,13 @@ namespace UnityFx.Async /// /// This class is the core entity of the library. In many aspects it mimics Task /// interface and behaviour. For example, any instance can have any - /// number of continuations (added either explicitly via TryAddCompletionCallback + /// number of continuations (added either explicitly via AddCompletionCallback /// call or implicitly using async/await keywords). These continuations can be - /// invoked on a captured . The class inherits - /// and can be used to implement Asynchronous Programming Model (APM). There are operation - /// state accessors that can be used exactly like corresponding properties of Task. - /// While the class implements disposing is only required - /// if property was used. + /// invoked on a an arbitrary . The class can be used to + /// implement Asynchronous Programming Model (APM). There are operation state accessors that + /// can be used exactly like corresponding properties of Task. While the class implements + /// disposing is only required if property + /// was used. /// /// Promises for game development /// How to implement the IAsyncResult design pattern From 50dc67647d3b65133081487cf5945208179a7991 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 13:54:37 +0300 Subject: [PATCH 44/57] Fixed invalid AppVeyor build script reference --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index d7182d8..1b90810 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,7 +16,7 @@ install: - cmd: git submodule -q update --init build_script: - - ps: .\build.ps1 + - ps: .\src\build.ps1 Release artifacts: - path: .\bin\net35 From d81bd62599db2200cfd744d1e26ec90c1b3646d7 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 14:36:25 +0300 Subject: [PATCH 45/57] Added strong name to UnityFx.Async --- src/UnityFx.Async/UnityFx.Async.csproj | 2 ++ src/UnityFx.Async/UnityFx.Async.snk | Bin 0 -> 596 bytes 2 files changed, 2 insertions(+) create mode 100644 src/UnityFx.Async/UnityFx.Async.snk diff --git a/src/UnityFx.Async/UnityFx.Async.csproj b/src/UnityFx.Async/UnityFx.Async.csproj index 134f79a..28f6878 100644 --- a/src/UnityFx.Async/UnityFx.Async.csproj +++ b/src/UnityFx.Async/UnityFx.Async.csproj @@ -21,6 +21,8 @@ en-US UnityFx.Async ../CodingConventions/Cs/CsharpRules.ruleset + true + UnityFx.Async.snk diff --git a/src/UnityFx.Async/UnityFx.Async.snk b/src/UnityFx.Async/UnityFx.Async.snk new file mode 100644 index 0000000000000000000000000000000000000000..c83c91ddd187eaf04bceb55e2267dbda77d3cac3 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098|389r@gEsGTKj#`5pVkYAfE+~qci`5m z;lq)+Pp>GEu_X9p;FZ^@Wry`(u>nVjIUZX|RRJU4DBCt@dxTY!?l-aEihz)oWSWHiZr;KdHd&k!lj$_4~YxJA34 zh+zgpd|C*jnS|Xt_5a=y{UUoP6p++5-r{M*kJ zbZTCq8HO}iFW6RovHpoYhk6!5Xcox&^ge|#gmmiw5g#d^T+Ek^&+zEEPo3QvGQmzO zeQ@VkyTDGR!)FPE^Q(#}HgQV0UGIGOdYjYRG({EnkZ)KJBO?Y818#fXQQunN6^^rP zRRZJNv^ Date: Wed, 26 Sep 2018 14:37:14 +0300 Subject: [PATCH 46/57] CHANGELOG update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c9352a..2199aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj - Added `SynchronizationContext` extension methods for `Send`/`Post` accepting `Action` as the delegate. - Added `AsyncResult.Yield` static method (workd exactly as `Task.Yield`). - Added `AsyncUtility.AddFrameCallback` helper for scheduling delegates for `MonoBehaviour` update loop. +- Signed the assembly with a strong name. - Added performance benchmarks. - Added sandbox Unity project. From 9bf754aee41000dadd73b39aeb464e9e52e102ce Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 15:06:30 +0300 Subject: [PATCH 47/57] README update --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1cd7717..020c8cd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Channel | UnityFx.Async | AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/hfmq9vow53al7tpd/branch/master?svg=true)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/branch/master) [![AppVeyor tests](https://img.shields.io/appveyor/tests/Arvtesh/unityFx-async.svg)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/build/tests) NuGet | [![NuGet](https://img.shields.io/nuget/v/UnityFx.Async.svg)](https://www.nuget.org/packages/UnityFx.Async) Github | [![GitHub release](https://img.shields.io/github/release/Arvtesh/UnityFx.Async.svg?logo=github)](https://github.com/Arvtesh/UnityFx.Async/releases) -Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.5-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) +Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.7-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) **Required Unity 5.4 or higher.** @@ -54,6 +54,9 @@ git submodule -q update --init ### Getting binaries The binaries are available as a [NuGet package](https://www.nuget.org/packages/UnityFx.Async). See [here](http://docs.nuget.org/docs/start-here/using-the-package-manager-console) for instructions on installing a package via nuget. One can also download them directly from [Github releases](https://github.com/Arvtesh/UnityFx.Async/releases). Unity3d users can import corresponding [Unity Asset Store package](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) using the editor. +### Unity dependencies +The library core (`UnityFx.Async.dll`) does not depend on Unity and can be used in any .NET projects (via assembly or [NuGet](https://www.nuget.org/packages/UnityFx.Async) reference). All Unity-specific stuff depends on the core and is included in [Unity Asset Store package](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696). + ## Understanding the concepts The topics below are just a quick summary of problems and the proposed solutions. For more details on the topic please see useful links at the end of this document. ### Callback hell From 11aecddc40cca7ef56daba939bccae0295be9578 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 15:22:28 +0300 Subject: [PATCH 48/57] Updated NuGet copyright string --- src/UnityFx.Async/UnityFx.Async.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UnityFx.Async/UnityFx.Async.csproj b/src/UnityFx.Async/UnityFx.Async.csproj index 28f6878..b5597ec 100644 --- a/src/UnityFx.Async/UnityFx.Async.csproj +++ b/src/UnityFx.Async/UnityFx.Async.csproj @@ -5,13 +5,13 @@ Task-like asynchronous operations (promises) for Unity3d. Alexander Bogarsukov - Alexander Bogarsukov + Copyright © 2017-2018 Alexander Bogarsukov https://github.com/Arvtesh/UnityFx.Async Git 0.0.1-alpha0001 https://github.com/Arvtesh/UnityFx.Async https://github.com/Arvtesh/UnityFx.Async/blob/master/LICENSE.md - UnityFx;Async;AsyncOperation;Coroutine;Task;Unity3d + UnityFx;Async;Promise;AsyncOperation;Coroutine;Task;Unity3d 0.7.0 0.7.0.0 From 35163450d031de3361d3d15b77d35c97c2f5aef8 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 17:26:53 +0300 Subject: [PATCH 49/57] Moved awaiters implementation to CompilerServices namespace --- .../Implementation/Public/AsyncResult.cs | 23 +++ .../Public/CompilerServices/AsyncAwaitable.cs | 34 ++++ .../AsyncAwaitable{TResult}.cs | 34 ++++ .../Public/CompilerServices/AsyncAwaiter.cs | 69 +++++++ .../CompilerServices/AsyncAwaiter{TResult}.cs | 58 ++++++ .../Extensions/AsyncExtensions.Tasks.cs | 170 ++---------------- .../Public/Extensions/AsyncExtensions.cs | 28 +-- 7 files changed, 234 insertions(+), 182 deletions(-) create mode 100644 src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs create mode 100644 src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs create mode 100644 src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs create mode 100644 src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index 7d92dcd..1a2bba3 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -1010,6 +1010,29 @@ internal static bool TryThrowException(Exception e) return false; } + /// + /// Returns a for the given options. + /// + internal static SynchronizationContext GetContext(AsyncCallbackOptions options) + { + SynchronizationContext syncContext; + + if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) + { + syncContext = SynchronizationContext.Current; + } + else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) + { + syncContext = _defaultContext; + } + else + { + syncContext = null; + } + + return syncContext; + } + #endregion #region IAsyncOperation diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs new file mode 100644 index 0000000..3a2fe3f --- /dev/null +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs @@ -0,0 +1,34 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.CompilerServices +{ +#if !NET35 + + /// + /// Provides an awaitable object that allows for configured awaits on . + /// This type is intended for compiler use only. + /// + /// + public struct AsyncAwaitable + { + private readonly AsyncAwaiter _awaiter; + + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) + { + _awaiter = new AsyncAwaiter(op, options); + } + + /// + /// Returns the awaiter. + /// + public AsyncAwaiter GetAwaiter() => _awaiter; + } + +#endif +} diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs new file mode 100644 index 0000000..43ca2a6 --- /dev/null +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs @@ -0,0 +1,34 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace UnityFx.Async.CompilerServices +{ +#if !NET35 + + /// + /// Provides an awaitable object that allows for configured awaits on . + /// This type is intended for compiler use only. + /// + /// + public struct AsyncAwaitable + { + private readonly AsyncAwaiter _awaiter; + + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) + { + _awaiter = new AsyncAwaiter(op, options); + } + + /// + /// Returns the awaiter. + /// + public AsyncAwaiter GetAwaiter() => _awaiter; + } + +#endif +} diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs new file mode 100644 index 0000000..00f5ca3 --- /dev/null +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs @@ -0,0 +1,69 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace UnityFx.Async.CompilerServices +{ +#if !NET35 + + /// + /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. + /// + /// + public struct AsyncAwaiter : INotifyCompletion + { + private readonly IAsyncOperation _op; + private readonly AsyncCallbackOptions _options; + + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) + { + _op = op; + _options = options; + } + + /// + /// Gets a value indicating whether the underlying operation is completed. + /// + /// The operation completion flag. + public bool IsCompleted => _op.IsCompleted; + + /// + /// Returns the source result value. + /// + public void GetResult() + { + if (!_op.IsCompletedSuccessfully) + { + _op.ThrowIfNonSuccess(); + } + } + + /// + public void OnCompleted(Action continuation) + { + SetAwaitContinuation(_op, continuation, _options); + } + + internal static void SetAwaitContinuation(IAsyncOperation op, Action continuation, AsyncCallbackOptions options) + { + var syncContext = AsyncResult.GetContext(options); + + if (op is AsyncResult ar) + { + ar.SetContinuationForAwait(continuation, syncContext); + } + else + { + op.AddCompletionCallback(asyncOp => continuation(), syncContext); + } + } + } + +#endif +} diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs new file mode 100644 index 0000000..14dc2e7 --- /dev/null +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs @@ -0,0 +1,58 @@ +// Copyright (c) Alexander Bogarsukov. +// Licensed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace UnityFx.Async.CompilerServices +{ +#if !NET35 + + /// + /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. + /// + /// + public struct AsyncAwaiter : INotifyCompletion + { + private readonly IAsyncOperation _op; + private readonly AsyncCallbackOptions _options; + + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) + { + _op = op; + _options = options; + } + + /// + /// Gets a value indicating whether the underlying operation is completed. + /// + /// The operation completion flag. + public bool IsCompleted => _op.IsCompleted; + + /// + /// Returns the source result value. + /// + /// Returns the underlying operation result. + public TResult GetResult() + { + if (!_op.IsCompletedSuccessfully) + { + _op.ThrowIfNonSuccess(); + } + + return _op.Result; + } + + /// + public void OnCompleted(Action continuation) + { + AsyncAwaiter.SetAwaitContinuation(_op, continuation, _options); + } + } + +#endif +} diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs index 3afe8a1..106a2f5 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs @@ -16,145 +16,14 @@ partial class AsyncExtensions { #region GetAwaiter/ConfigureAwait - /// - /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. - /// - /// - public struct AsyncAwaiter : INotifyCompletion - { - private readonly IAsyncOperation _op; - private readonly AsyncCallbackOptions _options; - - /// - /// Initializes a new instance of the struct. - /// - public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) - { - _op = op; - _options = options; - } - - /// - /// Gets a value indicating whether the underlying operation is completed. - /// - /// The operation completion flag. - public bool IsCompleted => _op.IsCompleted; - - /// - /// Returns the source result value. - /// - public void GetResult() - { - if (!_op.IsCompletedSuccessfully) - { - ThrowIfNonSuccess(_op); - } - } - - /// - public void OnCompleted(Action continuation) - { - SetAwaitContinuation(_op, continuation, _options); - } - } - - /// - /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. - /// - /// - public struct AsyncAwaiter : INotifyCompletion - { - private readonly IAsyncOperation _op; - private readonly AsyncCallbackOptions _options; - - /// - /// Initializes a new instance of the struct. - /// - public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) - { - _op = op; - _options = options; - } - - /// - /// Gets a value indicating whether the underlying operation is completed. - /// - /// The operation completion flag. - public bool IsCompleted => _op.IsCompleted; - - /// - /// Returns the source result value. - /// - /// Returns the underlying operation result. - public T GetResult() - { - if (!_op.IsCompletedSuccessfully) - { - ThrowIfNonSuccess(_op); - } - - return _op.Result; - } - - /// - public void OnCompleted(Action continuation) - { - SetAwaitContinuation(_op, continuation, _options); - } - } - - /// - /// Provides an awaitable object that allows for configured awaits on . This type is intended for compiler use only. - /// - /// - public struct ConfiguredAsyncAwaitable - { - private readonly AsyncAwaiter _awaiter; - - /// - /// Initializes a new instance of the struct. - /// - public ConfiguredAsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) - { - _awaiter = new AsyncAwaiter(op, options); - } - - /// - /// Returns the awaiter. - /// - public AsyncAwaiter GetAwaiter() => _awaiter; - } - - /// - /// Provides an awaitable object that allows for configured awaits on . This type is intended for compiler use only. - /// - /// - public struct ConfiguredAsyncAwaitable - { - private readonly AsyncAwaiter _awaiter; - - /// - /// Initializes a new instance of the struct. - /// - public ConfiguredAsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) - { - _awaiter = new AsyncAwaiter(op, options); - } - - /// - /// Returns the awaiter. - /// - public AsyncAwaiter GetAwaiter() => _awaiter; - } - /// /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. /// /// The operation to await. /// - public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) + public static CompilerServices.AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); + return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); } /// @@ -162,9 +31,9 @@ public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) /// /// The operation to await. /// - public static AsyncAwaiter GetAwaiter(this IAsyncOperation op) + public static CompilerServices.AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); + return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); } /// @@ -173,9 +42,9 @@ public static AsyncAwaiter GetAwaiter(this IAsyncOperationThe operation to await. /// If attempts to marshal the continuation back to the original context captured. /// An object used to await the operation. - public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); + return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); } /// @@ -184,9 +53,9 @@ public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, b /// The operation to await. /// If attempts to marshal the continuation back to the original context captured. /// An object used to await the operation. - public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new ConfiguredAsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); + return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); } /// @@ -195,9 +64,9 @@ public static ConfiguredAsyncAwaitable ConfigureAwait(this IAs /// The operation to await. /// Specifies continuation options. /// An object used to await the operation. - public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) { - return new ConfiguredAsyncAwaitable(op, continuationOptions); + return new CompilerServices.AsyncAwaitable(op, continuationOptions); } /// @@ -206,9 +75,9 @@ public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, A /// The operation to await. /// Specifies continuation options. /// An object used to await the operation. - public static ConfiguredAsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) { - return new ConfiguredAsyncAwaitable(op, continuationOptions); + return new CompilerServices.AsyncAwaitable(op, continuationOptions); } #endregion @@ -340,21 +209,6 @@ public static AsyncResult ToAsync(this Task task) #endregion #region implementation - - private static void SetAwaitContinuation(IAsyncOperation op, Action continuation, AsyncCallbackOptions options) - { - var syncContext = GetContext(options); - - if (op is AsyncResult ar) - { - ar.SetContinuationForAwait(continuation, syncContext); - } - else - { - op.AddCompletionCallback(asyncOp => continuation(), syncContext); - } - } - #endregion } diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs index 6911ad3..3e7b789 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs @@ -373,7 +373,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, ActionThrown is the operation has been disposed. public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) { - op.AddCompletionCallback(callback, GetContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetContext(options)); } /// @@ -408,7 +408,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncCo /// Thrown is the operation has been disposed. public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback, AsyncCallbackOptions options) { - op.AddCompletionCallback(callback, GetContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetContext(options)); } /// @@ -443,7 +443,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, ActionThrown is the operation has been disposed. public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) { - op.AddProgressCallback(callback, GetContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetContext(options)); } #if !NET35 @@ -480,7 +480,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress< /// Thrown is the operation has been disposed. public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback, AsyncCallbackOptions options) { - op.AddProgressCallback(callback, GetContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetContext(options)); } #endif @@ -810,26 +810,6 @@ private static bool SpinUntilCompletedInternal(IAsyncResult op, TimeSpan timeout return true; } - private static SynchronizationContext GetContext(AsyncCallbackOptions options) - { - SynchronizationContext syncContext; - - if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) - { - syncContext = SynchronizationContext.Current; - } - else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) - { - syncContext = AsyncResult.DefaultSynchronizationContext; - } - else - { - syncContext = null; - } - - return syncContext; - } - private static void ActionCallback(object args) { ((Action)args).Invoke(); From c917953b7f1bb86b809f010386bbbfce6d7c1c98 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 17:28:37 +0300 Subject: [PATCH 50/57] AsyncLazy changes --- .../Implementation/Public/AsyncLazy.cs | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs b/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs index 745b1f5..0272cb7 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs @@ -48,27 +48,6 @@ public struct AsyncLazy /// public bool IsCanceled => _op?.IsCanceled ?? false; - /// - /// Gets the operation (might return ). - /// - public IAsyncOperation Operation => _op; - - /// - /// Gets or sets the operation factory delegate. - /// - /// Thrown if argument value is . - public Func OperationFactory - { - get - { - return _opFactory; - } - set - { - _opFactory = value ?? throw new ArgumentNullException(nameof(value)); - } - } - /// /// Initializes a new instance of the struct. /// @@ -83,7 +62,7 @@ public AsyncLazy(Func opFactory) /// /// Starts the operation or just updates its state. /// - /// Thrown if is . + /// Thrown if operation factory is . public IAsyncOperation StartOrUpdate() { if (_op != null) @@ -106,14 +85,19 @@ public void Reset() _op = null; } +#if !NET35 + /// - /// Implicit conversion to . + /// Returns the operation awaiter. This method is intended for compiler use only. /// - public static implicit operator bool(AsyncLazy status) + public CompilerServices.AsyncAwaiter GetAwaiter() { - return status.IsCompletedSuccessfully; + var op = StartOrUpdate(); + return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); } +#endif + #endregion #region implementation From b9c7d9a7e8e52ba51c9beafe0f0d515e381352ff Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Wed, 26 Sep 2018 17:30:01 +0300 Subject: [PATCH 51/57] CHANGELOG update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2199aab..31cafd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/); this proj ### Changed - Moved several of `IAsyncOperationEvents` methods to the interface extensions. +- Simplified `AsyncLazy` interface. ### Fixed - Fixed error handling in `AsyncOperationResult`. From 668ee7439f282de822801ad0a7cfdf5c639df1ee Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 16:24:33 +0300 Subject: [PATCH 52/57] Changed project structure --- .../Implementation/Public/{ => Helpers}/AsyncLazy.cs | 0 .../Implementation/Public/{ => Helpers}/AsyncResultQueue{T}.cs | 0 .../Implementation/Public/{ => Helpers}/AsyncUpdateSource.cs | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/UnityFx.Async/Implementation/Public/{ => Helpers}/AsyncLazy.cs (100%) rename src/UnityFx.Async/Implementation/Public/{ => Helpers}/AsyncResultQueue{T}.cs (100%) rename src/UnityFx.Async/Implementation/Public/{ => Helpers}/AsyncUpdateSource.cs (100%) diff --git a/src/UnityFx.Async/Implementation/Public/AsyncLazy.cs b/src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Public/AsyncLazy.cs rename to src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs b/src/UnityFx.Async/Implementation/Public/Helpers/AsyncResultQueue{T}.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Public/AsyncResultQueue{T}.cs rename to src/UnityFx.Async/Implementation/Public/Helpers/AsyncResultQueue{T}.cs diff --git a/src/UnityFx.Async/Implementation/Public/AsyncUpdateSource.cs b/src/UnityFx.Async/Implementation/Public/Helpers/AsyncUpdateSource.cs similarity index 100% rename from src/UnityFx.Async/Implementation/Public/AsyncUpdateSource.cs rename to src/UnityFx.Async/Implementation/Public/Helpers/AsyncUpdateSource.cs From 7d4b22129b957572b0810eb8987da4726a196f1b Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 17:38:11 +0300 Subject: [PATCH 53/57] Minor code refactoring --- .../UnityFx.Async/Scripts/UnityExtensions.cs | 6 +- .../Implementation/Public/AsyncResult.cs | 6 +- .../Public/CompilerServices/AsyncAwaitable.cs | 5 +- .../AsyncAwaitable{TResult}.cs | 5 +- .../Public/CompilerServices/AsyncAwaiter.cs | 21 +++-- .../CompilerServices/AsyncAwaiter{TResult}.cs | 79 +++++++++++-------- .../Extensions/AsyncExtensions.Tasks.cs | 28 +++---- .../Public/Extensions/AsyncExtensions.cs | 8 +- .../Public/Helpers/AsyncLazy.cs | 2 +- 9 files changed, 89 insertions(+), 71 deletions(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs index fcb9693..0990e47 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/UnityExtensions.cs @@ -137,7 +137,7 @@ public void OnCompleted(Action continuation) } /// - /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. + /// Returns the operation awaiter. This method is intended for compiler use only. /// /// The operation to await. public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation op) @@ -233,7 +233,7 @@ public void OnCompleted(Action continuation) } /// - /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. + /// Returns the operation awaiter. This method is intended for compiler use only. /// /// The operation to await. public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequest op) @@ -331,7 +331,7 @@ public void OnCompleted(Action continuation) } /// - /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. + /// Returns the operation awaiter. This method is intended for compiler use only. /// /// The operation to await. public static WwwAwaiter GetAwaiter(this WWW op) diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index 1a2bba3..2eff072 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -78,8 +78,8 @@ public partial class AsyncResult : IAsyncOperation, IAsyncContinuation, IEnumera /// /// /// This property is supposed to be used as allocation optimization in applications working mostly with single - /// instance (single thread) such as Unity3d applications. It should be - /// set to main thread context is most cases. + /// instance (such as Unity3d applications). Usually this should be set to + /// a context attached to the app UI thread. /// /// An instance of that is used as default one. Initial value is . public static SynchronizationContext DefaultSynchronizationContext { get => _defaultContext; set => _defaultContext = value; } @@ -1013,7 +1013,7 @@ internal static bool TryThrowException(Exception e) /// /// Returns a for the given options. /// - internal static SynchronizationContext GetContext(AsyncCallbackOptions options) + internal static SynchronizationContext GetSynchronizationContext(AsyncCallbackOptions options) { SynchronizationContext syncContext; diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs index 3a2fe3f..e663a21 100644 --- a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; +using System.Threading; namespace UnityFx.Async.CompilerServices { @@ -19,9 +20,9 @@ public struct AsyncAwaitable /// /// Initializes a new instance of the struct. /// - public AsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) + public AsyncAwaitable(IAsyncOperation op, SynchronizationContext syncContext) { - _awaiter = new AsyncAwaiter(op, options); + _awaiter = new AsyncAwaiter(op, syncContext); } /// diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs index 43ca2a6..101bc98 100644 --- a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaitable{TResult}.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See the LICENSE.md file in the project root for more information. using System; +using System.Threading; namespace UnityFx.Async.CompilerServices { @@ -19,9 +20,9 @@ public struct AsyncAwaitable /// /// Initializes a new instance of the struct. /// - public AsyncAwaitable(IAsyncOperation op, AsyncCallbackOptions options) + public AsyncAwaitable(IAsyncOperation op, SynchronizationContext syncContext) { - _awaiter = new AsyncAwaiter(op, options); + _awaiter = new AsyncAwaiter(op, syncContext); } /// diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs index 00f5ca3..6fed48f 100644 --- a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter.cs @@ -16,15 +16,24 @@ namespace UnityFx.Async.CompilerServices public struct AsyncAwaiter : INotifyCompletion { private readonly IAsyncOperation _op; - private readonly AsyncCallbackOptions _options; + private readonly SynchronizationContext _syncContext; /// /// Initializes a new instance of the struct. /// - public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) + public AsyncAwaiter(IAsyncOperation op) { _op = op; - _options = options; + _syncContext = SynchronizationContext.Current; + } + + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaiter(IAsyncOperation op, SynchronizationContext syncContext) + { + _op = op; + _syncContext = syncContext; } /// @@ -47,13 +56,11 @@ public void GetResult() /// public void OnCompleted(Action continuation) { - SetAwaitContinuation(_op, continuation, _options); + SetAwaitContinuation(_op, continuation, _syncContext); } - internal static void SetAwaitContinuation(IAsyncOperation op, Action continuation, AsyncCallbackOptions options) + internal static void SetAwaitContinuation(IAsyncOperation op, Action continuation, SynchronizationContext syncContext) { - var syncContext = AsyncResult.GetContext(options); - if (op is AsyncResult ar) { ar.SetContinuationForAwait(continuation, syncContext); diff --git a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs index 14dc2e7..40986fe 100644 --- a/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs +++ b/src/UnityFx.Async/Implementation/Public/CompilerServices/AsyncAwaiter{TResult}.cs @@ -10,49 +10,58 @@ namespace UnityFx.Async.CompilerServices #if !NET35 /// - /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. + /// Provides an object that waits for the completion of an asynchronous operation. This type and its members are intended for compiler use only. + /// + /// + public struct AsyncAwaiter : INotifyCompletion + { + private readonly IAsyncOperation _op; + private readonly SynchronizationContext _syncContext; + + /// + /// Initializes a new instance of the struct. /// - /// - public struct AsyncAwaiter : INotifyCompletion + public AsyncAwaiter(IAsyncOperation op) { - private readonly IAsyncOperation _op; - private readonly AsyncCallbackOptions _options; - - /// - /// Initializes a new instance of the struct. - /// - public AsyncAwaiter(IAsyncOperation op, AsyncCallbackOptions options) - { - _op = op; - _options = options; - } + _op = op; + _syncContext = SynchronizationContext.Current; + } - /// - /// Gets a value indicating whether the underlying operation is completed. - /// - /// The operation completion flag. - public bool IsCompleted => _op.IsCompleted; - - /// - /// Returns the source result value. - /// - /// Returns the underlying operation result. - public TResult GetResult() - { - if (!_op.IsCompletedSuccessfully) - { - _op.ThrowIfNonSuccess(); - } + /// + /// Initializes a new instance of the struct. + /// + public AsyncAwaiter(IAsyncOperation op, SynchronizationContext syncContext) + { + _op = op; + _syncContext = syncContext; + } - return _op.Result; - } + /// + /// Gets a value indicating whether the underlying operation is completed. + /// + /// The operation completion flag. + public bool IsCompleted => _op.IsCompleted; - /// - public void OnCompleted(Action continuation) + /// + /// Returns the source result value. + /// + /// Returns the underlying operation result. + public TResult GetResult() + { + if (!_op.IsCompletedSuccessfully) { - AsyncAwaiter.SetAwaitContinuation(_op, continuation, _options); + _op.ThrowIfNonSuccess(); } + + return _op.Result; + } + + /// + public void OnCompleted(Action continuation) + { + AsyncAwaiter.SetAwaitContinuation(_op, continuation, _syncContext); } + } #endif } diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs index 106a2f5..d95ebb6 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs @@ -17,23 +17,23 @@ partial class AsyncExtensions #region GetAwaiter/ConfigureAwait /// - /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. + /// Returns the operation awaiter. This method is intended for compiler use only. /// /// The operation to await. - /// + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); + return new CompilerServices.AsyncAwaiter(op); } /// - /// Returns the operation awaiter. This method is intended for compiler rather than use directly in code. + /// Returns the operation awaiter. This method is intended for compiler use only. /// /// The operation to await. - /// + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaiter GetAwaiter(this IAsyncOperation op) { - return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); + return new CompilerServices.AsyncAwaiter(op); } /// @@ -41,10 +41,10 @@ public static CompilerServices.AsyncAwaiter GetAwaiter(this IA /// /// The operation to await. /// If attempts to marshal the continuation back to the original context captured. - /// An object used to await the operation. + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); + return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? SynchronizationContext.Current : null); } /// @@ -52,10 +52,10 @@ public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperatio /// /// The operation to await. /// If attempts to marshal the continuation back to the original context captured. - /// An object used to await the operation. + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, bool continueOnCapturedContext) { - return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? AsyncCallbackOptions.ExecuteOnCapturedContext : AsyncCallbackOptions.ExecuteSynchronously); + return new CompilerServices.AsyncAwaitable(op, continueOnCapturedContext ? SynchronizationContext.Current : null); } /// @@ -63,10 +63,10 @@ public static CompilerServices.AsyncAwaitable ConfigureAwait(t /// /// The operation to await. /// Specifies continuation options. - /// An object used to await the operation. + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) { - return new CompilerServices.AsyncAwaitable(op, continuationOptions); + return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationOptions)); } /// @@ -74,10 +74,10 @@ public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperatio /// /// The operation to await. /// Specifies continuation options. - /// An object used to await the operation. + /// An object that can be used to await the operation. public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) { - return new CompilerServices.AsyncAwaitable(op, continuationOptions); + return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationOptions)); } #endregion diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs index 3e7b789..5c7eaf8 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs @@ -373,7 +373,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, ActionThrown is the operation has been disposed. public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) { - op.AddCompletionCallback(callback, AsyncResult.GetContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(options)); } /// @@ -408,7 +408,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncCo /// Thrown is the operation has been disposed. public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback, AsyncCallbackOptions options) { - op.AddCompletionCallback(callback, AsyncResult.GetContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(options)); } /// @@ -443,7 +443,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, ActionThrown is the operation has been disposed. public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) { - op.AddProgressCallback(callback, AsyncResult.GetContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(options)); } #if !NET35 @@ -480,7 +480,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress< /// Thrown is the operation has been disposed. public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback, AsyncCallbackOptions options) { - op.AddProgressCallback(callback, AsyncResult.GetContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(options)); } #endif diff --git a/src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs b/src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs index 0272cb7..91ceef2 100644 --- a/src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs +++ b/src/UnityFx.Async/Implementation/Public/Helpers/AsyncLazy.cs @@ -93,7 +93,7 @@ public void Reset() public CompilerServices.AsyncAwaiter GetAwaiter() { var op = StartOrUpdate(); - return new CompilerServices.AsyncAwaiter(op, AsyncCallbackOptions.ExecuteOnCapturedContext); + return new CompilerServices.AsyncAwaiter(op); } #endif From 20632f35543007978a18724e11e61566c7f38872 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 21:12:39 +0300 Subject: [PATCH 54/57] Several renames --- ...Options.cs => AsyncContinuationContext.cs} | 25 ++++++++------- .../Api/AsyncContinuationOptions.cs | 1 + .../Implementation/Public/AsyncResult.cs | 6 ++-- .../Extensions/AsyncExtensions.Tasks.cs | 12 +++---- .../Public/Extensions/AsyncExtensions.cs | 32 +++++++++---------- 5 files changed, 39 insertions(+), 37 deletions(-) rename src/UnityFx.Async/Api/{AsyncCallbackOptions.cs => AsyncContinuationContext.cs} (74%) diff --git a/src/UnityFx.Async/Api/AsyncCallbackOptions.cs b/src/UnityFx.Async/Api/AsyncContinuationContext.cs similarity index 74% rename from src/UnityFx.Async/Api/AsyncCallbackOptions.cs rename to src/UnityFx.Async/Api/AsyncContinuationContext.cs index b3ed381..fbf841a 100644 --- a/src/UnityFx.Async/Api/AsyncCallbackOptions.cs +++ b/src/UnityFx.Async/Api/AsyncContinuationContext.cs @@ -6,27 +6,28 @@ namespace UnityFx.Async { /// - /// Specifies the behavior for an operation callbacks. + /// Specifies the synchronization context to schedule continuation on. /// - public enum AsyncCallbackOptions + /// + public enum AsyncContinuationContext { /// - /// Specifies that the continuation should be executed on the same thread that scheduled it. - /// That is the default behaviour. + /// Specifies that the continuation should be executed synchronously. With this option specified, + /// the continuation runs on the same thread that causes the antecedent operation to transition + /// into its final state. /// - ExecuteOnCapturedContext, + None, /// - /// Specifies that the continuation should be executed on the default thread. Please see - /// for more information. + /// Specifies that the continuation should be executed on the same thread that scheduled it. + /// That is the default behaviour of all library continuations. /// - ExecuteOnDefaultContext, + Current, /// - /// Specifies that the continuation should be executed synchronously. With this option specified, - /// the continuation runs on the same thread that causes the antecedent operation to transition - /// into its final state. + /// Specifies that the continuation should be executed on the default thread. See + /// for more information. /// - ExecuteSynchronously + Default } } diff --git a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs index ea78d45..77fa9bd 100644 --- a/src/UnityFx.Async/Api/AsyncContinuationOptions.cs +++ b/src/UnityFx.Async/Api/AsyncContinuationOptions.cs @@ -8,6 +8,7 @@ namespace UnityFx.Async /// /// Specifies the behavior of an asynchronous operation continuation. /// + /// [Flags] public enum AsyncContinuationOptions { diff --git a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs index 2eff072..a3926ad 100644 --- a/src/UnityFx.Async/Implementation/Public/AsyncResult.cs +++ b/src/UnityFx.Async/Implementation/Public/AsyncResult.cs @@ -1013,15 +1013,15 @@ internal static bool TryThrowException(Exception e) /// /// Returns a for the given options. /// - internal static SynchronizationContext GetSynchronizationContext(AsyncCallbackOptions options) + internal static SynchronizationContext GetSynchronizationContext(AsyncContinuationContext contextId) { SynchronizationContext syncContext; - if (options == AsyncCallbackOptions.ExecuteOnCapturedContext) + if (contextId == AsyncContinuationContext.Current) { syncContext = SynchronizationContext.Current; } - else if (options == AsyncCallbackOptions.ExecuteOnDefaultContext) + else if (contextId == AsyncContinuationContext.Default) { syncContext = _defaultContext; } diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs index d95ebb6..a270eb9 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.Tasks.cs @@ -62,22 +62,22 @@ public static CompilerServices.AsyncAwaitable ConfigureAwait(t /// Configures an awaiter used to await this operation. /// /// The operation to await. - /// Specifies continuation options. + /// Specifies continuation options. /// An object that can be used to await the operation. - public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncContinuationContext continuationContext) { - return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationOptions)); + return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationContext)); } /// /// Configures an awaiter used to await this operation. /// /// The operation to await. - /// Specifies continuation options. + /// Specifies continuation options. /// An object that can be used to await the operation. - public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncCallbackOptions continuationOptions) + public static CompilerServices.AsyncAwaitable ConfigureAwait(this IAsyncOperation op, AsyncContinuationContext continuationContext) { - return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationOptions)); + return new CompilerServices.AsyncAwaitable(op, AsyncResult.GetSynchronizationContext(continuationContext)); } #endregion diff --git a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs index 5c7eaf8..b23957b 100644 --- a/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs +++ b/src/UnityFx.Async/Implementation/Public/Extensions/AsyncExtensions.cs @@ -360,7 +360,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, Action /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed - /// the is invoked on a context specified via . + /// the is invoked on a context specified via . /// /// /// The is invoked on a specified. @@ -368,12 +368,12 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, Action /// The operation to schedule continuation for. /// The callback to be executed when the operation has completed. - /// The callback options. + /// Identifier of a to schedule callback on. /// Thrown if is . /// Thrown is the operation has been disposed. - public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) + public static void AddCompletionCallback(this IAsyncOperationEvents op, Action callback, AsyncContinuationContext continuationContext) { - op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(continuationContext)); } /// @@ -395,7 +395,7 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncCo /// /// Adds a completion callback to be executed after the operation has completed. If the operation is already completed - /// the is invoked on a context specified via . + /// the is invoked on a context specified via . /// /// /// The is invoked on a specified. @@ -403,12 +403,12 @@ public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncCo /// /// The operation to schedule continuation for. /// The callback to be executed when the operation has completed. - /// The callback options. + /// Identifier of a to schedule callback on. /// Thrown if is . /// Thrown is the operation has been disposed. - public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback, AsyncCallbackOptions options) + public static void AddCompletionCallback(this IAsyncOperationEvents op, IAsyncContinuation callback, AsyncContinuationContext continuationContext) { - op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(options)); + op.AddCompletionCallback(callback, AsyncResult.GetSynchronizationContext(continuationContext)); } /// @@ -430,7 +430,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, Action /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed - /// the is invoked on a context specified via . + /// the is invoked on a context specified via . /// /// /// The is invoked on a specified. @@ -438,12 +438,12 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, Action /// The operation to schedule continuation for. /// The callback to be executed when the operation progress has changed. - /// The callback options. + /// Identifier of a to schedule callback on. /// Thrown if is . /// Thrown is the operation has been disposed. - public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback, AsyncCallbackOptions options) + public static void AddProgressCallback(this IAsyncOperationEvents op, Action callback, AsyncContinuationContext continuationContext) { - op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(continuationContext)); } #if !NET35 @@ -467,7 +467,7 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress< /// /// Adds a callback to be executed when the operation progress has changed. If the operation is already completed - /// the is invoked on a context specified via . + /// the is invoked on a context specified via . /// /// /// The is invoked on a specified. @@ -475,12 +475,12 @@ public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress< /// /// The operation to schedule continuation for. /// The callback to be executed when the operation progress has changed. - /// The callback options. + /// Identifier of a to schedule callback on. /// Thrown if is . /// Thrown is the operation has been disposed. - public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback, AsyncCallbackOptions options) + public static void AddProgressCallback(this IAsyncOperationEvents op, IProgress callback, AsyncContinuationContext continuationContext) { - op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(options)); + op.AddProgressCallback(callback, AsyncResult.GetSynchronizationContext(continuationContext)); } #endif From 704424019d40e3f9137d7be2ade167c775594da5 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 21:33:15 +0300 Subject: [PATCH 55/57] Fixed Unity 5.4 compile errors --- .../Plugins/UnityFx.Async/Scripts/AsyncUtility.cs | 2 +- .../Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs index 2ffac4a..5b5192d 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncUtility.cs @@ -310,7 +310,7 @@ public static void AddCompletionCallback(AsyncOperation op, Action completionCal #else - GetRootBehaviour().AddCompletionCallback(op, completionCallback); + _rootBehaviour.AddCompletionCallback(op, completionCallback); #endif } diff --git a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs index 2705803..fdf60c6 100644 --- a/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs +++ b/src/UnityFx.Async.AssetStore/Assets/Plugins/UnityFx.Async/Scripts/AsyncWww.cs @@ -293,6 +293,7 @@ public static T GetResult(WWW request) where T : class { return request.texture as T; } +#if UNITY_5_6_OR_NEWER else if (typeof(T) == typeof(AudioClip)) { return request.GetAudioClip() as T; @@ -302,6 +303,16 @@ public static T GetResult(WWW request) where T : class { return request.GetMovieTexture() as T; } +#endif +#else + else if (typeof(T) == typeof(AudioClip)) + { + return request.audioClip as T; + } + else if (typeof(T) == typeof(MovieTexture)) + { + return request.movie as T; + } #endif else if (typeof(T) == typeof(byte[])) { From ab37aa903b53d60b21b9d7593855ac0fc585a3b7 Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 21:34:29 +0300 Subject: [PATCH 56/57] Added net35 sandbox --- .gitignore | 4 +++- BuildSandbox.bat | 2 ++ unity/Sandbox35/Assets/Plugins.meta | 9 +++++++++ .../ProjectSettings/AudioManager.asset | Bin 0 -> 4140 bytes .../ProjectSettings/ClusterInputManager.asset | Bin 0 -> 4104 bytes .../ProjectSettings/DynamicsManager.asset | Bin 0 -> 4280 bytes .../ProjectSettings/EditorBuildSettings.asset | Bin 0 -> 4104 bytes .../ProjectSettings/EditorSettings.asset | Bin 0 -> 4212 bytes .../ProjectSettings/GraphicsSettings.asset | Bin 0 -> 4392 bytes .../ProjectSettings/InputManager.asset | Bin 0 -> 5520 bytes .../ProjectSettings/NavMeshAreas.asset | Bin 0 -> 4384 bytes .../ProjectSettings/NetworkManager.asset | Bin 0 -> 4112 bytes .../ProjectSettings/Physics2DSettings.asset | Bin 0 -> 4364 bytes .../ProjectSettings/ProjectSettings.asset | Bin 0 -> 42901 bytes .../ProjectSettings/ProjectVersion.txt | 2 ++ .../ProjectSettings/QualitySettings.asset | Bin 0 -> 5004 bytes .../Sandbox35/ProjectSettings/TagManager.asset | Bin 0 -> 4308 bytes .../Sandbox35/ProjectSettings/TimeManager.asset | Bin 0 -> 4112 bytes .../ProjectSettings/UnityAdsSettings.asset | Bin 0 -> 4116 bytes .../ProjectSettings/UnityConnectSettings.asset | Bin 0 -> 4192 bytes 20 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 unity/Sandbox35/Assets/Plugins.meta create mode 100644 unity/Sandbox35/ProjectSettings/AudioManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/ClusterInputManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/DynamicsManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/EditorBuildSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/EditorSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/GraphicsSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/InputManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/NavMeshAreas.asset create mode 100644 unity/Sandbox35/ProjectSettings/NetworkManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/Physics2DSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/ProjectSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/ProjectVersion.txt create mode 100644 unity/Sandbox35/ProjectSettings/QualitySettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/TagManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/TimeManager.asset create mode 100644 unity/Sandbox35/ProjectSettings/UnityAdsSettings.asset create mode 100644 unity/Sandbox35/ProjectSettings/UnityConnectSettings.asset diff --git a/.gitignore b/.gitignore index 40da59b..060c784 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,11 @@ [Bb]uild/ [Bb]uilds/ -# Unity sandbox +# Unity /unity/Sandbox/Assets/Plugins/ /unity/Sandbox/*.* +/unity/Sandbox35/Assets/Plugins/ +/unity/Sandbox35/*.* # Visual Studio cache directory .vs/ diff --git a/BuildSandbox.bat b/BuildSandbox.bat index 22b6119..cf65128 100644 --- a/BuildSandbox.bat +++ b/BuildSandbox.bat @@ -1,3 +1,5 @@ powershell .\src\Build.ps1 Release rd unity\Sandbox\Assets\Plugins /S /Q xcopy bin\AssetStore\netstandard2.0 unity\Sandbox /S +rd unity\Sandbox35\Assets\Plugins /S /Q +xcopy bin\AssetStore\net35 unity\Sandbox35 /S diff --git a/unity/Sandbox35/Assets/Plugins.meta b/unity/Sandbox35/Assets/Plugins.meta new file mode 100644 index 0000000..d12c759 --- /dev/null +++ b/unity/Sandbox35/Assets/Plugins.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 382e7a09cd37d20449622045368b7bf2 +folderAsset: yes +timeCreated: 1538073111 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Sandbox35/ProjectSettings/AudioManager.asset b/unity/Sandbox35/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..38afce289013d324fa82692d030109fd89c21682 GIT binary patch literal 4140 zcmeH~u}&L75QgV`5E38>RT`Qr5LJXgBuW`VoXCo>WPFO-WI6WG*=w(L+!ds{ng^gH zN|TNzZ7LoB@dmsBuYmLadp<=qp=a6rpW5)n_N~BRY9HPK?|^r} nJK!Dg4tNK=1Kt7efOo(<@V^|W-r{BH(mltUu@F&H<8Ar}PIQ4D literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/ClusterInputManager.asset b/unity/Sandbox35/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..25aa9b955952e71fe4e3af59c666510e9b46e377 GIT binary patch literal 4104 zcmeH_yGjE=6o$|2=HmTsCBA?~P*iLKvCu+6B(@S{6eS6=xzqz%+xiBku=8C+2x6mU zp27A1cb1jK)K+KUaOQk-=AYSrRwU?)EKG>VJTj8VZe^#kdATj$aU2^1FhUGIR|jXo z+wgsO|KRFhk1Jp`1lKwCL>&6#q;TX$oi-eB6AP4Au#<|ofWxSZvFN2#Z`%5`}I^pkGk`pLWpY>$M zz5WJj>Q5p2bMyMs?63aSpCL~ouRoh{uMa;H{W;`u`gpCe`h3E1`imJaB;R|NzRMCg z2YsW@<-q&A?6K6Ey-wFghwa;5_o&fsT-iuk=SkVgErRab{`G}DZnP|lQycYdRF9hJ qby7VfTFhT+gb)0sI#UPK0d+tfPzTfjbwC|Z2h;&|KpprG2Yvu3!h4he literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/DynamicsManager.asset b/unity/Sandbox35/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..6c6d0c0db3ac6f65b18ce5c1ded4ff8918713df7 GIT binary patch literal 4280 zcmeH~&ubGw6vy8r+Sd5{$3?1G@E(*_3R7rn_Nw5*j_2KS4Zr z7eVmq$*btUAfXpQP&|sDw_^Oh*-e^*cM;}=mwoe@H*em2mpu$o@iNh|w?uRlPdtb& zmFLPA8ng6!Fc=5{Fc1IITK>HA!)TgSD+WDaT<*Ci*Op_(>dq4aeg-E`$t^RImB~tu0P>9 z?_Hozs9(jHYfQq$RL0BbXANTvy=Pqbe(r*C{sA~o^0~OrhdD1XhYk5-#GHSSA&fci z`wTI2?ul*4Un6FIm?4aL4f!8@OmxK4J-(B3){ho5{t^9u$B^~sSD5Ks5EoI0o%!(* zFZzC_v4;0OF~<3Q;ar}d%z3@pO?8y6%2;kHOI!DESlQ98OWV|?M^vvnyO8CqN~f%r z<|>kwR719n8zPXZHfm)FL0!7053VQeI8y6PtI}p-HZXPDDAgJVd6`NQI~lpPMk7^@ z^Agihb_Lr>r<1sXLVNg*GD(C6N7E@*+-jpWmEP2D-ReyogyC{59~gCQL$;jmsA^&( z1zM9`Wh;p>Iz?@q!0K(UX!ZwL*!Y9t&te{;^Eg;gASe(N2nqxRf&xK-pg>R{C=e9* kUle%%>&&~q^txE;zr0fFpI_i>bat&InnBE0%71Bp0FHJlEdT%j literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/EditorBuildSettings.asset b/unity/Sandbox35/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..db838363b003e6fee745b984e623008e073235f8 GIT binary patch literal 4104 zcmeH@J5B>Z5JYRd_VNo%fFndi2(pa$IJJj^tqzAZXV095dn~?$7@9uSbm%I3`s>(SUohIOCZ{x3adC-5F zWv|gt zI(sxn(s4+z!FbI-)wg5@`AwYgwaHXFQwoD$|Clqjn5uq3evsdq+ba@oAU~bkyCgp< z#VI?rSNU@7A7y!Ydw=+lPqLve%e)v*adS4j@P(fu2KZuhKJgjuM&(tURkt$4qt!y) iY1SBP-+~b^0!F|H7y%<-1dMQ}&3 zeJ@vmmtN(+HpN>}?2PTQbFtpeDBWxg9b2uE7i_cG=vAYgHAy$`_lqs3?+tJ7&OEI6Btsa_FA0W?LSpy5T27^I89YrQpv95`k|t%SD45jHGeb&fDWIUCVuoR8FyF7VlJ{}LAHd|7Xjb~@r{DJ{t)$yThyw?N zICxwL@qiEy;vvN8;Zwt->*L~|-Q8W!0~kcP`Rk2ix4)Yj8vS(QkF(*Qf31Nn?-SxK zJZY~A(S`r6Zghq4@aL<2qI=5|-9A9ZF~t)HQGXGIawQa+huY7GF@`$*5n3Dh8Pw)b z?n7Z8&4UO1-$I?NUo*ppq5BTn`%wlQH@XsS>e{^Xx*S8x>)vf}LH8c*ThzVRaihD1 zHg!1%T3#1#L0ew;e#f)(#oI!RqAoSk>-;&|WL$GvUiXl}ny1(KA;+`259=63-NTNX z`QAXAx{sjH^16>2T+n^Y@vQFSI!00V3CE4@*JxAs2nsE)`=r4I-J_0Yb-DL@t@Bfk z8{KcwrtUEmT3+{QgA2OPIG)vgR>vsL_c_On?)PX@_jwdrUiSrq3%WdiwEQ{ZP0(w; zLymjmC!DVz(dKzSfhP^R-btKC7V?)2cJYs34A1GyDbD?N9sWEMuQ=Y9IoHGBCZ9f$ zKG!3Tn|yvpo4TVePBtIprOnRQ=EM7jM$XI2<}8oJ4IgJ)BPpUohI)V zb!W)SMcr9)SYDUE8#K$U?nS~fx!FH|Lznw!p1iC5Gy8eLadS@X{&|xe#{F}+WcCl^ zTq5j}_lbGz{Sow$~!i{8ZuyiCFJlGL&-CyJmI6t%_{5MLU+wx{Q)ku5@JJ$2;`hTc>IiuBoYT8_(-z<$Co8s#(XY z!}NNnkM+jmz1WNV$x&HN} z&Ce5#=aa^|{eIP2$+s-)rBvNJK}X|%C{-U!>b9?x>cg+S;QwjpSUu_-W6iS$@Glvl BC8YoW literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/InputManager.asset b/unity/Sandbox35/ProjectSettings/InputManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..31648127efccbba56ab65bf05b450a465052d878 GIT binary patch literal 5520 zcmeI0Noy2A6vtniiTkdJF>Y~R4k0m$AgGBOQ8Xyx27z07n|6YtVBbXUKB)%#WTtJfh_BAqKlx)w!blgMUN zBB%RL^$&~>$)BaACCh@a0oTH>m(Sl`>HhY!^t*S@jvo62w9mNUt;-padGue>#=MAy z-@6W(|7gj42_iYsWyyEwWU{~ZUtrq`YY+@x)H~2FTJMk_(00Lx9A2_oqyxY0c$|v+ zcT(5=OEQYS?=dbpD^tBQ!(Rp68s)evGkl=M!j1ZEu*v7V*Q9#H-wT`kwWyksk5;VUxcRwTX|_GV-~ECjORGkN8(%lfMueV6*-*K-^Kb7>Uy3fo#!85 zl7EzXJTAYlkFkC%r+W>g?r8<}wesi>grJN3|+R%3Qe zWo$KJr@9*(7aL*dxl;E6hi$QGSHrPv2Pn6)eI|T++6iYdf?bh7xf(zraP7J{?zHkl z31{m{Y))*-n;mP^bflsiUk7Coe>eE)ZNOq{p|}+hC?Zfqpol;bfg%D$1d0e05%|v| zz%3xRv7?^v%z18TSDP=)twL3ehumKK&ctMhn%fOKt}CcThKIeaFV3=NTWi4%L+;^U zai`p*l3DSdx!n3U>Jcx%Gku@oT8_tgTy=bfV}eZK_MG$VD~EnEeQxnfxx!aSL4;M_G6yAL)sc^v)UydgTZ6vkNdf=Opw6I+=ay*-mLyWXfFTFt_F z2X(uwni8JcGdTa7Ivx))9wy`KmoMk2x2|W?|DnkxqqX`c3?4y5t2Q6Kx_BNt+zT`ke?FUXlX||S{&*4kC-0NwO+FX-p4e{&NcyLJ zPxKB~XJC`tevJ}lJ{L{Q?707C=JV0S%#PchY05_vFFR&?9*^nnG@jI)_`67AMcr3n z!*?UaGzP!!q^bxV8pUso5L A6aWAK literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/NavMeshAreas.asset b/unity/Sandbox35/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000000000000000000000000000000000000..c12291a7bcdc6121ea2d4f9af65fb9a1388f24ac GIT binary patch literal 4384 zcmeH~y-EW?6ot=ZfBcIWv9wvR5yYUVSVqAj2nMXIM_Ccw7;#t2u%%d7T4y^!51q5%lk;s4X)p3>lk1&icY7IbirbdB~p)a-X93lwt5jeVVz{yZbkCRxzve zkPzMDIh^j{o!UI_h>rxurQX9Fx2M1Lf#|N@N0YS+OvNW0=)s8p7nU;3UH=stSX7MV*glMLynWv}<*^kn-owkfQehol{wS)AK;jH6DP@uxD%*=-Rq z5zJjST`D>&0VSXWlzuB3c z^aAw`MZ2KsJ2TTHK0%9f;mkSrHy`($`^^wpYeeZZ5zQha5v^njnQS9Z-=60w1<*&_ zCVQ`UAJ65-o29{*{i#^mLhyTDt3)pJUa(`X=pjb#lOi_`$hsgDy+Mm^#N0ygV*LPo z9yRkALoDX+;ESmF{J*m-l>_Hsp76D-kNM}%p*L&ChWLU-?kV)#V?5$) zw+RO>c#(LL3mo7IAsis#ATbdRdccHu0l9hRAc-Di{l2cMp||-1h{?R|ntAV2uikt8 zs-}}(q9p~Q(Pc#RGSNzW5q(_vsIX)DLwYhlKks<}t1v3Z{@(oXpHnwGcPG!C>;C-x zb}%(Wge#R#h$J`KIK#Vak_8-O| zddfGzV$Q>G53@v{VsP~@V6bqUKM?10=kLLV$Th9By;^OSLocEl?@oy}D)!>v*5%o@j9C&yjhcl+GrE!(`C z`g~#D%{lJ!Zpm?%_q`lW9GHJ!(Q8*qD zb5lVig(}5L$p)`6v=}vK!)I|_i6{xvJhd4qZHO;py$}UaRYp>qg7(D3a>DU;6v zT~|S~DHV6d!kR`6m8cYlVQ|#Ulv*Nc%9@U6l9C9+BcgGf7Zk&e=q9yR+{rp;ZC75F zmEuU_J~)6?i%P{EcV8}4u_KO47_lNnO*%p%U0{kTCVby!mctlo!#O-9x)Pg*xdeNM zlcIvT^wgOT96y$2IEVaLT!jOkg2Bh21A`6>Ixy(KpaX*r3_9>X?!Zrv$8KfI=htBK z3f}X7{bgz|%p%d9Nuq0|rN3|7W7vcb?z4^W3I1OJF5XvWdoJaFl& z-#YxwkNof#-H%KRf@^jUf_3=>(m_Gcg#A12q8S8j_}?vS1=@SbdKLZpzl<30I0gh=$KF9@24y7xga zi7?~&3*blNlJ;SFXiq*Od_DYR3Uy9$?}K1{!pykNS-7Om26%;hF3NQ+E?GYtk~e8T zp=}!8@kPE7a9f6aEtl_hc!oL~le^bi!7;Es5iee|{yc9BsDB%-slz%=(%+2snO6Px zkh_=F-&}cH@W6zi`6XP__bu>ZVm-5d9>IJ1xus*C?+<^Tz%}b~E9Gs$bKuVie=mLp z!DOd%19V=(6?L{Ij_{XpMZOKO(o#7JSg{L{S;0`{Y@{^|ebZQlRw$&upz z@8DRg|2r!8`A&rn^W6zArm&xM3!m)hIA1J$=NKOozDtasA$->uzf|~?7{6WkZV}FY z{xxv?Kfn-mDXgEzh3`R{@qRvocKJCt`_G=vn%wr!y_DPjxp$1Sf3ki!E}6pmc?0_7 z`#L(#H=p47eldQC@cmCBJewuKMGnc}8xK{Y|7=J`K;|Eh{|FZBI z9xGpGEuZhq7~fj>fiaG;;rv9r)cU9YeZmip*`FZ%kQhH%IHI>pp`YgoXPjdS`E|k% z^H}*^!Viz}Cxjmn;~2xv|084kRpFT!e_MEGjBkd{!1n5j@tuWt$9RYEo*17kd{&GP z3ZEV01>tjI{AA&CWBh#Ky)k~P@S|e9vGk;3|UMfm$XcARnk9qP!ft^VIRmef@8Og#+{bfa-X@kMN}t&iXtAob`MHd1lzgl=c#_txsEXE%fzC6ZX7CuUz8Ta#F;H-xNITHQfbW#xPfETJdK)i?7 zAXS_dL|I7#H{8b@ux_r(0>LlQ{ z47r`Zs^sov*FQDoetmU<=-0uM^c%F#wCb-UcQ32IN_ktr`L`tctHGJ#^Y0puTl_yc z!q=exbN*%j|Df`TW}WsSaPQAV)BiuL+^>^Qk$OHwbv(ab_^IR>YI**M@FqD@$e$N} z8eztBj_W^zvtOM~jueiI4Y6n>|A?dGd}rZjL^#{M6P)dSCV7+gcHMFoa8kRRP3~T{ zUCvSN$9tdTdoDOrSgv7kK7Srz#&eddD)#4-BZcKUTlfVYJ5K*^0;m5UC2!K+`u{QD zB>yiYcQ5PzMaq4<+#`No49*n#|CI2Ld#wCd!Y_&OH-%psvK@}mCoAxPd+02su(|6_|-9fuJCIjobmQr zaMt6sG5&es*Twj^g?}=}pBH|8jQ>IS4dj_||K9;;J$#BBiS5GqYt!}p{B@(ppmzSc z$=TB0&R;hx_d2_Z&MhfApH_RTbE|T%bGYc-mZEdJ+FPB^DEB(YiOy$JbUvr{R_6}o zUZ*NLpHI>Gg4$c1JC%E#i$&+I6rC@sz16u}x!1W)f z=x{!IUO46&@uw}g0roEn|GC2(#8~Uv0m+@i>=aDXO*7L6&b@`fg;49A7^XNY4H^RgEIZpInjp#({=QY*w^>B*V z|5oiizf$<`BAoSeCphcp_vB6Ij~Umm11HtbAIROy*3Tc6`*HEK=)VD;r2i-7c3k|K z9Etmd-#~+LgMPkA*d(9m&RsXz$ou~nL;m>+{DSb0X|Ep)pdpzc^a>rV-9~J_3&J8*HZB#@qL(zKxSSFXtoF zXSr5O{cJ(lB)9dmCG9ihwtlu!9Xn3ntK92fAo^RU=x>vvzpd(6{q2;?z7_hE-k$#; zv0Qy9$-TmNi1BX<-;q4y?YU3?iTJsb+S_`VtlZYa&Jq3^G}uqJfb=fP{XF}3+++Lh z8sq;KJ|)80zH4vn+jlqRzF$284eIO;&RcCbt%=6@J(T-?wIOt9zo+W>d3F!c-%Gje zKYOc=?LYe{_v7mb=y3e*OPwbDvGul}a$9fvlOwTT9RrPUd>x?nJ`N9yK0lxF`Zi8Z z1NZ&Y#>wgAPT$7icI7?}S44jXjh(&KpQ+sHA1HhR;_zzmpY48-+D~%(zB6%;r?Q$(R+vRZbCiQK*9HHE{%aN+H zR`5k=gzb`1d)qFZ%5A-MfhV;KKTqQ$oWG*;LXYx^Zu~xqylFR!{~&Q*=D2=V_-yhF zxi9Z)Qr$e_xyo&MdsTm}VB#j@bm`a<~*P?>yzcA8wDl z*Y9eY=F~llLpP^>#dXQoDSB z-09nXxKz2<57#Fr(74HGtbUgE8FJe$!>VKTbIN`FFOvEhar#Z@*!s^qeR5kr%bbqq z(Q&j~xz`^S{m~TtLW=&0s$=Kh70UhmQi4AFTao&xAoeS+(@qo4&%;B`^~Po5Pl>$Q zTHZ4CGrnBW^05tJQtr!pi|AKV^lK^lb=9%@4dq_{F413^qQ5Fdf3@mZ{WZ$H z{zIaFa*F;3Q}jQiI#&O~%6+^12>KII^`}tZ)u-pL3O_Z%xh{HJ{ArRmTife2<+gvG zt~z%8{1LUc>*q7TeY@NB^O@w%PrH6TOS$)d(@lN3&Za(6*bny#kE_s6b_E>P~*R|V1eXo}9q)ZXe`sNDC5)1kw8;UelJ)c?h_ z&(Kd>{~uQ!+aE4b?(6MxsfSCckHmU&>t}GH%VPW~;g`qwZ-ie#p7A;y?{9sxr!W*#OIf*mHYbHYBR5Y4UH4@ucdv)>qO(pb*f|Q=ab64{w|__eTx1K zDf*vM9jkw%aHBdnEKHqH1oXK2kU?<_o_q!rA`|;Ozgm zE4TZCobx1Uw+`_IYHp~UC-Pi8#d^CjOq$dSVScAMCLKE@vt{)LDR`_-?(*{|*- zZ&JthtGmFH+Wm{2_$0e$w{ zZ&DwL{eRA2nEBEzwzSP^()JF>I?Ka8x2jtDxdix=DGOhLYjOyEbf27>!d%xuS zW9lP?0w4P#-C5_X{Q8-;g)SZMj~hPNp^A*Hqu;`&;Ec-)kh_-%%ea%=cEw_xI$@ z)_h;5PNp^AKd8RV_m9ebecmVfZ=~q|DMkO!s$=!vRPM|5sFdq3)JF=-^|a*sSMp|S zx&B6-Ol!IRuKG6Lx0L&QUzB|RL473V%l`0|@P9@)`|Tz;bYj2#7kRVQpSP)>Y4zvd z!#?h zm!iME>R9~^lzaUXMSsH-{f$!eH&z|1zln0Mf2!zjnxem1ivD|4$LjNY*}h%8{>Mar zixmAWQ}nk|9jpIdQYr-!A&wr|9pHqQ9f+Sbdx|nfiG| z^e3n2@0_B)i|SbYU6p(PpA-ElDf+vm=Ep&; zc4bFD& zirACiEWA6yS<+m1&o z_xjI^eqV}ye~SJ*)v@~Xl}mqsKFc{keWb9TZ1`T!kBRY}g)fNl8Nvr+{3zl4{hO%% zQsE29Gd^FQ2d)NZdo3b=kleP{V)7=rjT=kIk;vKZ;pa-ns=YlAd>^=PcY7Xq9J$l6 z=Yj86?%U;j@$-1*rF{vF&n#a(}*e3G{hRlBGTp^vyZpu-e;mlALny z=Z)g$2z8pRe&%VPA-8@mQyuH)a^=4Nd>Q(zuTknd9Uq^c0_Qj_kRyfj!VBWhiR4Xk zTW>4Cll%#PPb)qi$7mnXe?#<3Df;CU{fg??@}8vJ*XKK;Uro`krRdjH$Lcqfd;P7p z_WgflivFq;{ne^t_3_<)Q$PEP{>dr&A578zkm^|d4=eZnA1eB%r0AcTqTf^E$DBt`!W)v@|#D);)wiT+tB`e&!;pQAcf|6Ju>zaskQrRblZqJM$vSpAPG z_xk6F{>M`EFHF(DNOi3K#mc?@)uR9L6#Yw5^eRLAOH zsod*7Ci+*U=wF?pe~s!`{cDwb{TD_5x)l9Srs!XV6#dVq=zl?Vtp1(Kz5Yp}e^-kB7gO}_RvoMVCFNfK4AH+QMgQIu z{V%JI)xS@<*Z;Wa-=CuYl@$H2s*ctFnsTpyqv$`7qW|?2{RdUY>OZ91>)$8(52xrq zlA`|&)v@~DRPOu#51`L=%eSbH6z(fu7XE02vp@e${P{L{v$a1zM*R%AU0;2N-053? z9#`(myUwtV2zpLDrcMIsVyx*ffQn*grS@Qipd6V3()1IbIhTN9x z2dZ!L{h@MSu6EIXCPn{8Df&NF9jpJWa$l}4Dc4V^j}*4!F~WZu;oKLm0B3vrEXF@1 z{J9vvMELVD{wd)v#Q5F9e;(tH3jalnKPUW`G5&kuFOp|`xiHq66SwpGg_o4u{lc%n zeSfq2g_o84cG(;{jL*NOPLt2rc7KKTE??X3zfm3AF0U&0-`Cn*^j~xO%@+OND!2N- zBZoumZ#$v9;r{OTYVW@X%kOKkKfkW__Ip-;P<#75t3QIbWvFkzXY~fT%h!I->QBmj zy&W#)`m@vLGq&E|bo%7BTz_#oo*x6>!|%EMRk_!nC;ER&(f@mj{#&YJ+vOk1z5cN1 z|1(AZUn%-;tB%$Gw{ow)O7!1J(MPqQ{#)y(jU4UCdW+W21m#};BGF$99L?2I{}XAS zpue{2Sp9XBd;MEQe-e0-{<^eJ&|gn=tUkW?C*^8$-^=|v^zo~*!3N;Spe>BU&q}@< zk~dq+wGnkP^fyy(_1{B|ME&S^++6MLc-%tm?ReZ$ z?d^En3cM{teLEiCOYZWu<1zfZDPg_+TgtVK>f7YM(GYf0q~^625DUuMj?kJmYn^oi8vELKCEg0vI3EwNm9~ZuNj6W%SALah{ z?7j=meD?(pBKl#z`>DP6C(IY$bvOQm`5qACVZKw9`+EK(@?||w0}t!%4U~6_9ele_ zCx4JOwqLcAH_2_knn8{fA1^c2-hSWsK;?E^90cB$p^hCF2a`K}J1!1UKGA(&I{dzI z2e|js>L04y>K{gq#C)UU{cyFPagS1c3A5tBwzfifa|B~o00#B-+#k6<&wtkkVj;;S=mHW8bg#JWGzYjbd z*WAZlCHWpl-eg_ac7H#0GUPVjfTEC+O!@$LcRr?&IN4q0e$I2WJZBqt}Ixl4r*GdOLdiLd<@9;U`AyS^v|) z88=ptH~Fls{~~ys)3^0MMvh0~^Y<* zKV5i@Jmd9Qu8Y7~t~z;>+?J~W-sbFWxmJ?nk$AaQDfjJumFTYqPtspQ`vm>)@4&_N zKN!=$UGzVcqW|F({ZmxO_N!Bsd;h;G`pp#m(^B+LR~@VW5#?V0Nzp$eMgPnc{j*fZ z>YuIL>%S!W=cMSLo1%Z7>RA2rm3#d+MgM{n{g0;Te@u0({)NiD{`x!l{&`V~{>3T! zA6Ff#e~EHG?zVwG$K9pWM+(>H`%1o-kvGZhxVW4;8FD)=t{`_hHs4Pu_vJcV^sfX@ z(!YxK3Hn#7j@7?Lx!0d3`qzRd>0d|t1pQB{j@7?jxz}GR`Zs_l>3@p$3Hmpxj@7?O zx!13V{>|V?`nS+NLI2aLWA$%U?)6U<{oBBk^lztqg8pYz$LfDpxz|5m^gjolq<;tP z6ZAi?I#&M+%Dw*0qJJlNlKx$^PtgCO>RA1|m3#e%MgL3SN&5HDK0*Ip)v@|tR_@2$ zFQGpX()WQgaooLtocXbuk>ip0Jo12Yzkb+n zvbXy>csM_DKRZkKgAvYsRu-J|=0oHU@>%Q8!{kk$FUz$Z%E0nILXJd#qWhF@sJ-21 zeN(wzCw~jPEkhlDzVex0O!}DwFZ|o#7Ate+=CFxwhLM;rCk{|Bmu?%>L+c z>bQLU?_Y=IdV<{LJISmwpH%Mk&q3bI_bG6nuhsu9?GyCBr#e>u`^x?IWG;k0>-lML zCjNbZXHeFwCi{GUpxoyBL*=$yc-AHST@lwmxv!!AkCgjz-6;A$CT}udtN$!`TZY`~ z|AZWmkVn_&KUMC_b=PEHuAhN3h2{FzWM8i5$TQ?N-{;ld=KDg7hvoXYa{oP_XQ00! zq<^9M_T2uL;NE|GZvUckzps21I&AlssMF*#cD(#bxgEbRlOu7wFb;(K%3rI!{od3o z;B6V&+wV>NhTQ4c?@hg`-2Ywo2|N3Gehr+7acMK;I|ZEn|CYQ-ZvFqAa_j%^Rmb}O zy4qX+{{Y^Wp}zJ1kL1oD>;D_def*p${{IP_DU7QNg#Vd5<2lP!l5)LC-Xyo>`ipW~ zuD`0jE!W@F-j?g{;B78nTdudrku}R3?f?H!?&EV4e$wur;7lwROFV*KyIC&c*1yLkWCit*iqPmJ+{gs&ary~5Xt@uk8i z#dt;dx-ou+@bzN+6T;Vz@mqv%5aag<-;g}x+lBq=QE-lzjmVqiwqI?m-1e(Y$dTgX zeN(l!{mT8l?F{X0zj_bs+nkQ=SDP#M>ztp7pIfND^>a(wJALctR;pvyIqy~O^*7$t z*TdE+`rD-FZ>u_1e>>$~{}9pNK1F|r6#X4l$LjB--0LqB{mCi%JE!RHqB>T8SLI&+ z3elgEqQ6^;{_d({_4iQj^`8~}JyZ1eO3~k2b*%nA%Dw(OqQ7s7{(dR?`>T%CKR~(H zpE1SvpQ+$MlYQFu&uO$z=%3Tc@ko5#+pgT}A3w$G&j3$a$IhgEg8qT3WBor!xt}*L zn&R~j1`nF_$NGPWay!2Gck!9xao|w3w{hSwaPOy$1Ba749UBLZQ0~_!H%;+=9tj>a zTm8%^w|;h#BgOsfQhV!XH+YhtJ>*Wu`Z-Iv_w&Ii-cSDb0fJ_$pL3L3Kj)Go#r^D6 zd+X;>;7NWSP40B8pMA=`pFf@A{p<%1nyr4$Q*Qm7PmUD#b3pB_pT~eF`MH4H=~zF* z|9%4358N00d5ZUQNcC<1T&Udoxrp59+x5?4wYPpQ0Z;PtSaPRh{d}Kt@8<@)c|VU+ zee37@m0LfLCwKbR&kv}*^>ZnBlAkA#J00t1R=M|cSMhUL^{t;d<<`#;a;I@st1EjG)P9te+<;w|=f5M~e5)qS{+O$H0^PERj1M>t|WH z_j5@6tf;>A^Cacg&nmgoxAj?5d+TQ%Jju@nxzn+Ju2k;*tcstjRNwl!TDkRe4Y|{| zex9uM*3S=uC;9mya;Ibc{IGKG=f&dZDXMS%JXN{%vq|pst)Hi`T<|16&m(s_*3a{mdq2M^eqNyZ*3XYB zw|;(%-053CFI0Q$=SAR2eqK!ObgZ8rSML3MN&LJ-^{tq>_45kw zBtJhv?sTl5S1R{@{!9G4O7*RuS1Y%EUPJEmt)JJbz4h}t@FYJ!N$zy4pVuq*er~WlApJbJ00uirI1&pVWRKl{Yb&r|O$zV9v`MY(m*l0CSM)Q*XxDS@>)=-mPZ=7`kaNmJ;6w} zo;_~r@&4yD`8i#FwjUpKmPV@O!pK0iysS{nSA&uKvTUPRAIw$r`O^GqAz!Lz>xFVD zsAsFo^Yxzm%0ez5G-~y2!2K|WiI-!z3>To|d3+H%j$7nYCKEpujz z^TU>UOX9Jm3-YCrd=)Lg0^qv8Jd7g6X=kopSefrG7t7VbN)~kq!yz@&$1EGHXLBot zsxTi~Q$bZ1$~6|-X`yhvrIA7|TQ67Vm-@=t5x5YbW!SF&#R@u|l}c}^3-ZgW#g zwNZ-JUI2INjcR@nO;F6s)ALv6t5uY9a_>NSWO9F_R>%bd)qEve1)4uNd3L!vc|kr` zuDXV+HHOCu_0CeZxTapn)mR2Uy!%l3!`T(=I>kZ_#p}=4M$s3Rl`;B!hP|a)JzGMb zs^)8jlUc~ch0;iQ6-D~9IW+Yk8YsUABLZ=OHMG3a7+g^(mDpvLSF@E-WO-D1xE8D) zF0UTwT{4tk&GK~nVmUgiMB&br2rShIIJ!{E=P*w3oVW0R?ZJ+VOqNG(&MwqT`C2Vl ziIPCg)S+u=)_%hml02wya~rj!dBg@v{Jv;)~M*#)In7M7RLG@ZrDXtukUm#Up#igq@-2-06JmC+fN z!=JwV%6u`X)Y?t#TZztA?$3{vt837=7Uiq;{OYiKS8A2%0~o7SSB1Rl%$?LIRP$YP z`h!)4!os0Nk?u_}2Z4JaJJLVc+35@h8mO)=Q0 z5I)hBEwXoZm9y0mbECh^&NxtP)C|U?6jO4M#}BKpOEQCTt8T=wdeB*`pf4_97q20r zO8$sXQ9h%iJ($@sBbatz$F!;Z_mE(IeKcRK1;dDg=#wLu`wGhnD1-;7NDezpVtEEV z%GL69WROQ;eZwOV=PR5BO7-4SrBNSrQ={v3XgKLOeqhY0G*Hp`D#j5-YiP|P>bX|) z{c3zhz-(SeY39i2^z9nX+g;98@vNJp0uhaYzrRo#99a>%ED%u#0T5l&1&U&^uZ&rP zxo6Alsd$H3yi(}qj9o8a_QKrayI8GWEmUTe(B}|;kV|1;v|Pdv0Ig_06qp07cViS& zatv|EW#MmjH44R%d5y7Q)GGRB4kI7KsFbe{rdP#(KSM!)x7DKjz zDWMv44jeseH5L|pgi8l5dtAF<@L?LR18FtP`NTVnlCQv9m_7yi*13XjDxgBN|g<-cUjXh96U{7+I z+?6w)18>9~Owdg6k54E0NZ#V7-)hK68FK>{Ikiwk3-o9gXBTCwg)GAVO8;{xyWDLw z+@%k05LmdNZ!kBSA49;9sOSf*>}-TZd&yufi;YHB7Sz#EAjU`M*PxE8d6(Nb!zwFV zi?X3bCbEY4_trSYh8g&Yq>HhMyCRYE*Xpv|UgfqfqkgwC>>m+7DOo{n`^nk|aReN* zme)*NRQA=tPG1XJ0HPuzx3_^?-i-e)F4RX|n|g?QenU03RCZD3(XK4ka$HD7=RmJ<*>F@LZ{r76qGOZ~R^^BNl6okQWgTV}+zsFQZiueq zmm))jy4#hyg%CDK6>LoXieqf7TpG--#L63Ej;J%2#WuPka}iyV^0(Voer1-Es-%1m*g?e0^aF z^DUNDBePcLu!^Z>cGUpGU*uAin%QmnLSNobg&|SqDz=C`Qi%>Kz z%>5!}VGVJ)Ctq{R56UmWa@n`vh+LHWg7YKP1`)_?eCy()lt^nqYu{1B1*Z8Gc z7+-4cPBb(`_7i@K;XvoeNPz{+7G3s!#pddiEBL5#(k3K+f1q4*YFy?!z3y^pS-~GN z0QK~BTQD?=GCyM%N%vjiF!SdR~R^ z8zmkvpiEq$Rz}eRILrx+2hhJz_n}}{xm@oa&F5D1XIFDHu*0zQM|X`sLe0T~%TP^< zIO_2hIBAgWN&6zRm+5Sb6w0*mQ4*`L;WDxbx*!sYwtMtJymS&Y?_Rb0Ucpq`2B*ZevEkl#`VDoR`$cpfogV|#< zsS?}^bAfIEjd8kUGzO}LmD${yISnlQ&5d~jb%tSN8fq*+i`U(`2m&j%Vc0x#g}|)M zt$r-}(64(6RaYs6XTw$M4 z!&#PlqEed8!`l(L#WCooHf9=N*27vC_RDJHBLY>2z2=G7Yhs*7Ffw=JuHCKtxZyzF zgJpCs*`oNt=&%^d*(+iq4y>wL%h@_MjKkfPhKtpdL4)Q-2Udj9%wP9mywvJ(%Kh5% ze4(_g9QFb)2luM|*%AU!*abYd!+nN_?LCo#dE^djS}0~697o`=Z_xt!DQAXULtqnz zS%T-#ywO{N9nJy}uNvHhVpV{%fR(saneMF$+%LH6gve2uK5szsp3~J|uFg4XKun`S znN}_ejSm4L2GN=eG2xYlX^U$nYKO*HQZNAHJjh0x%5+pGPR^y8E7SW>4V_p?%t5=f zKt>LCa@=yK1q@+%KCX(}xl!M!z2l8aZ@_UfhqDG+yQxLolxe0`TZO|?$NbW}I@(09`|~4(EY6d%Ih=PmmH4DunI4~2E7QkArWQ0hui_Cq zlZL>~mMpI;*7yf0<8l&dk7?jcU8=y&Gbqa_mO-v>ID_cCQ<)x_c-W|R=E2Edbn1b7 zi#T&@jirS|8p_-`YpmgNb;oi;IHyGrm5&M7uNGEtq&&j2QfGzWR;-UM&Q{%NvoomW z5zF)xiilkSCmlH4@C#4(q(HwPmIqto;aGIM)hg8jdutByXP}JGx+aj7A*O@;GMr-# zt{EFH7v=a)8o}+>+Q4$ID!sK@gS$K) zAV%=Ka=mjIs?y(xOg7Qg?W&refu#ULm|kl&Our+c6j+#ifZLYhwcV9E3R0)!eS-wKV9O-3FCZx1j$K9fKNDrtT*tD>GvIR zL#G@yz#I^_;l^$mR!JP!?j*Co=**g)J=8f~a$K-t7z=7azuXQ9KD%_wI2S3FiJ2F{ z0;^umm5bv_sP0MunPTz`mqIv9LPeBd%gMQ-x3wBNPkszVM z#wq4t#Jq@^2eZbo<%v*q`xTK(4TaqJ;VfRVfCB;+Rz@(cxlb1`h_M6Paf>jv>LV`f zj^7{b9)HjE*8E!74_rhKGj`z~&75=-RfD;=unfzeq}vjduv@9F@mpvkn)hYE@kgmq z#2FYSGr1q_dV+eV>ZHR z3ToGl4!m_sJ&Zg(VeunosVrUn`JP+3jV<*ZL7oURaZ4>Ze-P&8n>@d?z;V@!MXuZ! zKTqeRQk03__0U484*Lp1xce#sKOaB?<0I`-zM}*3_{;*0!YINOEWEOz9{#W?jbW~}Y@1E;nyjH_gp$Hy={N;Y?S&~5-fWOCupRIPjv zjt*1hcTZ%q(b1tFk;m@%qs18P=y2zTF&bdrDQ1Ubw4);t2eYcxa&>N_)jZ`!z#y;` zU6RufKlp6P=f4;PNtv~>U;y908O`z&#FiXVZv_i+Cf8z~00Z~knx&m1wN`6>>n7n& zuo8=%GPalhWsHpY@h4xs5cVEqPZ6vlX@>U8kNUKrQXOD%MFHHu4FOMRs1^_&CAv0n6>-| zy}0Ep!$SdnPYp?axc9U0pOHQd?@q%n?>P|pXX9Vq_T))V+|}LO^w1LqANu5jyv1+1 zP2d}(!|=l6fh;z;vcZ?j0{kH@{AZW_jNLvH@6%G$4`)O1weW37yp|vn-Vbf~a~-)3 zdGsfL^^gfB{<$`n0{q=V68A6PG4XagBIz0g12VJ zH2ynvD*r?#ez+_5cL4#ywu=9h=iPJRKTbIOhrf4^G0+UJQ+`s{Ws-9Le}kE2G&SYI z<)Js)+@AypFL`eYUbA|p9oXK!-@Jh(OJ+`MKXCfesZ;k0%N73QGi&2D6&;@aH~OCU z!o;Efze(X(=QGyVhziz_OJ`<*LgU9J^|$P&m0Zy;n(!Jh`iwUESV2yM0#AywS1tTDh-lVDzAA$L3cz3h!1+ z?e_F_G6?|Z7nAX2WY=E3i`Xjrb#`_4OqBnBgx_^v0nhPUZ$>g1;@Jy z!GuY{S{%n*0=fW=_ugjq?DpBNNv3n*y=sm7s<8dOqiNEHV94|rx z+{a%eOo@~ literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/ProjectVersion.txt b/unity/Sandbox35/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..069bc88 --- /dev/null +++ b/unity/Sandbox35/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 5.4.0f3 +m_StandardAssetsVersion: 0 diff --git a/unity/Sandbox35/ProjectSettings/QualitySettings.asset b/unity/Sandbox35/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..3882fbdf80651dde28102709f3f1969827e515a6 GIT binary patch literal 5004 zcmeI0&u<$=6vv+v=Lc}Nc-F2Gu zfXoF2DF?V96%LRKhr+2+PaJ?FQhG$303pP+rT+loeP_lS@0J7HIM~T#XFl`h``)~r zadwAjXq9MmmxvxDI>r~GGvia^6ZJg(b#QQy$uKz0<>R~Gj%B|Y*?s%OUgbu9^4J+> zNBf8d_=?Y4L~XV|(2X`xhJU{7r}m8uwX+PNV@ig8VOzKYX9=QVWB()DpW-HT`oVX= z`!a8^JqkF+7~ZdSPVyKq9S7_5Q9tFmec9R%#`alSV%q|@p)(ZofrLIwP-Y2!2NU}D zfpaJLdDezL=5r+GS#7__ZNzhwi zP{)}i@XsxOC}n@s@`tBB^v;26>O&)%? z{4vduPs9JT{P7gWf`Z=@DL$Gp{E04Jw6YTqGtk3K_%opEDM#t>y&$tCX5%Xjo`1^x0Gtf!qVG>;H zC-*hJLku_f{Rrne%WR4Z;yK?Eu8OwHGK!S99#Z4dTq_8q7ugO5X_I7|JkgNUR9n(5 zs`ZU%&Tn}Ug&V^0uY~rxB17M8MauUqCn0w^n@h5 zNX@!Rgq#ox{d!aqL8NLfqT|-8T$hp1u?JGPk!r{lS$EBJcw$wyt18#6`XX?`1yPf8 zoS{IJ{7~spo8@hAx?rJIugjpUu1bF#$+?T_e$c?}ElH$OH|J$twA}bk^UCI> za`@Th|6N#~r+H%@(q65XfnElB8R%u8mw{dedKvitWB{+ucumGD@d7_J$uLR;cldnM zoaK(0udZL8{%~jK?5+Lc^qt$crw{uR!|2m%*QP=6*o@bFT=BsbesshBIn?;#AARU! zg6;vfertbU`@m~&w-3yxtQt*MnrAcUOHpSC%4ba!IgRcdCkmuW@YL>@iW4q&XT>THeXol_e@lv-h97$l!&3aDYD@VsM!tHa) zi}=mM&*kUKSeuw{shrnGJf=R?Rex945r3&%nuI=%WXhruw!HORg-^F)#;-<>aD9*0 z1awg<{Lt_56*kablhwG7>x)Ipp}(fo1&qOw$(rH-uY|dBq9UlON)=*A+eAu1ZK+^GSE*wqgd1?2A)CiO z0|RUfJO)!A02T%wq(j61Ut_D5JhSxP$i6vWj!*vcUoS_b@JD3sQbe9$$0qW&wpM%7 zS(U$&$;5F0HgTPv_by&t>(|FyC)Lh}-<6klynvnSok)cIi3uVR2cN5=L^A;7tRuh3 z3(g91d6Apv4KKwz1MGe-W zmZ_A-I@vn)AT?L#bjq_jACl+jWZ!u@XMyu{J|fT2`8egV&PBx3iPJ(S>^JMDIYPs; zI-fEhi+)zICw@L7jL1vI=l2L%e?H}I#^(iaXM_3WjL*->%~j6$TuFIJ&Tx+FhM$6KRtKJp zboXfFHS5wJwD-NAMp=Agc`Uy0e62UpEMvQ@1J(iSfOWt+U>&dySO=^F)&c9l|KPwf zn&dcK_d06S4~3)XcA)g|Pz9b2KkXvs7~1spAn=yIsc~BkLjWv}-8(A8lqSMa{zntH Nds@jDpXg5h_7*v!siXh^ literal 0 HcmV?d00001 diff --git a/unity/Sandbox35/ProjectSettings/TimeManager.asset b/unity/Sandbox35/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..a686ed5b2536dda0f5ac69a3db14d9e4964849be GIT binary patch literal 4112 zcmZQzVB}+95D;KsVBiPRK#GCERL?}uAkCQJ-~a#r85w~BtU$c@RmvB^9M=<_(`^;r zz8Aa#5_14zkUR*OGcYtjv_treK$&IC3=NwY85&rCLLhYz%*e11sFnxF2Z=KQF#`uk z4k9iM6=y~hH-U?5*=+2T?7O~n-md50s#tv3Lzsq$SAQ%GYHkv2p3yytrdJy&<5LEk(R#oKP*Z+X~mgx(+uyu9Yivm=-U6EB}v sTv7S;jW+CR9k32q2do3u0qcNuz&cT)y<<{oLcPAHHq;`qF#*^V3D${HdN);DWY1sy+&;x(tzL zLeN9beaRg24hI_Y!B6Nhkp~zWexG#~cnW=JQ3c)+*LZ{g-@#af;2wQvHqUF2yAxc8 zN6(mVaA3Zx;ewza@Ekh3xu?(n>hEE^o&H{M9k%|yh6}pGV+8c~b6@XYfA>Yr4>a7f z&UKKv`EJ)b7gwwPZr3^&N@(`ev3x!P{Sfa2MLa~nd#--7pLSi2fpcS@t-2fs42{l& zhX|Ytb(@{5t#cBb+f3)39uu9?^e>;){WN%Jc)RX%;1#&-&l$$s`7;l$!}jNF!#h^p z&oMW3xAo5>KZKU;{{?Uzw*ErRSJOmIma;UJv09c&CFy!eo3B=6sUBs0Sr6~MmZ@4T zM)j2Q2gy3-OGQ);pUXTeu(Bo4tk55LIxga2RJKzzzney*iAv(KwekV)D2YbN8~G$% zR#BnGxjun;@V3#`IPkkKiuzXubj>;79B>Xe2b=@W0q1~oz&YR?_%9u}#itr7m6x}J rAeY79io^}2^y5)B?)zh0YI=P?&NhQ6PXhBYh;dnwWn&2LMRofFX=~JD literal 0 HcmV?d00001 From 0b36df9f3d906bd6d981e97dae4d4acaed191c7e Mon Sep 17 00:00:00 2001 From: Alexander Bogarsukov Date: Thu, 27 Sep 2018 21:36:52 +0300 Subject: [PATCH 57/57] CHANGELOG update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31cafd5..c9f842b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). ----------------------- -## [0.9.7] - unreleased +## [0.9.7] - 2018.09.27 ### Added - Added convenience overloads for `SetException`-like methods accepting as error message string.