Loom.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System;
  5. using System.Threading;
  6. using System.Linq;
  7. public class Loom : MonoBehaviour
  8. {
  9. public static int maxThreads = 8;
  10. static int numThreads;
  11. private static Loom _current;
  12. private int _count;
  13. public static Loom Current
  14. {
  15. get
  16. {
  17. Initialize();
  18. return _current;
  19. }
  20. }
  21. void Awake()
  22. {
  23. _current = this;
  24. initialized = true;
  25. }
  26. static bool initialized;
  27. static void Initialize()
  28. {
  29. if (!initialized)
  30. {
  31. if (!Application.isPlaying)
  32. return;
  33. initialized = true;
  34. var g = new GameObject("Loom");
  35. _current = g.AddComponent<Loom>();
  36. }
  37. }
  38. private List<Action> _actions = new List<Action>();
  39. public struct DelayedQueueItem
  40. {
  41. public float time;
  42. public Action action;
  43. }
  44. private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
  45. List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
  46. public static void QueueOnMainThread(Action action)
  47. {
  48. QueueOnMainThread(action, 0f);
  49. }
  50. public static void QueueOnMainThread(Action action, float time)
  51. {
  52. if (time != 0)
  53. {
  54. lock (Current._delayed)
  55. {
  56. Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
  57. }
  58. }
  59. else
  60. {
  61. lock (Current._actions)
  62. {
  63. Current._actions.Add(action);
  64. }
  65. }
  66. }
  67. public static Thread RunAsync(Action a)
  68. {
  69. Initialize();
  70. while (numThreads >= maxThreads)
  71. {
  72. Thread.Sleep(1);
  73. }
  74. Interlocked.Increment(ref numThreads);
  75. ThreadPool.QueueUserWorkItem(RunAction, a);
  76. return null;
  77. }
  78. private static void RunAction(object action)
  79. {
  80. try
  81. {
  82. ((Action)action)();
  83. }
  84. catch
  85. {
  86. }
  87. finally
  88. {
  89. Interlocked.Decrement(ref numThreads);
  90. }
  91. }
  92. void OnDisable()
  93. {
  94. if (_current == this)
  95. {
  96. _current = null;
  97. }
  98. }
  99. // Use this for initialization
  100. void Start()
  101. {
  102. }
  103. List<Action> _currentActions = new List<Action>();
  104. // Update is called once per frame
  105. void Update()
  106. {
  107. lock (_actions)
  108. {
  109. _currentActions.Clear();
  110. _currentActions.AddRange(_actions);
  111. _actions.Clear();
  112. }
  113. foreach (var a in _currentActions)
  114. {
  115. a();
  116. }
  117. lock (_delayed)
  118. {
  119. _currentDelayed.Clear();
  120. _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
  121. foreach (var item in _currentDelayed)
  122. _delayed.Remove(item);
  123. }
  124. foreach (var delayed in _currentDelayed)
  125. {
  126. delayed.action();
  127. }
  128. }
  129. }