PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Rusty/Core/Flow.cs

http://github.com/polyethene/IronAHK
C# | 317 lines | 174 code | 50 blank | 93 comment | 42 complexity | 0e11c99373ade5c444458a85c9911240 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Threading;
  5. using System.Windows.Forms;
  6. using ThreadState = System.Threading.ThreadState;
  7. using Timer = System.Timers.Timer;
  8. namespace IronAHK.Rusty
  9. {
  10. partial class Core
  11. {
  12. /// <summary>
  13. /// Prevents the current thread from being interrupted by other threads.
  14. /// </summary>
  15. /// <param name="mode">
  16. /// <list type="bullet">
  17. /// <item><term>On</term>: <description>give the current thread the highest priority.</description></item>
  18. /// <item><term>Off</term>: <description>resets the current thread priority to normal.</description></item>
  19. /// </list>
  20. /// </param>
  21. public static void Critical(string mode)
  22. {
  23. bool on = OnOff(mode) ?? true;
  24. System.Threading.Thread.CurrentThread.Priority = on ? ThreadPriority.Highest : ThreadPriority.Normal;
  25. }
  26. /// <summary>
  27. /// Exits the current thread or the entire program if non-persistent.
  28. /// </summary>
  29. /// <param name="exitCode">An integer that is returned to the caller.</param>
  30. public static void Exit(int exitCode)
  31. {
  32. if (ApplicationExit != null)
  33. ApplicationExit(null, null);
  34. Environment.ExitCode = exitCode;
  35. Application.ExitThread();
  36. }
  37. /// <summary>
  38. /// Terminates the program unconditionally.
  39. /// </summary>
  40. /// <param name="exitCode">An integer that is returned to the caller.</param>
  41. public static void ExitApp(int exitCode)
  42. {
  43. if (ApplicationExit != null)
  44. ApplicationExit(null, null);
  45. Environment.Exit(exitCode);
  46. }
  47. /// <summary>
  48. /// Checks if a function is defined.
  49. /// </summary>
  50. /// <param name="name">The name of a function.</param>
  51. /// <returns><c>true</c> if the specified function exists in the current scope, <c>false</c> otherwise.</returns>
  52. public static bool IsFunc(string name)
  53. {
  54. return FindLocalMethod(name) != null;
  55. }
  56. /// <summary>
  57. /// Checks if a label is defined.
  58. /// </summary>
  59. /// <param name="name">The name of a label.</param>
  60. /// <returns><c>true</c> if the specified label exists in the current scope, <c>false</c> otherwise.</returns>
  61. public static bool IsLabel(string name)
  62. {
  63. string method = LabelMethodName(name);
  64. return FindLocalMethod(method) != null;
  65. }
  66. /// <summary>
  67. /// Specifies a label to run automatically when the program exits.
  68. /// </summary>
  69. /// <param name="label">The name of a label. Leave blank to remove an existing label, if any.</param>
  70. public static void OnExit(string label)
  71. {
  72. ErrorLevel = 0;
  73. if (onExit != null)
  74. {
  75. AppDomain.CurrentDomain.ProcessExit -= onExit;
  76. onExit = null;
  77. }
  78. if (string.IsNullOrEmpty(label))
  79. return;
  80. var method = FindLocalRoutine(label);
  81. if (method == null)
  82. {
  83. ErrorLevel = 1;
  84. return;
  85. }
  86. var handler = new EventHandler(delegate
  87. {
  88. try { method.Invoke(null, new object[] { new object[] { } }); }
  89. catch (Exception) { }
  90. });
  91. AppDomain.CurrentDomain.ProcessExit += handler;
  92. onExit = handler;
  93. }
  94. /// <summary>
  95. /// Specifies a function to call automatically when the program receives the specified message.
  96. /// </summary>
  97. /// <param name="number">The number of the message to monitor.</param>
  98. /// <param name="function">The name of a function to call whenever the specified message is received.</param>
  99. /// <param name="maxThreads">The maximum number of concurrent threads to launch per message number.</param>
  100. public static void OnMessage(string number, string function, string maxThreads)
  101. {
  102. // TODO: onmessage
  103. }
  104. /// <summary>
  105. /// Sends a string to the debugger (if any) for display.
  106. /// </summary>
  107. /// <param name="text">The text to send to the debugger for display.</param>
  108. public static void OutputDebug(string text)
  109. {
  110. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  111. WindowsAPI.OutputDebugString(text);
  112. }
  113. /// <summary>
  114. /// Pauses the current thread.
  115. /// </summary>
  116. /// <param name="mode">
  117. /// <list type="bullet">
  118. /// <item><term>Toggle</term> (default): <description>pauses the current thread unless the thread beneath it is paused, in which case the underlying thread is unpaused.</description></item>
  119. /// <item><term>On</term>: <description>pauses the current thread.</description></item>
  120. /// <item><term>Off</term>: <description>if the thread beneath the current thread is paused, it will be in an unpaused state when resumed.</description></item>
  121. /// </list>
  122. /// </param>
  123. /// <param name="parentThread">
  124. /// <list type="bullet">
  125. /// <item><term>0</term>: <description>pause the current thread.</description></item>
  126. /// <item><term>1</term>: <description>marks the thread beneath the current thread as paused so that when it resumes, it will finish the command it was running (if any) and then enter a paused state. If there is no thread beneath the current thread, the program itself is paused, which prevents timers from running.</description></item>
  127. /// </list>
  128. /// </param>
  129. public static void Pause(string mode, bool parentThread)
  130. {
  131. var thread = System.Threading.Thread.CurrentThread;
  132. var state = OnOff(mode);
  133. if (state == null && mode.Equals(Keyword_Toggle, StringComparison.OrdinalIgnoreCase))
  134. state = !(thread.ThreadState == ThreadState.Suspended || thread.ThreadState == ThreadState.SuspendRequested);
  135. #pragma warning disable 612,618
  136. if (state == true)
  137. thread.Suspend();
  138. else if (state == false)
  139. thread.Resume();
  140. #pragma warning restore 612,618
  141. // UNDONE: correct handling of pause on underlying thread
  142. if (parentThread)
  143. thread.Join();
  144. }
  145. /// <summary>
  146. /// Replaces the currently running instance of the program with a new one.
  147. /// </summary>
  148. public static void Reload()
  149. {
  150. Application.Restart();
  151. }
  152. /// <summary>
  153. /// Calls a function automatically at every specified interval.
  154. /// </summary>
  155. /// <param name="label">Name of the label to call.</param>
  156. /// <param name="mode">
  157. /// <list type="bullet">
  158. /// <item><term>On</term>: <description>enables a previously disabled timer or creates a new one at 250ms intervals.</description></item>
  159. /// <item><term>Off</term>: <description>disables an existing timer.</description></item>
  160. /// <item><term>Period</term>: <description>creates a new timer at the specified interval in milliseconds. If this value is negative the timer will only run once.</description></item>
  161. /// </list>
  162. /// </param>
  163. /// <param name="priority">A value between 0 and 4 inclusive to indicate the priority of the timer's thread.</param>
  164. public static void SetTimer(string label, string mode, int priority)
  165. {
  166. if (timers == null)
  167. timers = new Dictionary<string, Timer>();
  168. switch (mode.ToLowerInvariant())
  169. {
  170. case Keyword_On:
  171. if (timers.ContainsKey(label))
  172. {
  173. timers[label].Start();
  174. return;
  175. }
  176. else
  177. mode = "250";
  178. break;
  179. case Keyword_Off:
  180. if (timers.ContainsKey(label))
  181. timers[label].Stop();
  182. else
  183. ErrorLevel = 1;
  184. return;
  185. }
  186. int interval = 250;
  187. if (!string.IsNullOrEmpty(mode) && !int.TryParse(mode, out interval))
  188. {
  189. ErrorLevel = 2;
  190. return;
  191. }
  192. var timer = new Timer();
  193. bool once = interval < 0;
  194. if (once)
  195. interval = -interval;
  196. if (timers.ContainsKey(label))
  197. timers[label].Interval = interval;
  198. else
  199. timers.Add(label, timer);
  200. if (once)
  201. timers.Remove(label);
  202. timer.Interval = interval;
  203. var level = ThreadPriority.Normal;
  204. if (priority > -1 && priority < 5)
  205. level = (ThreadPriority)priority;
  206. var method = FindLocalMethod(label);
  207. timer.Elapsed += delegate
  208. {
  209. System.Threading.Thread.CurrentThread.Priority = level;
  210. try { method.Invoke(null, new object[] { new object[] { } }); }
  211. catch (Exception)
  212. {
  213. timer.Stop();
  214. timers.Remove(label);
  215. timer.Dispose();
  216. }
  217. if (once)
  218. {
  219. timer.Stop();
  220. timer.Dispose();
  221. }
  222. };
  223. timer.Start();
  224. }
  225. /// <summary>
  226. /// Waits the specified amount of time before continuing.
  227. /// </summary>
  228. /// <param name="Delay">The amount of time to pause in milliseconds.</param>
  229. public static void Sleep(int Delay)
  230. {
  231. System.Threading.Thread.CurrentThread.Join(Delay);
  232. int stop = Environment.TickCount + Delay;
  233. while (Environment.TickCount < stop)
  234. {
  235. Application.DoEvents();
  236. System.Threading.Thread.Sleep(10);
  237. }
  238. }
  239. /// <summary>
  240. /// Disables or enables all or selected hotkeys.
  241. /// </summary>
  242. /// <param name="mode">
  243. /// <list type="bullet">
  244. /// <item><term>On</term>: <description>suspends all hotkeys.</description></item>
  245. /// <item><term>Off</term>: <description>re-enables all hotkeys.</description></item>
  246. /// <item><term>Toggle</term> (default): <description>changes to the opposite of its previous state.</description></item>
  247. /// <item><term>Permit</term>: <description>marks the current subroutine as being exempt from suspension.</description></item>
  248. /// </list>
  249. /// </param>
  250. public static void Suspend(string mode)
  251. {
  252. var state = OnOff(mode);
  253. if (state == null && mode.Equals(Keyword_Toggle, StringComparison.OrdinalIgnoreCase))
  254. suspended = !suspended;
  255. else
  256. suspended = (bool)state;
  257. // UNDONE: permit mode for suspend
  258. }
  259. /// <summary>
  260. /// This method is obsolete, use <see cref="Critical"/>.
  261. /// </summary>
  262. [Obsolete]
  263. public static void Thread()
  264. {
  265. }
  266. }
  267. }