protected bool TryComplete(bool didCompleteSynchronously, Exception exception)
        {
            lock (this.ThisLock)
            {
                if (this.isCompleted)
                {
                    return(false);
                }

                this.exception   = exception;
                this.isCompleted = true;
            }

#if DEBUG
            this.marker.AsyncResult = null;
            this.marker             = null;
#endif

            this.completedSynchronously = didCompleteSynchronously;
            if (this.OnCompleting != null)
            {
                // Allow exception replacement, like a catch/throw pattern.
                try
                {
                    this.OnCompleting(this, this.exception);
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
                    this.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(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
            }
            else
            {
                lock (this.ThisLock)
                {
                    if (this.manualResetEvent != null)
                    {
                        this.manualResetEvent.Set();
                    }
                }
            }

            if (this.callback != null)
            {
                try
                {
                    if (this.VirtualCallback != null)
                    {
                        this.VirtualCallback(this.callback, this);
                    }
                    else
                    {
                        this.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 TransactionSignalScope(AsyncResult result, Transaction transaction)
 {
     Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope.");
     this.parent           = result;
     this.transactionScope = Fx.CreateTransactionScope(transaction);
 }
예제 #3
0
        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;
        }
예제 #4
0
 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.");
 }
예제 #5
0
 void IdleTimerCallback()
 {
     Fx.Assert(this.referenceCount == 0, "Cached IotHubConnection's ref count should be zero when idle timeout occurs!");
     this.cache.RemoveHubScopeConnectionPool(this.ConnectionString);
     this.Connection.CloseAsync().Fork();
 }
예제 #6
0
 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);
 }
예제 #7
0
 void SetDeadline()
 {
     Fx.Assert(!deadlineSet, "TimeoutHelper deadline set twice.");
     this.deadline    = DateTime.UtcNow + this.originalTimeout;
     this.deadlineSet = true;
 }
예제 #8
0
 public static Exception AssertAndThrowFatal(string description)
 {
     Fx.Assert(description);
     throw Fx.Exception.AsError(new FatalException(description));
 }
예제 #9
0
 public static Exception AssertAndThrow(string description)
 {
     Fx.Assert(description);
     throw Fx.Exception.AsError(new AssertionFailedException(description));
 }