Beispiel #1
0
 /// <summary>
 /// Schedules work for this worker.
 /// </summary>
 internal void Schedule(AsyncWorkUnit inUnit)
 {
     #if SUPPORTS_THREADING
     lock (m_LockObject)
     {
         if ((inUnit.AsyncFlags & AsyncFlags.MainThreadOnly) != 0)
         {
             m_Scheduler.Log("Scheduling {0} on main thread", inUnit);
             m_MainThreadOnlyQueue.Enqueue(inUnit);
         }
         else
         {
             m_Scheduler.Log("Scheduling {0} in background", inUnit);
             m_BackgroundQueue.Enqueue(inUnit);
         }
     }
     #else
     if ((inUnit.AsyncFlags & AsyncFlags.MainThreadOnly) != 0)
     {
         m_Scheduler.Log("Scheduling {0} on main thread", inUnit);
         m_MainThreadOnlyQueue.Enqueue(inUnit);
     }
     else
     {
         m_Scheduler.Log("Scheduling {0} in background", inUnit);
         m_BackgroundQueue.Enqueue(inUnit);
     }
     #endif // SUPPORTS_THREADING
 }
Beispiel #2
0
        // Loop to run on thread
        private void ProcessBackgroundQueueOnThread()
        {
            while (!ForceSingleThreaded)
            {
                if (Paused)
                {
                    Thread.Sleep(PausedSleepMS);
                    continue;
                }

                AsyncWorkUnit unit = null;
                lock (m_LockObject)
                {
                    if (m_BackgroundQueue.Count > 0)
                    {
                        unit = m_BackgroundQueue.Peek();
                    }
                }

                if (unit == null)
                {
                    Thread.Sleep(StarvationSleepMS);
                    continue;
                }

                AsyncWorkUnit.StepResult result = AsyncWorkUnit.StepResult.Incomplete;
                while (result.IsIncomplete() && !ForceSingleThreaded && !Paused)
                {
                    result = unit.ThreadedStep();
                    if (result.TickDelay > 0)
                    {
                        Thread.Sleep(TimeSpan.FromTicks(result.TickDelay));
                    }
                }

                if (!result.IsIncomplete())
                {
                    if (result.Type == AsyncWorkUnit.StepResultType.Complete)
                    {
                        m_Scheduler.Log("Completed {0}", unit);
                    }

                    lock (m_LockObject)
                    {
                        m_BackgroundQueue.Dequeue();
                    }

                    m_Scheduler.FreeUnit(unit);
                }
            }

            lock (m_LockObject)
            {
                m_Thread = null;
            }
        }
        // Allocates a work unit for the given enumerator.
        private AsyncWorkUnit AllocUnit(IEnumerator inEnumerator, AsyncFlags inFlags)
        {
            AsyncWorkUnit unit = AllocUnitImpl();

            #if DEVELOPMENT
            string name = Fiber.GetTypeName(inEnumerator.GetType());
            #else
            string name = "[not used]";
            #endif // DEVELOPMENT
            unit.Initialize(null, inEnumerator, inFlags, name);
            return(unit);
        }
        // Allocates a work unit for the given action.
        private AsyncWorkUnit AllocUnit(Action inAction, AsyncFlags inFlags)
        {
            AsyncWorkUnit unit = AllocUnitImpl();

            #if DEVELOPMENT
            string name = string.Format("{0}->{1}::{2}", inAction.Target, inAction.Method.DeclaringType.FullName, inAction.Method.Name);
            #else
            string name = "[not used]";
            #endif // DEVELOPMENT
            unit.Initialize(inAction, null, inFlags, name);
            return(unit);
        }
        /// <summary>
        /// Schedules an enumerated action.
        /// </summary>
        internal AsyncHandle Schedule(IEnumerator inEnumerator, AsyncFlags inFlags)
        {
            if (inEnumerator == null)
            {
                return(AsyncHandle.Null);
            }

            AsyncWorkUnit unit = AllocUnit(inEnumerator, inFlags);

            ScheduleImpl(unit);
            return(unit.GetHandle());
        }
        /// <summary>
        /// Schedules an action.
        /// </summary>
        internal AsyncHandle Schedule(Action inAction, AsyncFlags inFlags)
        {
            if (inAction == null)
            {
                return(AsyncHandle.Null);
            }

            AsyncWorkUnit unit = AllocUnit(inAction, inFlags);

            ScheduleImpl(unit);
            return(unit.GetHandle());
        }
        /// <summary>
        /// Frees a work unit and returns it to the pool.
        /// </summary>
        internal void FreeUnit(AsyncWorkUnit inWorkUnit, bool inbDispatchCallbacks = true)
        {
            if (inbDispatchCallbacks)
            {
                inWorkUnit.DispatchStop(Dispatcher);
            }

            inWorkUnit.Clear();

            #if SUPPORTS_THREADING
            lock (m_PoolLock)
            {
                m_WorkUnitPool.Add(inWorkUnit);
            }
            #else
            m_WorkUnitPool.Add(inWorkUnit);
            #endif // SUPPORTS_THREADING
        }
        // Allocates a work unit from the pool.
        private AsyncWorkUnit AllocUnitImpl()
        {
            #if SUPPORTS_THREADING
            lock (m_PoolLock)
            {
                #endif // SUPPORTS_THREADING

            int idx = m_WorkUnitPool.Count - 1;
            if (idx < 0)
            {
                return(new AsyncWorkUnit(this));
            }

            AsyncWorkUnit unit = m_WorkUnitPool[idx];
            m_WorkUnitPool.RemoveAt(idx);
            return(unit);

                #if SUPPORTS_THREADING
        }
            #endif // SUPPORTS_THREADING
        }
Beispiel #9
0
        // Processes scheduled work by time-slicing.
        private void ProcessBlockingQueue(Stopwatch inStopwatch, long inTotalBudget, long inSliceBudget, Queue <AsyncWorkUnit> ioQueue, bool inbCheckThread, ref long ioTicksRemaining)
        {
            #if SUPPORTS_THREADING
            if (inbCheckThread)
            {
                // if we have a running thread, don't process this frame
                lock (m_LockObject)
                {
                    if (m_Thread != null)
                    {
                        ioTicksRemaining = inTotalBudget - inStopwatch.ElapsedTicks;
                        return;
                    }
                }
            }
            #endif // SUPPORTS_THREADING

            if (m_NextBlockingTick > 0)
            {
                long current = Stopwatch.GetTimestamp();
                if (current < m_NextBlockingTick)
                {
                    ioTicksRemaining = inTotalBudget - inStopwatch.ElapsedTicks;
                    return;
                }

                m_NextBlockingTick = 0;
            }

            long timestamp = inStopwatch.ElapsedTicks;
            long cutoff    = timestamp + inSliceBudget;
            while (!Paused && ioTicksRemaining > 0 && ioQueue.Count > 0 && timestamp < cutoff && m_NextBlockingTick <= 0)
            {
                AsyncWorkUnit unit = ioQueue.Peek();

                AsyncWorkUnit.StepResult result = AsyncWorkUnit.StepResult.Incomplete;
                while (result.IsIncomplete() && ioTicksRemaining > 0 && !Paused && timestamp < cutoff && m_NextBlockingTick <= 0)
                {
                    result = unit.Step();
                    if (result.TickDelay > 0)
                    {
                        m_NextBlockingTick = Stopwatch.GetTimestamp() + result.TickDelay;
                    }

                    timestamp        = inStopwatch.ElapsedTicks;
                    ioTicksRemaining = inTotalBudget - timestamp;
                }

                if (!result.IsIncomplete())
                {
                    if (result.Type == AsyncWorkUnit.StepResultType.Complete)
                    {
                        m_Scheduler.Log("Completed {0}", unit);
                    }

                    ioQueue.Dequeue();
                    m_Scheduler.FreeUnit(unit);

                    timestamp        = inStopwatch.ElapsedTicks;
                    ioTicksRemaining = inTotalBudget - timestamp;
                }
            }
        }
Beispiel #10
0
        // Schedules work to the given priority worker.
        private void ScheduleImpl(AsyncWorkUnit inUnit)
        {
            AsyncWorker worker = GetWorker(inUnit.AsyncFlags);

            worker.Schedule(inUnit);
        }