예제 #1
0
        /// <summary>
        /// Adds a job to the JobManager.
        /// Locks: JobManager.m_ThreadStatsLock
        /// </summary>
        /// <param name="job">The job to enqueue.</param>
        /// <param name="priority">The priority of the job.</param>
        /// <returns>True if added, false if queue was full.</returns>
        internal static bool Enqueue(ThreadJob job, JobPriority priority)
        {
            if (TotalEnqueuedJobs >= QueueLengthLimit && priority != JobPriority.Critical)
            {
                try
                {
                    bool print = false;
                    using (TimedLock.Lock(m_ThreadStatsLock))
                    {
                        if (m_LastError != 2)
                        {
                            print = true;
                        }
                        m_LastError = 2;
                    }
                    if (print)
                    {
                        Console.WriteLine("{0} JM Error: Rejected job because queue was full.", DateTime.Now);
                    }
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Exception Caught in JobManager code: " + e.Message);
                    System.Console.WriteLine(e.StackTrace);
                }
                return(false);
            }

            if (TotalEnqueuedJobs >= QueueLengthLimit / 2)
            {
                try
                {
                    bool print = false;
                    using (TimedLock.Lock(m_ThreadStatsLock))
                    {
                        if (m_LastError != 1)
                        {
                            print = true;
                        }
                        m_LastError = 1;
                    }
                    if (print)
                    {
                        Console.WriteLine("{0} JM Warning: Queue length exceeds half of hard limit.", DateTime.Now);
                    }
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Exception Caught in JobManager code: " + e.Message);
                    System.Console.WriteLine(e.StackTrace);
                    return(false);
                }
            }

            m_Jobs[(int)priority].Enqueue(job);

            return(true);
        }
예제 #2
0
 public ThreadObject()
 {
     SyncRoot      = new object();
     m_Thread      = Thread.CurrentThread;
     m_Thread.Name = String.Format("JobWorker {0}", m_NextID++);
     m_Job         = null;
     m_Status      = ThreadStatus.Running;
     m_Signal      = new AutoResetEvent(false);
 }
예제 #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;
            }
        }
예제 #4
0
		/// <summary>
		/// Adds a job to the JobManager.
		/// Locks: JobManager.m_ThreadStatsLock
		/// </summary>
		/// <param name="job">The job to enqueue.</param>
		/// <param name="priority">The priority of the job.</param>
		/// <returns>True if added, false if queue was full.</returns>
		internal static bool Enqueue(ThreadJob job, JobPriority priority)
		{
			if (TotalEnqueuedJobs >= QueueLengthLimit && priority != JobPriority.Critical)
			{
                try
                {
                    bool print = false;
                    using (TimedLock.Lock(m_ThreadStatsLock))
                    {
                        if (m_LastError != 2)
                            print = true;
                        m_LastError = 2;
                    }
                    if (print)
                        Console.WriteLine("{0} JM Error: Rejected job because queue was full.", DateTime.Now);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Exception Caught in JobManager code: " + e.Message);
                    System.Console.WriteLine(e.StackTrace);
                }
				return false;
			}

			if (TotalEnqueuedJobs >= QueueLengthLimit / 2)
			{
                try
                {
                    bool print = false;
                    using (TimedLock.Lock(m_ThreadStatsLock))
                    {
                        if (m_LastError != 1)
                            print = true;
                        m_LastError = 1;
                    }
                    if (print)
                        Console.WriteLine("{0} JM Warning: Queue length exceeds half of hard limit.", DateTime.Now);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Exception Caught in JobManager code: " + e.Message);
                    System.Console.WriteLine(e.StackTrace);
                    return false;
                }
			}

			m_Jobs[(int)priority].Enqueue(job);

			return true;
		}
예제 #5
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;
            }
        }
예제 #6
0
		public ThreadObject()
		{
			SyncRoot = new object();
			m_Thread = Thread.CurrentThread;
			m_Thread.Name = String.Format("JobWorker {0}", m_NextID++);
			m_Job = null;
			m_Status = ThreadStatus.Running;
			m_Signal = new AutoResetEvent(false);
		}
예제 #7
0
 public static void StressCallback(ThreadJob job)
 {
     Console.WriteLine("Callback with results for job {0}", job.Results);
 }
예제 #8
0
        public static void StressTester()
        {
            ThreadJob job = new ThreadJob(new JobWorker(StressWorker), Utility.RandomMinMax(50, 5000), new JobCompletedCallback(StressCallback));

            job.Start((JobPriority)Utility.RandomMinMax(0, 4));
        }
예제 #9
0
		public static void StressCallback(ThreadJob job)
		{
			Console.WriteLine("Callback with results for job {0}", job.Results);
		}
예제 #10
0
		public static void StressTester()
		{	
			ThreadJob job = new ThreadJob(new JobWorker(StressWorker), Utility.RandomMinMax(50, 5000), new JobCompletedCallback(StressCallback));
			job.Start((JobPriority)Utility.RandomMinMax(0, 4));
		}