ToAsyncLazy

master
neuecc 2020-05-05 04:17:08 +09:00
parent b8d1a09224
commit 75f0bd26e7
3 changed files with 71 additions and 0 deletions

View File

@ -6,6 +6,62 @@ using System.Threading;
namespace UniRx.Async namespace UniRx.Async
{ {
public class AsyncLazy
{
Func<UniTask> valueFactory;
UniTask target;
object syncLock;
bool initialized;
public AsyncLazy(Func<UniTask> valueFactory)
{
this.valueFactory = valueFactory;
this.target = default;
this.syncLock = new object();
this.initialized = false;
}
internal AsyncLazy(UniTask value)
{
this.valueFactory = null;
this.target = value;
this.syncLock = null;
this.initialized = true;
}
public UniTask Task => EnsureInitialized();
public UniTask.Awaiter GetAwaiter() => EnsureInitialized().GetAwaiter();
UniTask EnsureInitialized()
{
if (Volatile.Read(ref initialized))
{
return target;
}
return EnsureInitializedCore();
}
UniTask EnsureInitializedCore()
{
lock (syncLock)
{
if (!Volatile.Read(ref initialized))
{
var f = Interlocked.Exchange(ref valueFactory, null);
if (f != null)
{
target = f().Preserve(); // with preserve(allow multiple await).
Volatile.Write(ref initialized, true);
}
}
}
return target;
}
}
public class AsyncLazy<T> public class AsyncLazy<T>
{ {
Func<UniTask<T>> valueFactory; Func<UniTask<T>> valueFactory;

View File

@ -93,6 +93,11 @@ namespace UniRx.Async
return factory(); return factory();
} }
public static AsyncLazy Lazy(Func<UniTask> factory)
{
return new AsyncLazy(factory);
}
public static AsyncLazy<T> Lazy<T>(Func<UniTask<T>> factory) public static AsyncLazy<T> Lazy<T>(Func<UniTask<T>> factory)
{ {
return new AsyncLazy<T>(factory); return new AsyncLazy<T>(factory);

View File

@ -180,6 +180,16 @@ namespace UniRx.Async
} }
} }
public static AsyncLazy ToAsyncLazy(this UniTask task)
{
return new AsyncLazy(task.Preserve()); // require Preserve
}
public static AsyncLazy<T> ToAsyncLazy<T>(this UniTask<T> task)
{
return new AsyncLazy<T>(task.Preserve()); // require Preserve
}
public static IEnumerator ToCoroutine<T>(this UniTask<T> task, Action<T> resultHandler = null, Action<Exception> exceptionHandler = null) public static IEnumerator ToCoroutine<T>(this UniTask<T> task, Action<T> resultHandler = null, Action<Exception> exceptionHandler = null)
{ {
return new ToCoroutineEnumerator<T>(task, resultHandler, exceptionHandler); return new ToCoroutineEnumerator<T>(task, resultHandler, exceptionHandler);