Ejemplo n.º 1
0
        /// <summary>
        /// Workhorse of the JobManager. Waits until a job is assigned to it and then runs the work.
        /// Locks: m_ThreadStatsLock, threadlock, ThreadJob.SyncRoot
        /// </summary>
        private static void ThreadWorker()
        {
            ThreadObject me = new ThreadObject();

            try
            {
                m_ReadyStack.Add(me);

                while (true)
                {
                    if (!me.Signal.WaitOne(IdleThreadLifespan, false))
                    {
                        me.Status = ThreadStatus.ReadyToDie;
                        continue;
                    }

                    if (!m_Running || me.Status == ThreadStatus.Dead)
                    {
                        break;                         // quit
                    }
                    try
                    {
                        ThreadJob job = me.Job;
                        if (job == null)                         // sanity check
                        {
                            continue;
                        }

                        me.Status = ThreadStatus.Running;

                        if (job.DoWork())
                        {
                            m_Completed.Enqueue(job);
                        }
                    }
                    finally
                    {
                        me.Job = null;
                    }
                }
            }
            finally
            {
                if (me.Job != null)
                {
                    Console.WriteLine("Worker thread dying with non-null job!!");
                }

                me.Job = null;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Assigns work to threads and keeps house.
        /// Locks: m_ThreadStatsLock, threadlock, ThreadJob.SyncRoot
        /// </summary>
        private static void ThreadScheduler()
        {
            try
            {
                while (true)
                {
                    // move finished threads back into ready stack
                    for (int i = m_RunningArray.Count - 1; i >= 0; i--)
                    {
                        if (i >= m_RunningArray.Count)
                        {
                            continue;
                        }

                        ThreadObject thread = m_RunningArray[i] as ThreadObject;

                        // make sure the thread is alive, sanity check
                        if (!thread.Thread.IsAlive)
                        {
                            if (m_Running)                             // dead threads in running array is expected when we're shutting down
                            {
                                Console.WriteLine("Dead thread found in JobManager.m_RunningArray: {0}", thread.Thread.Name);
                            }
                            m_RunningArray.Remove(thread);
                            continue;
                        }

                        if (thread.Job == null)
                        {
                            m_RunningArray.Remove(thread);
                            m_ReadyStack.Add(thread);
                        }
                    }

                    // kill off threads that need to die
                    for (int i = m_ReadyStack.Count - 1; i >= 0 && CurrentThreadCount > MinThreadCount; i--)
                    {
                        if (i >= m_ReadyStack.Count)
                        {
                            continue;
                        }

                        ThreadObject thread = m_ReadyStack[i] as ThreadObject;
                        m_ReadyStack.Remove(thread);
                        if (thread.Status == ThreadStatus.ReadyToDie)
                        {
                            thread.Status = ThreadStatus.Dead;
                            thread.Signal.Set();                             // wake the thread up so it can see it needs to die
                        }
                    }

                    // if we're shutting down, pulse all the waiting threads so they shut down
                    if (!m_Running)
                    {
                        if (m_RunningArray.Count == 0 && m_ReadyStack.Count == 0)
                        {
                            break;                             // all the workers are dead, now we die
                        }
                        while (m_ReadyStack.Count > 0)
                        {
                            ThreadObject thread = m_ReadyStack[0] as ThreadObject;

                            thread.Status = ThreadStatus.Dead;
                            thread.Signal.Set();                             // wake the thread up so it can see it needs to die
                        }

                        continue;
                    }

                    // promote old jobs to a higher priority - no higher than High
                    // only one promotion per priority per iteration
                    DateTime promotion = DateTime.Now - TimeSpan.FromMilliseconds(PriorityPromotionDelay);
                    for (int i = (int)JobPriority.Low; i < (int)JobPriority.High; i++)
                    {
                        if (m_Jobs[i].Count == 0)
                        {
                            continue;
                        }

                        ThreadJob job = m_Jobs[i].Peek() as ThreadJob;
                        if (job.Enqueued < promotion)
                        {
                            m_Jobs[i + 1].Enqueue(m_Jobs[i].Dequeue());
                            job.ResetEnqueued();
                        }
                    }

                    // assign work
                    for (int i = (int)JobPriority.Critical; i >= (int)JobPriority.Idle; i--)
                    {
                        while (m_ReadyStack.Count > 0 && m_Jobs[i].Count > 0)
                        {
                            ThreadObject thread = m_ReadyStack[m_ReadyStack.Count - 1] as ThreadObject;
                            m_ReadyStack.Remove(thread);                             // don't use m_ReadyStack.Count - 1, possible to change
                            m_RunningArray.Add(thread);
                            thread.Job = m_Jobs[i].Dequeue() as ThreadJob;
                            thread.Signal.Set();                             // wake thread up
                        }
                    }

                    // make sure we've got the minimum # of threads
                    if (CurrentThreadCount < MinThreadCount)
                    {
                        Thread worker = new Thread(new ThreadStart(ThreadWorker));
                        worker.IsBackground = true;
                        worker.Start();
                    }

                    // see if we should create some more threads for critical tasks
                    for (int i = 0; i < m_Jobs[(int)JobPriority.Critical].Count; i++)
                    {
                        Thread worker = new Thread(new ThreadStart(ThreadWorker));
                        worker.IsBackground = true;
                        worker.Start();
                    }

                    // lastly, create one more thread if work is getting backed up long enough
                    if (m_Jobs[(int)JobPriority.High].Count > 0 &&                                // make sure there's a job in the first place
                        ((ThreadJob)m_Jobs[(int)JobPriority.High].Peek()).Enqueued < promotion && // check if it's overdue
                        CurrentThreadCount < MaxThreadCount)                                      // make sure we're not at max - main diff between this and promotion, crit gets new thread always
                    {
                        Thread worker = new Thread(new ThreadStart(ThreadWorker));
                        worker.IsBackground = true;
                        worker.Start();
                    }

                    Thread.Sleep(100);
                }
            }
            finally
            {
                m_Running = false;
            }
        }
Ejemplo n.º 3
0
		/// <summary>
		/// Workhorse of the JobManager. Waits until a job is assigned to it and then runs the work.
		/// Locks: m_ThreadStatsLock, threadlock, ThreadJob.SyncRoot
		/// </summary>
		private static void ThreadWorker()
		{
			ThreadObject me = new ThreadObject();
			try
			{
				m_ReadyStack.Add(me);

				while (true)
				{
					if (!me.Signal.WaitOne(IdleThreadLifespan, false))
					{
						me.Status = ThreadStatus.ReadyToDie;
						continue;
					}

					if (!m_Running || me.Status == ThreadStatus.Dead)
						break; // quit

					try
					{
						ThreadJob job = me.Job;
						if (job == null) // sanity check
							continue;

						me.Status = ThreadStatus.Running;
					
						if (job.DoWork())
						{
							m_Completed.Enqueue(job);
						}
					}
					finally
					{
						me.Job = null;
					}
				}
			}
			finally
			{
				if (me.Job != null)
					Console.WriteLine("Worker thread dying with non-null job!!");
				
				me.Job = null;
			}
		}