Esempio n. 1
0
            public void Post(IOThreadScheduler iots)
            {
                Fx.Assert(_scheduler == null, "Post called on an overlapped that is already posted.");
                Fx.Assert(iots != null, "Post called with a null scheduler.");

                _scheduler = iots;
                _postDelegate();
            }
Esempio n. 2
0
            public void Post(IOThreadScheduler iots)
            {
                Fx.Assert(scheduler == null, "Post called on an overlapped that is already posted.");
                Fx.Assert(iots != null, "Post called with a null scheduler.");

                scheduler = iots;
                ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped);
            }
Esempio n. 3
0
        // Returns true if successfully scheduled, false otherwise.
        bool ScheduleCallbackLowPriHelper(Action <object> callback, object state)
        {
            // See if there's a free slot.  Fortunately the overflow bit is simply lost.
            int slot = Interlocked.Add(ref headTailLowPri, Bits.HiOne);

            // If this is the first low-priority work item, make sure we're not idle.
            bool wasIdle = false;

            if (Bits.CountNoIdle(slot) == 1)
            {
                // Since Interlocked calls create a full thread barrier, this will read the value of headTail
                // at the time of the Interlocked.Add or later.  The invariant is that the IOTS is unidle at some
                // point after the Add.
                int ht = headTail;

                if (Bits.Count(ht) == -1)
                {
                    // Use a temporary local here to store the result of the Interlocked.CompareExchange.  This
                    // works around a codegen bug in the 32-bit JIT (TFS 749182).
                    int interlockedResult = Interlocked.CompareExchange(ref headTail, ht + Bits.HiOne, ht);
                    if (ht == interlockedResult)
                    {
                        wasIdle = true;
                    }
                }
            }

            // Check if we wrapped *around* to empty.
            if (Bits.CountNoIdle(slot) == 0)
            {
                // Since the capacity is limited to 32k, this means we wrapped the array at least twice.  That's bad
                // because headTail no longer knows how many work items we have - it looks like zero.  This can
                // only happen if 32k threads come through here while one is swapped out.
                throw Fx.AssertAndThrowFatal("Low-priority Head/Tail overflow!");
            }

            bool wrapped;
            bool queued = slotsLowPri[slot >> Bits.HiShift & SlotMaskLowPri].TryEnqueueWorkItem(
                callback, state, out wrapped);

            if (wrapped)
            {
                IOThreadScheduler next =
                    new IOThreadScheduler(slots.Length, Math.Min(slotsLowPri.Length * 2, MaximumCapacity));
                Interlocked.CompareExchange <IOThreadScheduler>(ref IOThreadScheduler.current, next, this);
            }

            if (wasIdle)
            {
                // It's our responsibility to kick off the overlapped.
                overlapped.Post(this);
            }

            return(queued);
        }
Esempio n. 4
0
 static void ScheduleCallback(Action <object> callback, object state, bool lowPriority)
 {
     Fx.Assert(callback != null, "Cannot schedule a null callback");
     if (lowPriority)
     {
         IOThreadScheduler.ScheduleCallbackLowPriNoFlow(callback, state);
     }
     else
     {
         IOThreadScheduler.ScheduleCallbackNoFlow(callback, state);
     }
 }
Esempio n. 5
0
        // Returns true if successfully scheduled, false otherwise.
        bool ScheduleCallbackHelper(Action <object> callback, object state)
        {
            // See if there's a free slot.  Fortunately the overflow bit is simply lost.
            int slot = Interlocked.Add(ref headTail, Bits.HiOne);

            // If this brings us to 'empty', then the IOTS used to be 'idle'.  Remember that, and increment
            // again.  This doesn't need to be in a loop, because until we call Post(), we can't go back to idle.
            bool wasIdle = Bits.Count(slot) == 0;

            if (wasIdle)
            {
                slot = Interlocked.Add(ref headTail, Bits.HiOne);
                Fx.Assert(Bits.Count(slot) != 0, "IOTS went idle when it shouldn't have.");
            }

            // Check if we wrapped *around* to idle.
            if (Bits.Count(slot) == -1)
            {
                // Since the capacity is limited to 32k, this means we wrapped the array at least twice.  That's bad
                // because headTail no longer knows how many work items we have - it looks like zero.  This can
                // only happen if 32k threads come through here while one is swapped out.
                throw Fx.AssertAndThrowFatal("Head/Tail overflow!");
            }

            bool wrapped;
            bool queued = slots[slot >> Bits.HiShift & SlotMask].TryEnqueueWorkItem(callback, state, out wrapped);

            if (wrapped)
            {
                // Wrapped around the circular buffer.  Create a new, bigger IOThreadScheduler.
                IOThreadScheduler next =
                    new IOThreadScheduler(Math.Min(slots.Length * 2, MaximumCapacity), slotsLowPri.Length);
                Interlocked.CompareExchange <IOThreadScheduler>(ref IOThreadScheduler.current, next, this);
            }

            if (wasIdle)
            {
                // It's our responsibility to kick off the overlapped.
                overlapped.Post(this);
            }

            return(queued);
        }
Esempio n. 6
0
            void IOCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
            {
                // Unhook the IOThreadScheduler ASAP to prevent it from leaking.
                IOThreadScheduler iots = scheduler;

                scheduler = null;
                Fx.Assert(iots != null, "Overlapped completed without a scheduler.");

                Action <object> callback;
                object          state;

                try { }
                finally
                {
                    // Called in a finally because it needs to run uninterrupted in order to maintain consistency.
                    iots.CompletionCallback(out callback, out state);
                }

                bool found = true;

                while (found)
                {
                    // The callback can be null if synchronization misses result in unsuable slots.  Keep going onto
                    // the next slot in such cases until there are no more slots.
                    if (callback != null)
                    {
                        callback(state);
                    }

                    try { }
                    finally
                    {
                        // Called in a finally because it needs to run uninterrupted in order to maintain consistency.
                        found = iots.TryCoalesce(out callback, out state);
                    }
                }
            }
Esempio n. 7
0
 public override void Post(SendOrPostCallback d, object state)
 {
     IOThreadScheduler.ScheduleCallbackNoFlow(
         (s) => { d(s); }, state);
 }