LuaThread.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using System.Runtime.CompilerServices;
  2. using Lua.Internal;
  3. using Lua.Runtime;
  4. namespace Lua;
  5. public class LuaThread : IPoolNode<LuaThread>
  6. {
  7. static LinkedPool<LuaThread> pool;
  8. LuaThread? parent;
  9. ref LuaThread? IPoolNode<LuaThread>.NextNode => ref parent;
  10. public static LuaThread Create(LuaState state)
  11. {
  12. var thread = new LuaThread { CoreData = { State = state } };
  13. return thread;
  14. }
  15. public virtual LuaThreadStatus GetStatus()
  16. {
  17. return LuaThreadStatus.Running;
  18. }
  19. public virtual void UnsafeSetStatus(LuaThreadStatus status){}
  20. public virtual ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
  21. {
  22. return new(context.Return(false, "cannot resume non-suspended coroutine"));
  23. }
  24. public virtual ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
  25. {
  26. throw new LuaRuntimeException(context.State.GetTraceback(), "attempt to yield from outside a coroutine");
  27. }
  28. internal class ThreadCoreData
  29. {
  30. internal LuaState State;
  31. //internal LuaCoroutineData? coroutineData;
  32. internal LuaStack Stack = new();
  33. internal FastStackCore<CallStackFrame> CallStack;
  34. internal BitFlags2 LineAndCountHookMask;
  35. internal BitFlags2 CallOrReturnHookMask;
  36. internal bool IsInHook;
  37. internal int HookCount;
  38. internal int BaseHookCount;
  39. internal int LastPc;
  40. internal LuaFunction? Hook { get; set; }
  41. }
  42. internal ThreadCoreData CoreData = new();
  43. public LuaState State=> CoreData.State;
  44. internal LuaStack Stack => CoreData.Stack;
  45. internal ref FastStackCore<CallStackFrame> CallStack => ref CoreData.CallStack;
  46. internal bool IsLineHookEnabled
  47. {
  48. get => CoreData.LineAndCountHookMask.Flag0;
  49. set => CoreData.LineAndCountHookMask.Flag0 = value;
  50. }
  51. internal bool IsCountHookEnabled
  52. {
  53. get => CoreData.LineAndCountHookMask.Flag1;
  54. set => CoreData.LineAndCountHookMask.Flag1 = value;
  55. }
  56. internal bool IsCallHookEnabled
  57. {
  58. get => CoreData.CallOrReturnHookMask.Flag0;
  59. set => CoreData.CallOrReturnHookMask.Flag0 = value;
  60. }
  61. internal bool IsReturnHookEnabled
  62. {
  63. get => CoreData.CallOrReturnHookMask.Flag1;
  64. set => CoreData.CallOrReturnHookMask.Flag1 = value;
  65. }
  66. internal BitFlags2 LineAndCountHookMask
  67. {
  68. get => CoreData.LineAndCountHookMask;
  69. set => CoreData.LineAndCountHookMask = value;
  70. }
  71. internal BitFlags2 CallOrReturnHookMask
  72. {
  73. get => CoreData.CallOrReturnHookMask;
  74. set => CoreData.CallOrReturnHookMask = value;
  75. }
  76. internal bool IsInHook
  77. {
  78. get => CoreData.IsInHook;
  79. set => CoreData.IsInHook = value;
  80. }
  81. internal int HookCount
  82. {
  83. get => CoreData.HookCount;
  84. set => CoreData.HookCount = value;
  85. }
  86. internal int BaseHookCount
  87. {
  88. get => CoreData.BaseHookCount;
  89. set => CoreData.BaseHookCount = value;
  90. }
  91. internal int LastPc
  92. {
  93. get => CoreData.LastPc;
  94. set => CoreData.LastPc = value;
  95. }
  96. internal LuaFunction? Hook
  97. {
  98. get => CoreData.Hook;
  99. set => CoreData.Hook = value;
  100. }
  101. public ref readonly CallStackFrame GetCurrentFrame()
  102. {
  103. return ref CoreData.CallStack.PeekRef();
  104. }
  105. public ReadOnlySpan<LuaValue> GetStackValues()
  106. {
  107. return CoreData.Stack.AsSpan();
  108. }
  109. public ReadOnlySpan<CallStackFrame> GetCallStackFrames()
  110. {
  111. return CoreData.CallStack.AsSpan();
  112. }
  113. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  114. internal void PushCallStackFrame(in CallStackFrame frame)
  115. {
  116. CoreData.CallStack.Push(frame);
  117. }
  118. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  119. internal void PopCallStackFrameWithStackPop()
  120. {
  121. if (CoreData.CallStack.TryPop(out var frame))
  122. {
  123. CoreData.Stack.PopUntil(frame.Base);
  124. }
  125. else
  126. {
  127. ThrowForEmptyStack();
  128. }
  129. }
  130. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  131. internal void PopCallStackFrameWithStackPop(int frameBase)
  132. {
  133. if (CoreData.CallStack.TryPop())
  134. {
  135. CoreData.Stack.PopUntil(frameBase);
  136. }
  137. else
  138. {
  139. ThrowForEmptyStack();
  140. }
  141. }
  142. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  143. internal void PopCallStackFrame()
  144. {
  145. if (!CoreData.CallStack.TryPop())
  146. {
  147. ThrowForEmptyStack();
  148. }
  149. }
  150. internal void DumpStackValues()
  151. {
  152. var span = GetStackValues();
  153. for (int i = 0; i < span.Length; i++)
  154. {
  155. Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
  156. }
  157. }
  158. public void Release()
  159. {
  160. if (CoreData.CallStack.Count != 0)
  161. {
  162. throw new InvalidOperationException("This thread is running! Call stack is not empty!!");
  163. }
  164. }
  165. static void ThrowForEmptyStack() => throw new InvalidOperationException("Empty stack");
  166. }