Skip to content

Commit

Permalink
Remove AwakeMonitor
Browse files Browse the repository at this point in the history
Awake monitor is only necessary for UniTask due to how
Unity Monobehaviours functioned. Specifically,
MonoBehaviours would not call OnDestroy if they
were not awaked first. Therefore UniTask had to rely
on checking if the MonoBehaviour was set to null to
detect if the MonoBehavior was destroyed.

However in Godot, Predelete is always called when a node is freed, so there's
no need to handle any edge cases.

See Cysharp/UniTask#435 the use of AwakeMonitor in UniTask.
  • Loading branch information
Atlinx committed Mar 28, 2024
1 parent 8e15e47 commit 116a3d8
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 101 deletions.
34 changes: 4 additions & 30 deletions addons/GDTask/Triggers/AsyncDestroyTrigger.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Threading;
using Godot;
using Godot;
using System.Threading;

namespace Fractural.Tasks.Triggers
{
Expand All @@ -13,7 +13,7 @@ public static AsyncDestroyTrigger GetAsyncDestroyTrigger(this Node node)

public sealed partial class AsyncDestroyTrigger : Node
{
bool awakeCalled = false;
bool enterTreeCalled = false;
bool called = false;
CancellationTokenSource cancellationTokenSource;

Expand All @@ -26,18 +26,13 @@ public CancellationToken CancellationToken
cancellationTokenSource = new CancellationTokenSource();
}

if (!awakeCalled)
{
GDTaskPlayerLoopAutoload.AddAction(PlayerLoopTiming.Process, new AwakeMonitor(this));
}

return cancellationTokenSource.Token;
}
}

public override void _EnterTree()
{
awakeCalled = true;
enterTreeCalled = true;
}

public override void _Notification(int what)
Expand Down Expand Up @@ -69,27 +64,6 @@ public GDTask OnDestroyAsync()

return tcs.Task;
}

class AwakeMonitor : IPlayerLoopItem
{
readonly AsyncDestroyTrigger trigger;

public AwakeMonitor(AsyncDestroyTrigger trigger)
{
this.trigger = trigger;
}

public bool MoveNext()
{
if (trigger.called) return false;
if (trigger == null)
{
trigger.OnDestroy();
return false;
}
return true;
}
}
}
}

7 changes: 3 additions & 4 deletions addons/GDTask/Triggers/AsyncEnterTreeTrigger.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System.Threading;
using Godot;
using Godot;

namespace Fractural.Tasks.Triggers
{
public static partial class AsyncTriggerExtensions
{
public static AsyncEnterTreeTrigger GetAsyncAwakeTrigger(this Node node)
public static AsyncEnterTreeTrigger GetAsyncEnterTreeTrigger(this Node node)
{
return node.GetOrAddImmediateChild<AsyncEnterTreeTrigger>();
}
Expand All @@ -19,7 +18,7 @@ public override void _EnterTree()
RaiseEvent(AsyncUnit.Default);
}

public GDTask AwakeAsync()
public GDTask EnterTreeAsync()
{
if (calledEnterTree) return GDTask.CompletedTask;

Expand Down
4 changes: 2 additions & 2 deletions addons/GDTask/Triggers/AsyncReadyTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Fractural.Tasks.Triggers
{
public static partial class AsyncTriggerExtensions
{
public static AsyncReadyTrigger GetAsyncStartTrigger(this Node node)
public static AsyncReadyTrigger GetAsyncReadyTrigger(this Node node)
{
return node.GetOrAddImmediateChild<AsyncReadyTrigger>();
}
Expand All @@ -21,7 +21,7 @@ public override void _Ready()
RaiseEvent(AsyncUnit.Default);
}

public GDTask StartAsync()
public GDTask ReadyAsync()
{
if (called) return GDTask.CompletedTask;

Expand Down
35 changes: 2 additions & 33 deletions addons/GDTask/Triggers/AsyncTriggerBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using Godot;
using System;
using System.Threading;
using Godot;

namespace Fractural.Tasks.Triggers
{
Expand Down Expand Up @@ -32,49 +32,18 @@ void OnDestroy()

internal void AddHandler(ITriggerHandler<T> handler)
{
if (!calledEnterTree)
{
GDTaskPlayerLoopAutoload.AddAction(PlayerLoopTiming.Process, new AwakeMonitor(this));
}

triggerEvent.Add(handler);
}

internal void RemoveHandler(ITriggerHandler<T> handler)
{
if (!calledEnterTree)
{
GDTaskPlayerLoopAutoload.AddAction(PlayerLoopTiming.Process, new AwakeMonitor(this));
}

triggerEvent.Remove(handler);
}

protected void RaiseEvent(T value)
{
triggerEvent.SetResult(value);
}

class AwakeMonitor : IPlayerLoopItem
{
readonly AsyncTriggerBase<T> trigger;

public AwakeMonitor(AsyncTriggerBase<T> trigger)
{
this.trigger = trigger;
}

public bool MoveNext()
{
if (trigger.calledEnterTree) return false;
if (trigger == null)
{
trigger.OnDestroy();
return false;
}
return true;
}
}
}

public interface IAsyncOneShotTrigger
Expand Down
64 changes: 32 additions & 32 deletions addons/GDTask/Triggers/AsyncTriggerExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Threading;
using Fractural.Tasks.Triggers;
using Fractural.Tasks.Triggers;
using Godot;
using System;
using System.Threading;

namespace Fractural.Tasks
{
Expand All @@ -20,48 +20,48 @@ namespace Fractural.Tasks.Triggers
public static partial class AsyncTriggerExtensions
{
// Special for single operation.
public static T GetImmediateChild<T>(this Node node, bool includeRoot = true)
{
if (node == null) throw new ArgumentNullException(nameof(node));
if (includeRoot && node is T castedRoot)
return castedRoot;
else
{
foreach (Node child in node.GetChildren())
if (child is T castedChild) return castedChild;
}
return default(T);
}
public static T GetImmediateChild<T>(this Node node, bool includeRoot = true)
{
if (node == null) throw new ArgumentNullException(nameof(node));
if (includeRoot && node is T castedRoot)
return castedRoot;
else
{
foreach (Node child in node.GetChildren())
if (child is T castedChild) return castedChild;
}
return default(T);
}

public static T AddImmediateChild<T>(this Node node) where T : Node, new()
{
T child = new T();
node.AddChild(child);
return child;
}
public static T AddImmediateChild<T>(this Node node) where T : Node, new()
{
T child = new T();
node.AddChild(child);
return child;
}

public static T GetOrAddImmediateChild<T>(this Node node) where T : Node, new()
{
T child = GetImmediateChild<T>(node);
if (child == null)
child = AddImmediateChild<T>(node);
return child;
}
public static T GetOrAddImmediateChild<T>(this Node node) where T : Node, new()
{
T child = GetImmediateChild<T>(node);
if (child == null)
child = AddImmediateChild<T>(node);
return child;
}

/// <summary>This function is called when the Node will be destroyed.</summary>
public static GDTask OnDestroyAsync(this Node node)
{
return node.GetAsyncDestroyTrigger().OnDestroyAsync();
}

public static GDTask StartAsync(this Node node)
public static GDTask ReadyAsync(this Node node)
{
return node.GetAsyncStartTrigger().StartAsync();
return node.GetAsyncReadyTrigger().ReadyAsync();
}

public static GDTask AwakeAsync(this Node node)
public static GDTask EnterTreeAsync(this Node node)
{
return node.GetAsyncAwakeTrigger().AwakeAsync();
return node.GetAsyncEnterTreeTrigger().EnterTreeAsync();
}
}
}
Expand Down

0 comments on commit 116a3d8

Please sign in to comment.