mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-02-18 07:32:30 +00:00
Add Task object for async functions
This commit is contained in:
parent
7fff12c9ac
commit
f9aeb9f793
6 changed files with 436 additions and 63 deletions
|
@ -62,13 +62,14 @@ local function drawVendorImage()
|
||||||
|
|
||||||
local w, h = gpu.getSize()
|
local w, h = gpu.getSize()
|
||||||
local ok, err = pcall(function()
|
local ok, err = pcall(function()
|
||||||
local buffer<close>, width, height = gpu.loadImage("/boot/vendor.bmp")
|
local task<close> = gpu.loadImageAsync("/boot/vendor.bmp")
|
||||||
|
local buffer<close> = task:await()
|
||||||
|
|
||||||
local x, y =
|
local x, y =
|
||||||
math.ceil((w / 2) - (width / 2)),
|
math.ceil((w / 2) - (buffer.width / 2)),
|
||||||
math.ceil((h / 2) - (height / 2))
|
math.ceil((h / 2) - (buffer.height / 2))
|
||||||
|
|
||||||
gpu.drawBuffer(buffer, x, y, width, height)
|
gpu.drawBuffer(buffer, x, y)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class Event : IComponent
|
||||||
return nargs;
|
return nargs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int L_Pull(IntPtr state)
|
public static int L_Pull(IntPtr state)
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ using Microsoft.Xna.Framework.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Libraries;
|
namespace Capy64.Runtime.Libraries;
|
||||||
|
|
||||||
|
@ -123,8 +124,8 @@ public class GPU : IComponent
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
name = "loadImage",
|
name = "loadImageAsync",
|
||||||
function = L_LoadImage,
|
function = L_LoadImageAsync,
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
|
@ -412,7 +413,7 @@ public class GPU : IComponent
|
||||||
_game.Drawing.Canvas.GetData(buffer);
|
_game.Drawing.Canvas.GetData(buffer);
|
||||||
|
|
||||||
ObjectManager.PushObject(L, buffer);
|
ObjectManager.PushObject(L, buffer);
|
||||||
L.SetMetaTable(GPUBuffer.ObjectType);
|
L.SetMetaTable(GPUBufferMeta.ObjectType);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -421,9 +422,9 @@ public class GPU : IComponent
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
var buffer = GPUBuffer.CheckBuffer(L, false);
|
var buffer = GPUBufferMeta.CheckBuffer(L, false);
|
||||||
|
|
||||||
_game.Drawing.Canvas.SetData(buffer);
|
_game.Drawing.Canvas.SetData(buffer.Buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -438,7 +439,7 @@ public class GPU : IComponent
|
||||||
var buffer = new uint[width * height];
|
var buffer = new uint[width * height];
|
||||||
|
|
||||||
ObjectManager.PushObject(L, buffer);
|
ObjectManager.PushObject(L, buffer);
|
||||||
L.SetMetaTable(GPUBuffer.ObjectType);
|
L.SetMetaTable(GPUBufferMeta.ObjectType);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -447,30 +448,23 @@ public class GPU : IComponent
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
var buffer = GPUBuffer.CheckBuffer(L, false);
|
var buffer = GPUBufferMeta.CheckBuffer(L, false);
|
||||||
|
|
||||||
var x = (int)L.CheckInteger(2) - 1;
|
var x = (int)L.CheckInteger(2) - 1;
|
||||||
var y = (int)L.CheckInteger(3) - 1;
|
var y = (int)L.CheckInteger(3) - 1;
|
||||||
var w = (int)L.CheckInteger(4);
|
|
||||||
var h = (int)L.CheckInteger(5);
|
|
||||||
|
|
||||||
if (w * h != buffer.Length)
|
_game.Drawing.DrawBuffer(buffer.Buffer, new()
|
||||||
{
|
|
||||||
L.Error("width and height do not match buffer size");
|
|
||||||
}
|
|
||||||
|
|
||||||
_game.Drawing.DrawBuffer(buffer, new()
|
|
||||||
{
|
{
|
||||||
X = x,
|
X = x,
|
||||||
Y = y,
|
Y = y,
|
||||||
Width = w,
|
Width = buffer.Width,
|
||||||
Height = h,
|
Height = buffer.Height,
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int L_LoadImage(IntPtr state)
|
private static int L_LoadImageAsync(IntPtr state)
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
@ -484,6 +478,8 @@ public class GPU : IComponent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var task = TaskMeta.Push(L, GPUBufferMeta.ObjectType);
|
||||||
|
|
||||||
Texture2D texture;
|
Texture2D texture;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -491,44 +487,52 @@ public class GPU : IComponent
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
L.Error(e.Message);
|
task.Reject(e.Message);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = new uint[texture.Width * texture.Height];
|
var data = new uint[texture.Width * texture.Height];
|
||||||
texture.GetData(data);
|
texture.GetData(data);
|
||||||
|
|
||||||
if (_game.EngineMode == EngineMode.Classic)
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.Length; i++)
|
if (_game.EngineMode == EngineMode.Classic)
|
||||||
{
|
{
|
||||||
var value = data[i];
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
var value = data[i];
|
||||||
|
|
||||||
// ABGR to RGB
|
// ABGR to RGB
|
||||||
value =
|
value =
|
||||||
((value & 0x00_00_00_FFU) << 16) | // move R
|
((value & 0x00_00_00_FFU) << 16) | // move R
|
||||||
(value & 0x00_00_FF_00U) | // move G
|
(value & 0x00_00_FF_00U) | // move G
|
||||||
((value & 0x00_FF_00_00U) >> 16); // move B
|
((value & 0x00_FF_00_00U) >> 16); // move B
|
||||||
|
|
||||||
value = ColorPalette.GetColor(value);
|
value = ColorPalette.GetColor(value);
|
||||||
|
|
||||||
// RGB to ABGR
|
// RGB to ABGR
|
||||||
value =
|
value =
|
||||||
((value & 0x00_FF_00_00U) >> 16) | // move R
|
((value & 0x00_FF_00_00U) >> 16) | // move R
|
||||||
(value & 0x00_00_FF_00U) | // move G
|
(value & 0x00_00_FF_00U) | // move G
|
||||||
((value & 0x00_00_00_FFU) << 16) | // move B
|
((value & 0x00_00_00_FFU) << 16) | // move B
|
||||||
0xFF_00_00_00U;
|
0xFF_00_00_00U;
|
||||||
|
|
||||||
|
data[i] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ObjectManager.PushObject(L, data);
|
var buffer = new GPUBufferMeta.GPUBuffer
|
||||||
L.SetMetaTable(GPUBuffer.ObjectType);
|
{
|
||||||
L.PushInteger(texture.Width);
|
Buffer = data,
|
||||||
L.PushInteger(texture.Height);
|
Height = texture.Height,
|
||||||
|
Width = texture.Width,
|
||||||
|
};
|
||||||
|
task.Fulfill(buffer);
|
||||||
|
|
||||||
texture.Dispose();
|
texture.Dispose();
|
||||||
|
});
|
||||||
|
|
||||||
return 3;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int L_Clear(IntPtr state)
|
private static int L_Clear(IntPtr state)
|
||||||
|
|
|
@ -72,6 +72,11 @@ public class Machine : IComponent
|
||||||
name = "getClipboard",
|
name = "getClipboard",
|
||||||
function = L_GetClipboard,
|
function = L_GetClipboard,
|
||||||
},
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "task",
|
||||||
|
function = L_Task,
|
||||||
|
},
|
||||||
new(),
|
new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,6 +92,18 @@ public class Machine : IComponent
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int L_Task(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = new Objects.TaskMeta.RuntimeTask("test");
|
||||||
|
|
||||||
|
ObjectManager.PushObject(L, task);
|
||||||
|
L.SetMetaTable(Objects.TaskMeta.ObjectType);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
private static int L_Shutdown(IntPtr _)
|
private static int L_Shutdown(IntPtr _)
|
||||||
{
|
{
|
||||||
RuntimeManager.Shutdown();
|
RuntimeManager.Shutdown();
|
||||||
|
|
|
@ -20,10 +20,17 @@ using System;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Objects;
|
namespace Capy64.Runtime.Objects;
|
||||||
|
|
||||||
public class GPUBuffer : IComponent
|
public class GPUBufferMeta : IComponent
|
||||||
{
|
{
|
||||||
public const string ObjectType = "GPUBuffer";
|
public const string ObjectType = "GPUBuffer";
|
||||||
|
|
||||||
|
public struct GPUBuffer
|
||||||
|
{
|
||||||
|
public uint[] Buffer { get; set; }
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
private static LuaRegister[] MetaMethods = new LuaRegister[]
|
private static LuaRegister[] MetaMethods = new LuaRegister[]
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
|
@ -61,7 +68,8 @@ public class GPUBuffer : IComponent
|
||||||
};
|
};
|
||||||
|
|
||||||
private static IGame _game;
|
private static IGame _game;
|
||||||
public GPUBuffer(IGame game) {
|
public GPUBufferMeta(IGame game)
|
||||||
|
{
|
||||||
_game = game;
|
_game = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +80,7 @@ public class GPUBuffer : IComponent
|
||||||
|
|
||||||
public static uint GetColor(uint color)
|
public static uint GetColor(uint color)
|
||||||
{
|
{
|
||||||
if(_game.EngineMode == EngineMode.Classic)
|
if (_game.EngineMode == EngineMode.Classic)
|
||||||
return ColorPalette.GetColor(color);
|
return ColorPalette.GetColor(color);
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
|
@ -84,18 +92,18 @@ public class GPUBuffer : IComponent
|
||||||
L.SetFuncs(MetaMethods, 0);
|
L.SetFuncs(MetaMethods, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint[] ToBuffer(Lua L, bool gc = false)
|
public static GPUBuffer ToBuffer(Lua L, bool gc = false)
|
||||||
{
|
{
|
||||||
return ObjectManager.ToObject<uint[]>(L, 1, gc);
|
return ObjectManager.ToObject<GPUBuffer>(L, 1, gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint[] CheckBuffer(Lua L, bool gc = false)
|
public static GPUBuffer CheckBuffer(Lua L, bool gc = false)
|
||||||
{
|
{
|
||||||
var obj = ObjectManager.CheckObject<uint[]>(L, 1, ObjectType, gc);
|
var obj = ObjectManager.CheckObject<GPUBuffer>(L, 1, ObjectType, gc);
|
||||||
if (obj is null)
|
if (obj.Buffer is null)
|
||||||
{
|
{
|
||||||
L.Error("attempt to use a closed buffer");
|
L.Error("attempt to use a closed buffer");
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -108,19 +116,27 @@ public class GPUBuffer : IComponent
|
||||||
|
|
||||||
if (!L.IsInteger(2))
|
if (!L.IsInteger(2))
|
||||||
{
|
{
|
||||||
L.PushNil();
|
var vkey = L.ToString(2);
|
||||||
|
|
||||||
|
if (vkey == "width")
|
||||||
|
L.PushInteger(buffer.Width);
|
||||||
|
else if (vkey == "height")
|
||||||
|
L.PushInteger(buffer.Height);
|
||||||
|
else
|
||||||
|
L.PushNil();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = L.ToInteger(2);
|
var key = L.ToInteger(2);
|
||||||
|
|
||||||
if (key < 0 || key >= buffer.Length)
|
if (key < 0 || key >= buffer.Buffer.Length)
|
||||||
{
|
{
|
||||||
L.PushNil();
|
L.PushNil();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = buffer[key];
|
var value = buffer.Buffer[key];
|
||||||
|
|
||||||
// ABGR to RGB
|
// ABGR to RGB
|
||||||
value =
|
value =
|
||||||
|
@ -145,7 +161,7 @@ public class GPUBuffer : IComponent
|
||||||
|
|
||||||
var key = L.ToInteger(2);
|
var key = L.ToInteger(2);
|
||||||
|
|
||||||
if (key < 0 || key >= buffer.Length)
|
if (key < 0 || key >= buffer.Buffer.Length)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +182,7 @@ public class GPUBuffer : IComponent
|
||||||
0xFF_00_00_00U;
|
0xFF_00_00_00U;
|
||||||
|
|
||||||
|
|
||||||
buffer[key] = value;
|
buffer.Buffer[key] = value;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +202,7 @@ public class GPUBuffer : IComponent
|
||||||
|
|
||||||
var buffer = CheckBuffer(L, false);
|
var buffer = CheckBuffer(L, false);
|
||||||
|
|
||||||
L.PushInteger(buffer.LongLength);
|
L.PushInteger(buffer.Buffer.LongLength);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +211,7 @@ public class GPUBuffer : IComponent
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
var buffer = ToBuffer(L);
|
var buffer = ToBuffer(L);
|
||||||
if (buffer is not null)
|
if (buffer.Buffer is not null)
|
||||||
{
|
{
|
||||||
L.PushString("GPUBuffer ({0:X})", (ulong)&buffer);
|
L.PushString("GPUBuffer ({0:X})", (ulong)&buffer);
|
||||||
}
|
}
|
335
Capy64/Runtime/Objects/Task.cs
Normal file
335
Capy64/Runtime/Objects/Task.cs
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
// This file is part of Capy64 - https://github.com/Ale32bit/Capy64
|
||||||
|
// Copyright 2023 Alessandro "AlexDevs" Proto
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License").
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
using Capy64.API;
|
||||||
|
using Cyotek.Drawing.BitmapFont;
|
||||||
|
using KeraLua;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Capy64.Runtime.Objects;
|
||||||
|
|
||||||
|
public class TaskMeta : IComponent
|
||||||
|
{
|
||||||
|
private static IGame _game;
|
||||||
|
public TaskMeta(IGame game)
|
||||||
|
{
|
||||||
|
_game = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
public const string ObjectType = "Task";
|
||||||
|
|
||||||
|
public enum TaskStatus
|
||||||
|
{
|
||||||
|
Running,
|
||||||
|
Succeeded,
|
||||||
|
Failed,
|
||||||
|
}
|
||||||
|
public class RuntimeTask
|
||||||
|
{
|
||||||
|
public RuntimeTask(string typeName)
|
||||||
|
{
|
||||||
|
TypeName = typeName;
|
||||||
|
}
|
||||||
|
public Guid Guid { get; set; } = Guid.NewGuid();
|
||||||
|
public string TypeName { get; set; }
|
||||||
|
public TaskStatus Status { get; set; } = TaskStatus.Running;
|
||||||
|
public object Result { get; private set; }
|
||||||
|
public string Error { get; private set; }
|
||||||
|
|
||||||
|
public void Fulfill<T>(T obj)
|
||||||
|
{
|
||||||
|
Status = TaskStatus.Succeeded;
|
||||||
|
|
||||||
|
Result = obj;
|
||||||
|
|
||||||
|
_game.LuaRuntime.QueueEvent("task_finish", LK =>
|
||||||
|
{
|
||||||
|
LK.PushString(Guid.ToString());
|
||||||
|
|
||||||
|
ObjectManager.PushObject(LK, obj);
|
||||||
|
LK.SetMetaTable(TypeName);
|
||||||
|
|
||||||
|
LK.PushNil();
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fulfill(Action<Lua> lk)
|
||||||
|
{
|
||||||
|
Status = TaskStatus.Succeeded;
|
||||||
|
|
||||||
|
Result = lk;
|
||||||
|
|
||||||
|
_game.LuaRuntime.QueueEvent("task_finish", LK =>
|
||||||
|
{
|
||||||
|
LK.PushString(Guid.ToString());
|
||||||
|
|
||||||
|
lk(LK);
|
||||||
|
|
||||||
|
LK.PushNil();
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reject(string error, params object[] args)
|
||||||
|
{
|
||||||
|
Status = TaskStatus.Failed;
|
||||||
|
Error = string.Format(error, args);
|
||||||
|
|
||||||
|
_game.LuaRuntime.QueueEvent("task_finish", LK =>
|
||||||
|
{
|
||||||
|
LK.PushString(Guid.ToString());
|
||||||
|
|
||||||
|
LK.PushNil();
|
||||||
|
|
||||||
|
LK.PushString(Error);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LuaRegister[] Methods = new LuaRegister[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "await",
|
||||||
|
function = L_Await,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "getID",
|
||||||
|
function = L_GetID,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "getType",
|
||||||
|
function = L_GetType,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "getStatus",
|
||||||
|
function = L_GetStatus,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "getResult",
|
||||||
|
function = L_GetResult,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "getError",
|
||||||
|
function = L_GetResult,
|
||||||
|
},
|
||||||
|
new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static LuaRegister[] MetaMethods = new LuaRegister[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__index",
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__gc",
|
||||||
|
function = LM_GC,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__close",
|
||||||
|
function = LM_GC,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
name = "__tostring",
|
||||||
|
function = LM_ToString,
|
||||||
|
},
|
||||||
|
|
||||||
|
new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
public void LuaInit(Lua L)
|
||||||
|
{
|
||||||
|
CreateMeta(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateMeta(Lua L)
|
||||||
|
{
|
||||||
|
L.NewMetaTable(ObjectType);
|
||||||
|
L.SetFuncs(MetaMethods, 0);
|
||||||
|
L.NewLibTable(Methods);
|
||||||
|
L.SetFuncs(Methods, 0);
|
||||||
|
L.SetField(-2, "__index");
|
||||||
|
L.Pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RuntimeTask Push(Lua L, string typeName)
|
||||||
|
{
|
||||||
|
var task = new RuntimeTask(typeName);
|
||||||
|
|
||||||
|
ObjectManager.PushObject(L, task);
|
||||||
|
L.SetMetaTable(ObjectType);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RuntimeTask ToTask(Lua L, bool gc = false)
|
||||||
|
{
|
||||||
|
return ObjectManager.ToObject<RuntimeTask>(L, 1, gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RuntimeTask CheckTask(Lua L, bool gc = false)
|
||||||
|
{
|
||||||
|
var obj = ObjectManager.CheckObject<RuntimeTask>(L, 1, ObjectType, gc);
|
||||||
|
if (obj is null)
|
||||||
|
{
|
||||||
|
L.Error("attempt to use a closed file");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WaitForTask(Lua L)
|
||||||
|
{
|
||||||
|
L.PushCFunction(Libraries.Event.L_Pull);
|
||||||
|
L.PushString("task_finish");
|
||||||
|
L.CallK(1, 4, 0, LK_Await);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_Await(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
WaitForTask(L);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LK_Await(IntPtr state, int status, nint ctx)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
var taskId = L.CheckString(3);
|
||||||
|
|
||||||
|
if (task.Guid.ToString() != taskId)
|
||||||
|
{
|
||||||
|
WaitForTask(L);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_GetID(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
|
L.PushString(task.Guid.ToString());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_GetType(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
|
L.PushString(task.TypeName);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_GetStatus(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
|
L.PushString(task.Status.ToString().ToLower());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_GetResult(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
|
if (task.Status == TaskStatus.Succeeded)
|
||||||
|
{
|
||||||
|
if (task.Result is Action<Lua> lk)
|
||||||
|
{
|
||||||
|
// todo: make use of first-generated data
|
||||||
|
lk(L);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ObjectManager.PushObject(L, task.Result);
|
||||||
|
L.SetMetaTable(task.TypeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L.PushNil();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int L_GetError(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
|
if (task.Status == TaskStatus.Failed)
|
||||||
|
{
|
||||||
|
L.PushString(task.Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L.PushNil();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LM_GC(IntPtr state)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LM_ToString(IntPtr state)
|
||||||
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
var task = ToTask(L);
|
||||||
|
L.PushString("Task<{0}>: {1} ({2})", task?.TypeName, task?.Guid, task?.Status);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue