mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-18 18:46:43 +00:00
Fix tasks crashing memory and stuff
This commit is contained in:
parent
d137c46ed9
commit
9aadc35329
5 changed files with 74 additions and 68 deletions
|
@ -24,6 +24,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Libraries;
|
namespace Capy64.Runtime.Libraries;
|
||||||
|
|
||||||
|
@ -527,7 +528,12 @@ public class GPU : IComponent
|
||||||
Height = texture.Height,
|
Height = texture.Height,
|
||||||
Width = texture.Width,
|
Width = texture.Width,
|
||||||
};
|
};
|
||||||
task.Fulfill(buffer);
|
|
||||||
|
task.Fulfill(lk =>
|
||||||
|
{
|
||||||
|
ObjectManager.PushObject(lk, buffer);
|
||||||
|
lk.SetMetaTable(GPUBufferMeta.ObjectType);
|
||||||
|
});
|
||||||
|
|
||||||
texture.Dispose();
|
texture.Dispose();
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,6 +25,7 @@ using System.Net.Http;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Capy64.Runtime.Libraries;
|
namespace Capy64.Runtime.Libraries;
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
@ -198,19 +199,15 @@ public class HTTP : IComponent
|
||||||
|
|
||||||
var requestId = _requestId++;
|
var requestId = _requestId++;
|
||||||
|
|
||||||
|
var luaTask = TaskMeta.Push(L, "HTTPRequest");
|
||||||
|
|
||||||
var reqTask = _httpClient.SendAsync(request);
|
var reqTask = _httpClient.SendAsync(request);
|
||||||
reqTask.ContinueWith(async (task) =>
|
reqTask.ContinueWith(async (task) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
if (task.IsFaulted || task.IsCanceled)
|
if (task.IsFaulted || task.IsCanceled)
|
||||||
{
|
{
|
||||||
_game.LuaRuntime.QueueEvent("http_failure", LK =>
|
luaTask.Reject(task.Exception?.Message);
|
||||||
{
|
|
||||||
LK.PushInteger(requestId);
|
|
||||||
LK.PushString(task.Exception?.Message);
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,23 +215,15 @@ public class HTTP : IComponent
|
||||||
|
|
||||||
var stream = await response.Content.ReadAsStreamAsync();
|
var stream = await response.Content.ReadAsStreamAsync();
|
||||||
|
|
||||||
_game.LuaRuntime.QueueEvent("http_response", LK =>
|
luaTask.Fulfill(LK =>
|
||||||
{
|
{
|
||||||
// arg 1, request id
|
|
||||||
LK.PushInteger(requestId);
|
|
||||||
|
|
||||||
// arg 2, response data
|
|
||||||
ObjectManager.PushObject(L, stream);
|
|
||||||
//L.PushObject(stream);
|
|
||||||
L.SetMetaTable(FileHandle.ObjectType);
|
|
||||||
/*if ((bool)options["binary"])
|
|
||||||
BinaryReadHandle.Push(LK, new(stream));
|
|
||||||
else
|
|
||||||
ReadHandle.Push(LK, new(stream));*/
|
|
||||||
|
|
||||||
// arg 3, response info
|
|
||||||
LK.NewTable();
|
LK.NewTable();
|
||||||
|
|
||||||
|
LK.PushString("content");
|
||||||
|
ObjectManager.PushObject(LK, stream);
|
||||||
|
LK.SetMetaTable(FileHandle.ObjectType);
|
||||||
|
LK.SetTable(-3);
|
||||||
|
|
||||||
LK.PushString("success");
|
LK.PushString("success");
|
||||||
LK.PushBoolean(response.IsSuccessStatusCode);
|
LK.PushBoolean(response.IsSuccessStatusCode);
|
||||||
LK.SetTable(-3);
|
LK.SetTable(-3);
|
||||||
|
@ -258,15 +247,9 @@ public class HTTP : IComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
LK.SetTable(-3);
|
LK.SetTable(-3);
|
||||||
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
L.PushInteger(requestId);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Capy64.Runtime;
|
||||||
public class LuaState : IDisposable
|
public class LuaState : IDisposable
|
||||||
{
|
{
|
||||||
public Lua Thread;
|
public Lua Thread;
|
||||||
private readonly Lua _parent;
|
public readonly Lua Parent;
|
||||||
|
|
||||||
private readonly ConcurrentQueue<LuaEvent> _queue = new();
|
private readonly ConcurrentQueue<LuaEvent> _queue = new();
|
||||||
|
|
||||||
|
@ -36,25 +36,21 @@ public class LuaState : IDisposable
|
||||||
|
|
||||||
public LuaState()
|
public LuaState()
|
||||||
{
|
{
|
||||||
_parent = new Lua(false)
|
Parent = new Lua(false)
|
||||||
{
|
{
|
||||||
Encoding = Encoding.UTF8,
|
Encoding = Encoding.UTF8,
|
||||||
};
|
};
|
||||||
|
|
||||||
Sandbox.OpenLibraries(_parent);
|
Sandbox.OpenLibraries(Parent);
|
||||||
Sandbox.Patch(_parent);
|
Sandbox.Patch(Parent);
|
||||||
|
|
||||||
Thread = _parent.NewThread();
|
Thread = Parent.NewThread();
|
||||||
|
|
||||||
Thread.SetHook(LH_YieldTimeout, LuaHookMask.Count, 7000);
|
Thread.SetHook(LH_YieldTimeout, LuaHookMask.Count, 7000);
|
||||||
yieldTimeoutTimer.Elapsed += (sender, ev) =>
|
yieldTimeoutTimer.Elapsed += (sender, ev) =>
|
||||||
{
|
{
|
||||||
yieldTimedOut = true;
|
yieldTimedOut = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
InitPlugins();
|
|
||||||
|
|
||||||
Thread.SetTop(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LH_YieldTimeout(IntPtr state, IntPtr ar)
|
private static void LH_YieldTimeout(IntPtr state, IntPtr ar)
|
||||||
|
@ -68,6 +64,13 @@ public class LuaState : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
InitPlugins();
|
||||||
|
|
||||||
|
Thread.SetTop(0);
|
||||||
|
}
|
||||||
|
|
||||||
private void InitPlugins()
|
private void InitPlugins()
|
||||||
{
|
{
|
||||||
var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
|
var allPlugins = new List<IComponent>(Capy64.Instance.NativePlugins);
|
||||||
|
@ -192,6 +195,6 @@ public class LuaState : IDisposable
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
_queue.Clear();
|
_queue.Clear();
|
||||||
Thread.Close();
|
Thread.Close();
|
||||||
_parent.Close();
|
Parent.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,19 +44,23 @@ public class TaskMeta : IComponent
|
||||||
}
|
}
|
||||||
public class RuntimeTask
|
public class RuntimeTask
|
||||||
{
|
{
|
||||||
public RuntimeTask(string typeName)
|
public RuntimeTask(string name)
|
||||||
{
|
{
|
||||||
TypeName = typeName;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RuntimeTask() { }
|
||||||
|
|
||||||
public Guid Guid { get; set; } = Guid.NewGuid();
|
public Guid Guid { get; set; } = Guid.NewGuid();
|
||||||
public string TypeName { get; set; }
|
public string Name { get; set; } = "object";
|
||||||
public TaskStatus Status { get; set; } = TaskStatus.Running;
|
public TaskStatus Status { get; set; } = TaskStatus.Running;
|
||||||
public object Result { get; private set; }
|
public object Result { get; private set; }
|
||||||
public string Error { get; private set; }
|
public string Error { get; private set; }
|
||||||
|
public int DataIndex { get; private set; } = 0;
|
||||||
|
|
||||||
public void Fulfill<T>(T obj)
|
public void Fulfill<T>(T obj)
|
||||||
{
|
{
|
||||||
Status = TaskStatus.Succeeded;
|
/*Status = TaskStatus.Succeeded;
|
||||||
|
|
||||||
Result = obj;
|
Result = obj;
|
||||||
|
|
||||||
|
@ -65,32 +69,30 @@ public class TaskMeta : IComponent
|
||||||
LK.PushString(Guid.ToString());
|
LK.PushString(Guid.ToString());
|
||||||
|
|
||||||
ObjectManager.PushObject(LK, obj);
|
ObjectManager.PushObject(LK, obj);
|
||||||
LK.SetMetaTable(TypeName);
|
LK.SetMetaTable(Name);
|
||||||
|
|
||||||
LK.PushNil();
|
LK.PushNil();
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Fulfill(Action<Lua> lk)
|
public void Fulfill(Action<Lua> lk)
|
||||||
{
|
{
|
||||||
Status = TaskStatus.Succeeded;
|
Status = TaskStatus.Succeeded;
|
||||||
|
|
||||||
|
var container = tasks.NewThread();
|
||||||
|
lk(container);
|
||||||
|
container.XMove(tasks, 1);
|
||||||
|
tasks.Replace(-2);
|
||||||
|
DataIndex = tasks.GetTop();
|
||||||
|
|
||||||
_game.LuaRuntime.QueueEvent("task_finish", LK =>
|
_game.LuaRuntime.QueueEvent("task_finish", LK =>
|
||||||
{
|
{
|
||||||
LK.PushString(Guid.ToString());
|
LK.PushString(Guid.ToString());
|
||||||
|
|
||||||
// Create Lua thread to store Lua native result data
|
tasks.PushCopy(DataIndex);
|
||||||
Result = LK.NewThread();
|
tasks.XMove(LK, 1);
|
||||||
var thread = (Lua)Result;
|
|
||||||
LK.Pop(1);
|
|
||||||
|
|
||||||
lk(thread);
|
|
||||||
|
|
||||||
// Push copy of value on top and move it to LK
|
|
||||||
thread.PushCopy(-1);
|
|
||||||
thread.XMove(LK, 1);
|
|
||||||
|
|
||||||
LK.PushNil();
|
LK.PushNil();
|
||||||
|
|
||||||
|
@ -176,8 +178,11 @@ public class TaskMeta : IComponent
|
||||||
new(),
|
new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static Lua tasks;
|
||||||
public void LuaInit(Lua L)
|
public void LuaInit(Lua L)
|
||||||
{
|
{
|
||||||
|
tasks = _game.LuaRuntime.Parent.NewThread();
|
||||||
|
|
||||||
CreateMeta(L);
|
CreateMeta(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +216,7 @@ public class TaskMeta : IComponent
|
||||||
var obj = ObjectManager.CheckObject<RuntimeTask>(L, 1, ObjectType, gc);
|
var obj = ObjectManager.CheckObject<RuntimeTask>(L, 1, ObjectType, gc);
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
{
|
{
|
||||||
L.Error("attempt to use a closed file");
|
L.Error("attempt to use a closed task");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -265,7 +270,7 @@ public class TaskMeta : IComponent
|
||||||
|
|
||||||
var task = CheckTask(L, false);
|
var task = CheckTask(L, false);
|
||||||
|
|
||||||
L.PushString(task.TypeName);
|
L.PushString(task.Name);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -289,17 +294,9 @@ public class TaskMeta : IComponent
|
||||||
|
|
||||||
if (task.Status == TaskStatus.Succeeded)
|
if (task.Status == TaskStatus.Succeeded)
|
||||||
{
|
{
|
||||||
if (task.Result is Lua thread)
|
// Push copy of value on top and move it to L
|
||||||
{
|
tasks.PushCopy(task.DataIndex);
|
||||||
// Push copy of value on top and move it to LK
|
tasks.XMove(L, 1);
|
||||||
thread.PushCopy(-1);
|
|
||||||
thread.XMove(L, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ObjectManager.PushObject(L, task.Result);
|
|
||||||
L.SetMetaTable(task.TypeName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -329,6 +326,21 @@ public class TaskMeta : IComponent
|
||||||
|
|
||||||
private static int LM_GC(IntPtr state)
|
private static int LM_GC(IntPtr state)
|
||||||
{
|
{
|
||||||
|
var L = Lua.FromIntPtr(state);
|
||||||
|
|
||||||
|
var task = ToTask(L, true);
|
||||||
|
if (task is null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// todo: add cleanup to remove nil values at top of stack
|
||||||
|
|
||||||
|
if (tasks.GetTop() == task.DataIndex)
|
||||||
|
tasks.SetTop(task.DataIndex - 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tasks.PushNil();
|
||||||
|
tasks.Replace(task.DataIndex);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +348,7 @@ public class TaskMeta : IComponent
|
||||||
{
|
{
|
||||||
var L = Lua.FromIntPtr(state);
|
var L = Lua.FromIntPtr(state);
|
||||||
var task = ToTask(L);
|
var task = ToTask(L);
|
||||||
L.PushString("Task<{0}>: {1} ({2})", task?.TypeName, task?.Guid, task?.Status);
|
L.PushString("Task<{0}>: {1} ({2})", task?.Name, task?.Guid, task?.Status);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ internal class RuntimeManager : IComponent
|
||||||
|
|
||||||
luaState = new LuaState();
|
luaState = new LuaState();
|
||||||
_game.LuaRuntime = luaState;
|
_game.LuaRuntime = luaState;
|
||||||
|
luaState.Init();
|
||||||
|
|
||||||
emitter = new(_game.EventEmitter, luaState);
|
emitter = new(_game.EventEmitter, luaState);
|
||||||
|
|
||||||
|
@ -136,6 +137,7 @@ internal class RuntimeManager : IComponent
|
||||||
|
|
||||||
luaState = new LuaState();
|
luaState = new LuaState();
|
||||||
_game.LuaRuntime = luaState;
|
_game.LuaRuntime = luaState;
|
||||||
|
luaState.Init();
|
||||||
|
|
||||||
emitter = new(_game.EventEmitter, luaState);
|
emitter = new(_game.EventEmitter, luaState);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue