Add support for user tasks, deprecate native task:await()

This commit is contained in:
Alessandro Proto 2023-03-15 21:29:33 +01:00
parent b2e7969793
commit a84aedbe38
2 changed files with 112 additions and 3 deletions

View file

@ -14,6 +14,7 @@
// limitations under the License.
using Capy64.API;
using Capy64.Runtime.Objects;
using KeraLua;
using System;
@ -26,6 +27,8 @@ public class Event : IComponent
private static Lua UserQueue;
private static bool FrozenTaskAwaiter = false;
private static IGame _game;
public Event(IGame game)
{
@ -49,15 +52,36 @@ public class Event : IComponent
name = "push",
function = L_Push,
},
new()
{
name = "setAwaiter",
function = L_SetTaskAwaiter,
},
new()
{
name = "fulfill",
function = L_Fulfill,
},
new()
{
name = "reject",
function = L_Reject,
},
new()
{
name = "newTask",
function = L_NewTask,
},
new(),
};
public void LuaInit(Lua L)
{
PushQueue = 0;
UserQueue = _game.LuaRuntime.Parent.NewThread();
FrozenTaskAwaiter = false;
L.RequireF("event", OpenLib, false);
}
@ -140,4 +164,86 @@ public class Event : IComponent
return 0;
}
private static int L_SetTaskAwaiter(IntPtr state)
{
var L = Lua.FromIntPtr(state);
L.CheckType(1, LuaType.Function);
if (FrozenTaskAwaiter)
{
L.Error("awaiter is frozen");
}
FrozenTaskAwaiter = L.ToBoolean(2);
L.GetMetaTable(TaskMeta.ObjectType);
L.GetField(-1, "__index");
L.Rotate(1, -1);
L.SetField(-2, "await");
L.Pop(2);
return 0;
}
private static int L_Fulfill(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var task = TaskMeta.CheckTask(L, false);
L.CheckAny(2);
if(!task.UserTask)
{
L.Error("attempt to fulfill machine task");
}
if (task.Status != TaskMeta.TaskStatus.Running)
{
L.Error("attempt to fulfill a finished task");
}
task.Fulfill(lk =>
{
L.XMove(lk, 1);
});
return 0;
}
private static int L_Reject(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var task = TaskMeta.CheckTask(L, false);
var error = L.CheckString(2);
if (!task.UserTask)
{
L.Error("attempt to reject machine task");
}
if(task.Status != TaskMeta.TaskStatus.Running)
{
L.Error("attempt to reject a finished task");
}
task.Reject(error);
return 0;
}
private static int L_NewTask(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var name = L.OptString(1, "object");
var task = TaskMeta.Push(L, name);
task.UserTask = true;
return 1;
}
}

View file

@ -56,6 +56,7 @@ public class TaskMeta : IComponent
public TaskStatus Status { get; set; } = TaskStatus.Running;
public string Error { get; private set; }
public int DataIndex { get; private set; } = 0;
public bool UserTask { get; set; } = false;
public void Fulfill(Action<Lua> lk)
{
@ -191,12 +192,12 @@ public class TaskMeta : IComponent
return task;
}
private static RuntimeTask ToTask(Lua L, bool gc = false)
public static RuntimeTask ToTask(Lua L, bool gc = false)
{
return ObjectManager.ToObject<RuntimeTask>(L, 1, gc);
}
private static RuntimeTask CheckTask(Lua L, bool gc = false)
public static RuntimeTask CheckTask(Lua L, bool gc = false)
{
var obj = ObjectManager.CheckObject<RuntimeTask>(L, 1, ObjectType, gc);
if (obj is null)
@ -218,6 +219,8 @@ public class TaskMeta : IComponent
{
var L = Lua.FromIntPtr(state);
L.Warning("Native task awaiter should be avoided", false);
var task = CheckTask(L, false);
if (task.Status == TaskStatus.Succeeded)