Inheritance: IDisposable
示例#1
0
		public ThreadWorker (IScheduler sched, ThreadWorker[] others, IProducerConsumerCollection<Task> sharedWorkQueue,
		                     bool createThread, int maxStackSize, ThreadPriority priority)
		{
			this.others          = others;

//			if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("USE_CYCLIC"))) {
//				Console.WriteLine ("Using cyclic deque");
//				this.dDeque = new CyclicDeque<Task> ();
//			} else {
//				this.dDeque = new DynamicDeque<Task> ();
//			}
			this.dDeque = new CyclicDeque<Task> ();
			
			this.sharedWorkQueue = sharedWorkQueue;
			this.workerLength    = others.Length;
			this.isLocal         = !createThread;
			
			this.childWorkAdder = delegate (Task t) { 
				dDeque.PushBottom (t);
				sched.PulseAll ();
			};
			
			// Find the stealing start index randomly (then the traversal
			// will be done in Round-Robin fashion)
			do {
				this.stealingStart = r.Next(0, workerLength);
			} while (others[stealingStart] == this);
			
			InitializeUnderlyingThread (maxStackSize, priority);
		}
示例#2
0
		public ThreadWorker (IScheduler sched, ThreadWorker[] others, IProducerConsumerCollection<Task> sharedWorkQueue,
		                     bool createThread, int maxStackSize, ThreadPriority priority, EventWaitHandle handle)
		{
			this.others          = others;

			this.dDeque = new CyclicDeque<Task> ();
			
			this.sharedWorkQueue = sharedWorkQueue;
			this.workerLength    = others.Length;
			this.isLocal         = !createThread;
			this.waitHandle      = handle;
			
			this.childWorkAdder = delegate (Task t) { 
				dDeque.PushBottom (t);
				sched.PulseAll ();
			};
			
			// Find the stealing start index randomly (then the traversal
			// will be done in Round-Robin fashion)
			do {
				this.stealingStart = r.Next(0, workerLength);
			} while (others[stealingStart] == this);
			
			InitializeUnderlyingThread (maxStackSize, priority);
		}
		public Scheduler (int maxWorker, int maxStackSize, ThreadPriority priority)
		{
			workQueue = new ConcurrentQueue<Task> ();
			workers = new ThreadWorker [maxWorker];
			
			for (int i = 0; i < maxWorker; i++) {
				workers [i] = new ThreadWorker (this, workers, workQueue, maxStackSize, priority);
			}
		}
示例#4
0
文件: Scheduler.cs 项目: koush/mono
		public Scheduler (int maxWorker, ThreadPriority priority)
		{
			workQueue = new ConcurrentQueue<Task> ();
			workers = new ThreadWorker [maxWorker];
			
			for (int i = 0; i < maxWorker; i++) {
				workers [i] = new ThreadWorker (workers, i, workQueue, new CyclicDeque<Task> (), priority, pulseHandle);
				workers [i].Pulse ();
			}
		}
示例#5
0
        static void Main(string[] args)
        {
            Thread.Sleep(5000);
            Console.WriteLine("Background auto mail program started");
            ThreadWorker worker = new ThreadWorker();
            worker.ThreadDone += worker_ThreadDone;
            Console.WriteLine("Object created and method assigned...");

            Thread thread1 = new Thread(worker.Run);
            thread1.Start();

            _count = 0;
        }
示例#6
0
        static void worker_ThreadDone(object sender, EventArgs e)
        {
            Thread.Sleep(10000);
            Console.WriteLine("New thread!");
            Console.WriteLine("Count: " + _count);
            ThreadWorker worker = new ThreadWorker();
            worker.ThreadDone += worker_ThreadDone;

            Thread thread2 = new Thread(worker.Run);
            thread2.Start();

            _count++;
        }
示例#7
0
文件: ThreadWorker.cs 项目: ztzg/mono
		public ThreadWorker (ThreadWorker[] others,
		                     int workerPosition,
		                     IProducerConsumerCollection<Task> sharedWorkQueue,
		                     IConcurrentDeque<Task> dDeque,
		                     ThreadPriority priority,
		                     ManualResetEvent handle)
		{
			this.others          = others;
			this.dDeque          = dDeque;
			this.sharedWorkQueue = sharedWorkQueue;
			this.workerLength    = others.Length;
			this.workerPosition  = workerPosition;
			this.waitHandle      = handle;
			this.threadPriority  = priority;

			InitializeUnderlyingThread ();
		}
		public ThreadWorker (IScheduler sched,
		                     ThreadWorker[] others,
		                     int workerPosition,
		                     IProducerConsumerCollection<Task> sharedWorkQueue,
		                     ThreadPriority priority,
		                     EventWaitHandle handle)
		{
			this.others          = others;
			this.dDeque          = new CyclicDeque<Task> ();
			this.sched           = sched;
			this.sharedWorkQueue = sharedWorkQueue;
			this.workerLength    = others.Length;
			this.workerPosition  = workerPosition;
			this.waitHandle      = handle;
			this.threadPriority  = priority;

			InitializeUnderlyingThread ();
		}
示例#9
0
        public override bool Equals(object obj)
        {
            ThreadWorker temp = obj as ThreadWorker;

            return(temp == null ? false : Equals(temp));
        }
示例#10
0
 public bool Equals(ThreadWorker other)
 {
     return((other == null) ? false : object.ReferenceEquals(this.dDeque, other.dDeque));
 }
示例#11
0
		// Almost same as above but with an added predicate and treating one item at a time. 
		// It's used by Scheduler Participate(...) method for special waiting case like
		// Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
		// Predicate should be really fast and not blocking as it is called a good deal of time
		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
		public static void ParticipativeWorkerMethod (Task self,
		                                              ManualResetEventSlim predicateEvt,
		                                              int millisecondsTimeout,
		                                              IProducerConsumerCollection<Task> sharedWorkQueue,
		                                              ThreadWorker[] others,
		                                              ManualResetEvent evt)
		{
			const int stage1 = 5, stage2 = 0;
			int tries = 8;
			WaitHandle[] handles = null;
			Watch watch = Watch.StartNew ();
			if (millisecondsTimeout == -1)
				millisecondsTimeout = int.MaxValue;

			while (!predicateEvt.IsSet && watch.ElapsedMilliseconds < millisecondsTimeout) {
				Task value;
				
				// If we are in fact a normal ThreadWorker, use our own deque
				if (autoReference != null) {
					while (autoReference.dDeque.PopBottom (out value) == PopResult.Succeed && value != null) {
						evt.Set ();
						if (CheckTaskFitness (self, value))
							value.Execute (autoReference.ChildWorkAdder);
						else {
							sharedWorkQueue.TryAdd (value);
							evt.Set ();
						}

						if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
							return;
					}
				}

				int count = sharedWorkQueue.Count;

				// Dequeue only one item as we have restriction
				while (--count >= 0 && sharedWorkQueue.TryTake (out value) && value != null) {
					evt.Set ();
					if (CheckTaskFitness (self, value))
						value.Execute (null);
					else {
						if (autoReference == null)
							sharedWorkQueue.TryAdd (value);
						else
							autoReference.dDeque.PushBottom (value);
						evt.Set ();
					}

					if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
						return;
				}

				// First check to see if we comply to predicate
				if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
					return;
				
				// Try to complete other work by stealing since our desired tasks may be in other worker
				ThreadWorker other;
				for (int i = 0; i < others.Length; i++) {
					if ((other = others [i]) == autoReference || other == null)
						continue;

					if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) {
						evt.Set ();
						if (CheckTaskFitness (self, value))
							value.Execute (null);
						else {
							if (autoReference == null)
								sharedWorkQueue.TryAdd (value);
							else
								autoReference.dDeque.PushBottom (value);
							evt.Set ();
						}
					}

					if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
						return;
				}

				if (--tries > stage1)
					Thread.Yield ();
				else if (tries >= stage2)
					predicateEvt.Wait (ComputeTimeout (100, millisecondsTimeout, watch));
				else {
					if (tries == stage2 - 1)
						handles = new [] { predicateEvt.WaitHandle, evt };
					WaitHandle.WaitAny (handles, ComputeTimeout (1000, millisecondsTimeout, watch));
				}
			}
		}
		public ThreadWorker (IScheduler sched, ThreadWorker[] others, IProducerConsumerCollection<Task> sharedWorkQueue,
		                     int maxStackSize, ThreadPriority priority)
			: this (sched, others, sharedWorkQueue, true, maxStackSize, priority)
		{
		}
		public bool Equals (ThreadWorker other)
		{
			return (other == null) ? false : object.ReferenceEquals (this.dDeque, other.dDeque);	
		}
		// Almost same as above but with an added predicate and treating one item at a time. 
		// It's used by Scheduler Participate(...) method for special waiting case like
		// Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
		// Predicate should be really fast and not blocking as it is called a good deal of time
		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
		public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue,
		                                 ThreadWorker[] others)
		{
			while (!predicate ()) {
				Task value;
				
				// Dequeue only one item as we have restriction
				if (sharedWorkQueue.TryTake (out value)) {
					if (value != null) {
						if (CheckTaskFitness (value))
							value.Execute (null);
						else
							sharedWorkQueue.TryAdd (value);
					}
				}
				
				// First check to see if we comply to predicate
				if (predicate ()) {
					return;
				}
				
				// Try to complete other work by stealing since our desired tasks may be in other worker
				ThreadWorker other;
				for (int i = 0; i < others.Length; i++) {
					if ((other = others [i]) == null)
						continue;
					
					if (other.dDeque.PopTop (out value) == PopResult.Succeed) {
						if (value != null) {
							if (CheckTaskFitness (value))
								value.Execute (null);
							else
								sharedWorkQueue.TryAdd (value);
						}
					}
					
					if (predicate ()) {
						return;
					}
				}
			}
		}
示例#15
0
		// Almost same as above but with an added predicate and treating one item at a time. 
		// It's used by Scheduler Participate(...) method for special waiting case like
		// Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
		// Predicate should be really fast and not blocking as it is called a good deal of time
		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
		public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue,
		                                 ThreadWorker[] others, ManualResetEvent evt)
		{
			while (!predicate ()) {
				Task value;
				
				// If we are in fact a normal ThreadWorker, use our own deque
				if (autoReference != null) {
					while (autoReference.dDeque.PopBottom (out value) == PopResult.Succeed && value != null) {
						evt.Set ();
						if (CheckTaskFitness (value))
							value.Execute (autoReference.ChildWorkAdder);
						else {
							autoReference.dDeque.PushBottom (value);
							evt.Set ();
						}

						if (predicate ())
							return;
					}
				}

				// Dequeue only one item as we have restriction
				while (sharedWorkQueue.TryTake (out value) && value != null) {
					evt.Set ();
					if (CheckTaskFitness (value))
						value.Execute (null);
					else {
						sharedWorkQueue.TryAdd (value);
						evt.Set ();
					}

					if (predicate ())
						return;
				}

				// First check to see if we comply to predicate
				if (predicate ())
					return;
				
				// Try to complete other work by stealing since our desired tasks may be in other worker
				ThreadWorker other;
				for (int i = 0; i < others.Length; i++) {
					if ((other = others [i]) == null)
						continue;
					
					if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) {
						evt.Set ();
						if (CheckTaskFitness (value))
							value.Execute (null);
						else {
							sharedWorkQueue.TryAdd (value);
							evt.Set ();
						}
					}
					
					if (predicate ())
						return;
				}

				Thread.Yield ();
			}
		}
示例#16
0
		// This is the actual method called in the Thread
		void WorkerMethodWrapper ()
		{
			int sleepTime = 0;
			autoReference = this;
			
			// Main loop
			while (started == 1) {
				bool result = false;

				result = WorkerMethod ();
				if (!result)
					waitHandle.Reset ();

				Thread.Yield ();

				if (result) {
					deepSleepTime = 8;
					sleepTime = 0;
					continue;
				}

				// If we are spinning too much, have a deeper sleep
				if (++sleepTime > sleepThreshold && sharedWorkQueue.Count == 0) {
					waitHandle.WaitOne ((deepSleepTime =  deepSleepTime >= 0x4000 ? 0x4000 : deepSleepTime << 1));
				}
			}

			started = 0;
		}
示例#17
0
 // Called with Task.WaitAll(someTasks) or Task.WaitAny(someTasks) so that we can remove ourselves
 // also when our wait condition is ok
 public void ParticipateUntil(Func <bool> predicate)
 {
     ThreadWorker.WorkerMethod(predicate, workQueue, workers);
 }
示例#18
0
文件: Scheduler.cs 项目: yonder/mono
 internal void ParticipateUntilInternal(Task self, ManualResetEventSlim evt, int millisecondsTimeout)
 {
     ThreadWorker.ParticipativeWorkerMethod(self, evt, millisecondsTimeout, workQueue, workers, pulseHandle);
 }
示例#19
0
		// Almost same as above but with an added predicate and treating one item at a time. 
		// It's used by Scheduler Participate(...) method for special waiting case like
		// Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
		// Predicate should be really fast and not blocking as it is called a good deal of time
		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
		public static void ParticipativeWorkerMethod (Task self,
		                                              ManualResetEventSlim predicateEvt,
		                                              int millisecondsTimeout,
		                                              IProducerConsumerCollection<Task> sharedWorkQueue,
		                                              ThreadWorker[] others,
		                                              ManualResetEvent evt)
		{
			const int stage1 = 5, stage2 = 0;
			int tries = 50;
			WaitHandle[] handles = null;
			Watch watch = Watch.StartNew ();
			if (millisecondsTimeout == -1)
				millisecondsTimeout = int.MaxValue;
			bool aggressive = false;
			bool hasAutoReference = autoReference != null;
			Action<Task> adder = null;

			while (!predicateEvt.IsSet && watch.ElapsedMilliseconds < millisecondsTimeout && !self.IsCompleted) {
				// We try to execute the self task as it may be the simplest way to unlock
				// the situation
				if (self.Status == TaskStatus.WaitingToRun) {
					self.Execute (hasAutoReference ? autoReference.adder : (Action<Task>)null);
					if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
						return;
				}

				Task value;
				
				// If we are in fact a normal ThreadWorker, use our own deque
				if (hasAutoReference) {
					var enumerable = autoReference.dDeque.GetEnumerable ();
					if (adder == null)
						adder = hasAutoReference ? autoReference.adder : (Action<Task>)null;

					if (enumerable != null) {
						foreach (var t in enumerable) {
							if (t == null)
								continue;

							if (CheckTaskFitness (self, t))
								t.Execute (adder);

							if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
								return;
						}
					}
				}

				int count = sharedWorkQueue.Count;

				// Dequeue only one item as we have restriction
				while (--count >= 0 && sharedWorkQueue.TryTake (out value) && value != null) {
					evt.Set ();
					if (CheckTaskFitness (self, value) || aggressive)
						value.Execute (null);
					else {
						if (autoReference == null)
							sharedWorkQueue.TryAdd (value);
						else
							autoReference.dDeque.PushBottom (value);
						evt.Set ();
					}

					if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
						return;
				}

				// First check to see if we comply to predicate
				if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
					return;
				
				// Try to complete other work by stealing since our desired tasks may be in other worker
				ThreadWorker other;
				for (int i = 0; i < others.Length; i++) {
					if ((other = others [i]) == autoReference || other == null)
						continue;

					if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) {
						evt.Set ();
						if (CheckTaskFitness (self, value) || aggressive)
							value.Execute (null);
						else {
							if (autoReference == null)
								sharedWorkQueue.TryAdd (value);
							else
								autoReference.dDeque.PushBottom (value);
							evt.Set ();
						}
					}

					if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout)
						return;
				}

				/* Waiting is split in 4 phases
				 *   - until stage 1 we simply yield the thread to let others add data
				 *   - between stage 1 and stage2 we use ManualResetEventSlim light waiting mechanism
				 *   - after stage2 we fall back to the heavier WaitHandle waiting mechanism
				 *   - if really the situation isn't evolving after a couple of sleep, we disable
				 *     task fitness check altogether
				 */
				if (--tries > stage1)
					Thread.Yield ();
				else if (tries >= stage2)
					predicateEvt.Wait (ComputeTimeout (5, millisecondsTimeout, watch));
				else {
					if (tries == stage2 - 1)
						handles = new [] { predicateEvt.WaitHandle, evt };
					WaitHandle.WaitAny (handles, ComputeTimeout (1000, millisecondsTimeout, watch));
					if (tries == stage2 - 10)
						aggressive = true;
				}
			}
		}