protected bool TryComplete(bool didCompleteSynchronously, Exception exception) { lock (ThisLock) { if (IsCompleted) { return(false); } _exception = exception; IsCompleted = true; } #if DEBUG _marker.AsyncResult = null; _marker = null; #endif CompletedSynchronously = didCompleteSynchronously; if (OnCompleting != null) { // Allow exception replacement, like a catch/throw pattern. try { OnCompleting(this, _exception); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } _exception = e; } } if (didCompleteSynchronously) { // If we completedSynchronously, then there's no chance that the manualResetEvent was created so // we don't need to worry about a race Fx.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); } else { lock (ThisLock) { if (_manualResetEvent != null) { _manualResetEvent.Set(); } } } if (_callback != null) { try { if (VirtualCallback != null) { VirtualCallback(_callback, this); } else { _callback(this); } } #pragma warning disable 1634 #pragma warning suppress 56500 // transferring exception to another thread catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw Fx.Exception.AsError(new CallbackException(CommonResources.AsyncCallbackThrewException, e)); } #pragma warning restore 1634 } return(true); }
public static void Fork(this Task thisTask, string tracingInfo) { Fx.Assert(thisTask != null, "task is required!"); thisTask.ContinueWith(t => Fx.Exception.TraceHandled(t.Exception, tracingInfo), TaskContinuationOptions.OnlyOnFaulted); }
public TransactionSignalScope(AsyncResult result, Transaction transaction) { Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope."); _parent = result; _transactionScope = Fx.CreateTransactionScope(transaction); }
public static Exception AssertAndThrowFatal(string description) { Fx.Assert(description); throw Fx.Exception.AsError(new FatalException(description)); }
public static Exception AssertAndThrow(string description) { Fx.Assert(description); throw Fx.Exception.AsError(new AssertionFailedException(description)); }
public void DebugVerifyEmpty() { Fx.Assert(this.gate == 0, "Finalized with unfinished slot."); Fx.Assert(this.heldCallback == null, "Finalized with leaked callback."); Fx.Assert(this.heldState == null, "Finalized with leaked state."); }
private void CompletionCallback(out Action <object> callback, out object state) { int slot = this.headTail; int slotLowPri; while (true) { Fx.Assert(Bits.Count(slot) != -1, "CompletionCallback called on idle IOTS!"); bool wasEmpty = Bits.Count(slot) == 0; if (wasEmpty) { // We're about to set this to idle. First check the low-priority queue. This alone doesn't // guarantee we service all the low-pri items - there hasn't even been an Interlocked yet. But // we take care of that later. slotLowPri = this.headTailLowPri; while (Bits.CountNoIdle(slotLowPri) != 0) { if (slotLowPri == (slotLowPri = Interlocked.CompareExchange(ref this.headTailLowPri, Bits.IncrementLo(slotLowPri), slotLowPri))) { this.overlapped.Post(this); this.slotsLowPri[slotLowPri & SlotMaskLowPri].DequeueWorkItem(out callback, out state); return; } } } if (slot == (slot = Interlocked.CompareExchange(ref this.headTail, Bits.IncrementLo(slot), slot))) { if (!wasEmpty) { this.overlapped.Post(this); this.slots[slot & SlotMask].DequeueWorkItem(out callback, out state); return; } // We just set the IOThreadScheduler to idle. Check if a low-priority item got added in the // interim. // Interlocked calls create a thread barrier, so this read will give us the value of // headTailLowPri at the time of the interlocked that set us to idle, or later. The invariant // here is that either the low-priority queue was empty at some point after we set the IOTS to // idle (so that the next enqueue will notice, and issue a Post), or that the IOTS was unidle at // some point after we set it to idle (so that the next attempt to go idle will verify that the // low-priority queue is empty). slotLowPri = this.headTailLowPri; if (Bits.CountNoIdle(slotLowPri) != 0) { // Whoops, go back from being idle (unless someone else already did). If we go back, start // over. (We still owe a Post.) slot = Bits.IncrementLo(slot); if (slot == Interlocked.CompareExchange(ref this.headTail, slot + Bits.HiOne, slot)) { slot += Bits.HiOne; continue; } // We know that there's a low-priority work item. But we also know that the IOThreadScheduler // wasn't idle. It's best to let it take care of itself, since according to this method, we // just set the IOThreadScheduler to idle so shouldn't take on any tasks. } break; } } callback = null; state = null; return; }