Skip to content

Commit

Permalink
Merge pull request #679 from left-/feature/task-async-startable
Browse files Browse the repository at this point in the history
Make IAsyncStartable available on Unity 2021.3 using System.Threading.Tasks.Task
  • Loading branch information
hadashiA authored Jun 16, 2024
2 parents 85d48af + 5dfea44 commit 5ec983c
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 45 deletions.
21 changes: 20 additions & 1 deletion VContainer/Assets/Tests/Unity/EntryPointTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,24 @@ public IEnumerator FromParent_LifetimeScoped()
Assert.That(childEntryPoint.InitializeCalled, Is.EqualTo(1));
Assert.That(childEntryPoint.StartCalled, Is.EqualTo(1));
}

#if UNITY_2021_3_OR_NEWER
[UnityTest]
public IEnumerator AsyncStartableExceptionHandler()
{
var handled = 0;

LifetimeScope.Create(builder =>
{
builder.RegisterEntryPoint<AsyncStartableThrowable>();
builder.RegisterEntryPointExceptionHandler(_ => { handled += 1; });
});

yield return null;
yield return null;

Assert.That(handled, Is.EqualTo(1));
}
#endif
}
}
}
14 changes: 14 additions & 0 deletions VContainer/Assets/Tests/Unity/Fixtures/SampleEntryPoint.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
using System.Threading;
using VContainer.Unity;
#if UNITY_2023_1_OR_NEWER
using UnityEngine;
#else
using Awaitable = System.Threading.Tasks.Task;
#endif

namespace VContainer.Tests.Unity
{
Expand Down Expand Up @@ -151,4 +157,12 @@ public void PostLateTick()
throw new System.NotImplementedException();
}
}

#if UNITY_2021_3_OR_NEWER
public class AsyncStartableThrowable : IAsyncStartable
{
public Awaitable StartAsync(CancellationToken cancellation)
=> throw new System.NotImplementedException();
}
#endif
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright (c) 2024 left (https://github.com/left-/)
// Copyright (c) 2020 hadashiA
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#if UNITY_2021_3_OR_NEWER
using System;
#if UNITY_2023_1_OR_NEWER
using UnityEngine;
#else
using Awaitable = System.Threading.Tasks.Task;
#endif

namespace VContainer.Unity
{
internal static class AwaitableExtensions
{
public static async Awaitable Forget(this Awaitable awaitable,
EntryPointExceptionHandler exceptionHandler = null)
{
try
{
await awaitable;
}
catch (Exception ex)
{
if (exceptionHandler != null)
exceptionHandler.Publish(ex);
else
throw;
}
}
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,46 +1,16 @@
#if VCONTAINER_UNITASK_INTEGRATION
using System.Threading;
using Cysharp.Threading.Tasks;

namespace VContainer.Unity
{
public interface IAsyncStartable
{
UniTask StartAsync(CancellationToken cancellation);
}
}
#elif UNITY_2023_1_OR_NEWER
using System;
using System.Threading;
#if UNITY_2023_1_OR_NEWER
using UnityEngine;
#elif VCONTAINER_UNITASK_INTEGRATION
using Awaitable = Cysharp.Threading.Tasks.UniTask;
#else
using Awaitable = System.Threading.Tasks.Task;
#endif

namespace VContainer.Unity
{
public interface IAsyncStartable
{
Awaitable StartAsync(CancellationToken cancellation);
}

static class AwaitableHelper
{
public static async Awaitable Forget(Awaitable awaitable, EntryPointExceptionHandler exceptionHandler)
{
try
{
await awaitable;
}
catch (Exception ex)
{
if (exceptionHandler != null)
{
exceptionHandler.Publish(ex);
}
else
{
throw;
}
}
}
Awaitable StartAsync(CancellationToken cancellation = default);
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public void Dispatch()
PlayerLoopHelper.Dispatch(PlayerLoopTiming.PostLateUpdate, loopItem);
}

#if VCONTAINER_UNITASK_INTEGRATION
#if VCONTAINER_UNITASK_INTEGRATION || UNITY_2021_3_OR_NEWER
var asyncStartables = container.Resolve<ContainerLocal<IReadOnlyList<IAsyncStartable>>>().Value;
if (asyncStartables.Count > 0)
{
Expand All @@ -143,4 +143,4 @@ public void Dispatch()

public void Dispose() => disposable.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ static LifetimeScope Find(Type type, Scene scene)

static LifetimeScope Find(Type type)
{
#if UNITY_2020_4_OR_NEWER || UNITY_2021_4_OR_NEWER || UNITY_2022_3_OR_NEWER || UNITY_2023_1_OR_NEWER
#if UNITY_2020_4_OR_NEWER || UNITY_2021_4_OR_NEWER || UNITY_2022_3_OR_NEWER || UNITY_2021_3_OR_NEWER
return (LifetimeScope)FindAnyObjectByType(type);
#else
return (LifetimeScope)FindObjectOfType(type);
Expand Down
20 changes: 17 additions & 3 deletions VContainer/Assets/VContainer/Runtime/Unity/PlayerLoopItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public bool MoveNext()
public void Dispose() => disposed = true;
}

#if VCONTAINER_UNITASK_INTEGRATION || UNITY_2023_1_OR_NEWER
#if VCONTAINER_UNITASK_INTEGRATION || UNITY_2021_3_OR_NEWER
sealed class AsyncStartableLoopItem : IPlayerLoopItem, IDisposable
{
readonly IEnumerable<IAsyncStartable> entries;
Expand All @@ -308,19 +308,33 @@ public bool MoveNext()
if (disposed) return false;
foreach (var x in entries)
{
var task = x.StartAsync(cts.Token);
#if VCONTAINER_UNITASK_INTEGRATION
var task = x.StartAsync(cts.Token);
if (exceptionHandler != null)
task.Forget(ex => exceptionHandler.Publish(ex));
else
task.Forget();
#else
var _ = AwaitableHelper.Forget(task, exceptionHandler);
InvokeStartAsync(x);
#endif
}
return false;
}

private void InvokeStartAsync(IAsyncStartable x)
{
try
{
var task = x.StartAsync(cts.Token);
_ = task.Forget(exceptionHandler);
}
catch (Exception ex)
{
if (exceptionHandler == null) throw;
exceptionHandler.Publish(ex);
}
}

public void Dispose()
{
lock (entries)
Expand Down
2 changes: 1 addition & 1 deletion VContainer/Assets/VContainer/Runtime/VContainer.asmdef
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "VContainer",
"rootNamespace": "",
"rootNamespace": "VContainer",
"references": [
"Unity.Collections",
"Unity.Entities",
Expand Down

0 comments on commit 5ec983c

Please sign in to comment.