private void NextThen() { var tid = Thread.CurrentThread.ManagedThreadId; //等待的事件成功,继续下一步 waitable.Then(() => { if (Status != WaitableStatus.Running) { return; } var fastCall = tid == Thread.CurrentThread.ManagedThreadId; var complete = waitable is ICompleteCoroutineWaitable; waitable = null; if (complete) { Enqueue(Success, fastCall); } else { Enqueue(NextStep, fastCall); } }); }
public bool TryEnqueue(T item, int timeoutMilliseconds = 0) { if (item == null) { return(false); } //The method only throws exception on thread lock timeout using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { return(false); } if (m_count == m_size) { return(false); } m_items[m_tail++] = item; // Place the new item immediately after tail, then increment tail pos m_tail %= m_size; // Modulus new tail pos with size so queue items will wrap around m_count++; // Count will never be more than size after incrementing here //Signal that an item has been enqueued to unblock waiting //dequeue threads syncLock.PulseAll(); return(true); } }
private void NextCatch() { var tid = Thread.CurrentThread.ManagedThreadId; waitable.Catch(e => { if (Status != WaitableStatus.Running) { return; } var fastCall = tid == Thread.CurrentThread.ManagedThreadId; waitable = null; if (waitable is ICompleteCoroutineWaitable) { Enqueue(() => Fail(e), fastCall); } else { //等待的事件失败,继续下一步,由调用者处理异常,coroutine本身未失败 Enqueue(NextStep, fastCall); } }); }
public bool TryDequeue(out T item, int timeoutMilliseconds = 0) { //This method only throws exception on thread lock timeout using (IWaitable syncRoot = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { item = null; return(false); } if (m_count == 0) { item = null; return(false); } item = m_items[m_head]; // Get item at head of queue m_items[m_head++] = null; // Clear item at head of queue then increment head pos m_head %= m_size; // Modulus new head pos with size so queue items will wrap around m_count--; // Count will never be less than zero after decrementing here //Signal that an item has been dequeued to unblock waiting //enqueue threads syncRoot.PulseAll(); return(true); } }
public static IWaitable Catch(this IWaitable self, Action callback) { if (callback == null) { return(self); } return(self.Catch(e => callback())); }
public static IWaitable <T> Then <T>(this IWaitable <T> self, Action <T> callback) { Assert.NotNull(self, nameof(self)); Assert.NotNull(callback, nameof(callback)); self.Then(() => callback(self.Result)); return(self); }
public static Exception Throw(this IWaitable self) { if (self.Exception != null) { ExceptionDispatchInfo.Capture(self.Exception).Throw(); } return(null); }
public static IWaitable Finally(this IWaitable self, Action callback) { Assert.NotNull(self, nameof(self)); Assert.NotNull(callback, nameof(callback)); self.Then(callback); self.Catch(e => callback()); return(self); }
public static void WaitOnUI(this IWaitable comp, Action task) { Task.Run(() => { comp.StartWait(); task.Invoke(); comp.StopWait(); }); }
public void ClearAllCoroutines() { var list = new IWaitable[waitables.Count]; waitables.CopyTo(list); waitables.Clear(); foreach (var waitable in list) { waitable.Abort(); } }
public static IWaitable Finally(this IWaitable self, Action callback) { if (callback == null) { return(self); } self.Then(callback); self.Catch(callback); return(self); }
private void Dispatch(IWaitable waitable) { this.waitable = waitable; if (waitable is IBindCoroutineWaitable bindCoroutineWaitable) { bindCoroutineWaitable.Bind(container); } NextThen(); NextCatch(); }
public void Clear() { using (IWaitable syncLock = SyncRoot.Enter() as IWaitable) { //Unblock waiting threads syncLock.PulseAll(); m_count = 0; m_head = 0; m_tail = 0; m_items = new T[m_size]; } }
private void Dispose() { waitable = null; if (enumerator is IDisposable disposable) { disposable.Dispose(); } enumerator = null; successCallbacks = null; failCallbacks = null; }
public bool IsDone(float deltaTime) { bool isNoNeedWait = true, isMoveOver = true; var current = Enumerator.Current; if (current is IWaitable) { IWaitable waitable = current as IWaitable; isNoNeedWait = waitable.IsTickOver(deltaTime); } if (isNoNeedWait) { isMoveOver = Enumerator.MoveNext(); } return(!isMoveOver); }
public static void Throw(this IWaitable self) { Assert.NotNull(self, nameof(self)); var exception = self.Exception; var status = self.Status; if (exception != null) { ExceptionDispatchInfo.Capture(exception).Throw(); return; } if (status == WaitableStatus.Abort) { throw new WaitableAbortException(); } }
public void TestAbort2() { var i = 0; IWaitable co2 = null; var co1 = CoroutineContainer.StartCoroutine(RunFather()); Assert.AreEqual(0, i); CoroutineManager.OneLoop(); Assert.AreEqual(1, i); CoroutineManager.OneLoop(); Assert.AreEqual(2, i); CoroutineManager.OneLoop(); Assert.AreEqual(3, i); co1.Abort(); Assert.AreEqual(3, i); CoroutineManager.OneLoop(); Assert.AreEqual(3, i); Tick(); Assert.AreEqual(3, i); Assert.AreEqual(WaitableStatus.Abort, co1.Status); Assert.AreEqual(WaitableStatus.Abort, co2.Status); Assert.IsTrue(co1.IsAborted()); Assert.IsTrue(co2.IsAborted()); IEnumerable RunFather() { i++; co2 = CoroutineContainer.StartCoroutine(RunChild()); yield return(co2); i++; } IEnumerable RunChild() { while (true) { i++; yield return(null); } } }
private void NextStep() { bool moveNext; try { moveNext = enumerator.MoveNext(); } catch (Exception e) { //coroutine本身抛出异常,当前coroutine失败 Fail(e); return; } waitable = null; if (!moveNext) { Success(); return; } var current = enumerator.Current; switch (current) { case null: Enqueue(NextStep, false); break; case IEnumerable enumerable: Dispatch(container.StartCoroutine(enumerable)); break; case Task task: Dispatch(new WaitForTask(task)); break; default: Dispatch((IWaitable)current); break; } }
private void NextStep() { bool moveNext; try { moveNext = enumerator.MoveNext(); } catch (Exception e) { //coroutine本身抛出异常,当前coroutine失败 Fail(e); return; } waitable = null; if (!moveNext) { Success(default);
public void Enqueue(T item, int timeoutMilliseconds = -1) { if (item == null) { throw new ArgumentNullException("item", "item cannot be null"); } if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { //While the queue is full, wait for an empty space //Timeout won't be exact if multiple enqueues are blocked on a full queue //So a dequeue could be followed by a different enqueue so this will wait //for another loop while (m_count == m_size) { //Wait for a pulse from a dequeue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Enqueue timed out while waiting for available queue space"); } //Double check not disposed since waiting for available space if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } m_items[m_tail++] = item; // Place the new item immediately after tail, then increment tail pos m_tail %= m_size; // Modulus new tail pos with size so queue items will wrap around m_count++; // Count will never be more than size after incrementing here //Signal that an item has been enqueued to unblock waiting //dequeue threads syncLock.PulseAll(); } }
public void Clear() { IWaitable[] list; using (spin.Hold()) { list = new IWaitable[waitables.Count]; waitables.CopyTo(list); waitables.Clear(); } foreach (var waitable in list) { try { waitable.Abort(); } catch (Exception e) { Console.Error.WriteLine(e); } } }
public T Peek(int timeoutMilliseconds = -1, bool waitForEnqueue = false) { using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } if (m_count == 0) { if (waitForEnqueue) { //While queue is empty, wait for an item to enqueue while (m_count == 0) { //Wait for a signal from an enqueue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue"); } //Double check not disposed since waiting for item to be enqueued if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } } else { throw new InvalidOperationException("Bounded Blocking Queue is empty"); } } T value = m_items[m_head]; return(value); } }
public T Dequeue(int timeoutMilliseconds = -1) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { //Similar reasoning for here from Enqueue method //While queue is empty, wait for an item to enqueue while (m_count == 0) { //Wait for a signal from an enqueue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue"); } //Double check not disposed since waiting for item to be enqueued if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } T value = m_items[m_head]; // Get item at head of queue m_items[m_head++] = null; // Clear item at head of queue then increment head pos m_head %= m_size; // Modulus new head pos with size so queue items will wrap around m_count--; // Count will never be less than zero after decrementing here //Signal that an item has been dequeued to unblock waiting //enqueue threads syncLock.PulseAll(); return(value); } }
public static void Wait(IWaitable wait, Action okCallback) { CCosmosEngine.EngineInstance.StartCoroutine(CoWaitTrue(new[] { wait }, okCallback)); }
public static void Wait(IWaitable wait, Action okCallback) { CCosmosEngine.EngineInstance.StartCoroutine(CoWaitTrue(new[] { wait }, okCallback)); }
public static bool IsCompleted(this IWaitable self) { Assert.NotNull(self, nameof(self)); return(self.Status != WaitableStatus.Running); }
private IWaitable Add(IWaitable waitable) { waitables.Add(waitable); waitable.Finally(() => waitables.Remove(waitable)); return(waitable); }
public void WaitsOn(IWaitable waitable) { WaitsOn(new List <IWaitable> { waitable }); }
public MalockTryEnterCallback(EventWaitHandle handle) { this.handle = handle; this.signal = handle.NewWaitable(); }
public static Awaiter GetAwaiter(this IWaitable waitable) { return(new Awaiter(waitable)); }
public Awaiter(IWaitable waitable) { this.waitable = waitable; }