public void CopyTo() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Create a new array of size 5. PriorityValuePair <int>[] arrayCopy = new PriorityValuePair <int> [5]; // Enqueue 3 elements into the queue. PriorityValuePair <int> elem = new PriorityValuePair <int>(3.0, 6); queue.Enqueue(1.0, 2); queue.Enqueue(elem); queue.Enqueue(2.0, 4); // Copy the queue data to the array, starting from index 1 (not 0). queue.CopyTo(arrayCopy, 1); // Expect the first array index to be unset, but all the rest to be set. // Note: The order of elements after the first can't be guaranteed, because the heap // implementing the queue internally doesn't store things in an exact linear order, // but we can be sure that the elements aren't going to be equal to null because we // set them. Assert.That(arrayCopy[0], Is.EqualTo(null)); Assert.That(arrayCopy[1], Is.EqualTo(elem)); Assert.That(arrayCopy[2], Is.Not.EqualTo(null)); Assert.That(arrayCopy[3], Is.Not.EqualTo(null)); Assert.That(arrayCopy[4], Is.EqualTo(null)); }
Enqueue(double priority, WaitCallback callback, object context = null) { if (IsStopping) { // We want to block new tasks from being queued while the task runner is trying to // shut down, so that it can successfully stop instead of being bogged down by new // tasks forever. throw new InvalidOperationException("Cannot enqueue tasks while the task runner is stopping."); } // Create a new task, wrap it in a PriorityValuePair, and enqueue it. Task task = new Task(context, callback); PriorityValuePair <Task> elem = new PriorityValuePair <Task>(priority, task); __queue.Enqueue(elem); // Mark the task as waiting to complete. onWaitingTask(elem); // Subscribe an event listener to the task's CallbackReturned event that will release // the task resources and allow another to run. ManualResetEvent resetEvent = new ManualResetEvent(false); task.TaskComplete += delegate { onCompletedTask(elem); resetEvent.Set(); }; // Return the ManualResetEvent to the caller so they can be aware of when this task // finishes execution. return(resetEvent); }
public void PopValue() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Try to PopPriority() and expect an NullReferenceException to be thrown. Assert.Throws <NullReferenceException>(() => { heap.PopValue(); }); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Store an element and insert it into the heap. PriorityValuePair <int> elem = new PriorityValuePair <int>(1f, 2); heap.Push(elem); // Ensure that the element was inserted into the heap. Assert.That(heap.Peek(), Is.EqualTo(elem)); // Ensure that the value of the pushed element is returned. Assert.That(heap.PopValue(), Is.EqualTo(2)); // Ensure that the element was removed from the heap. Assert.That(heap.Count, Is.EqualTo(0)); }
public void Remove() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Create and store a few elements. PriorityValuePair <int> elem1 = new PriorityValuePair <int>(1f, 2); PriorityValuePair <int> elem2 = new PriorityValuePair <int>(2f, 4); PriorityValuePair <int> elem3 = new PriorityValuePair <int>(3f, 6); // Expect Remove() to return null for an empty heap. Assert.That(heap.Remove(elem1), Is.EqualTo(false)); // Insert 2 of the elements into the heap. heap.Push(elem2); heap.Push(elem3); // Expect Remove() to return false for elem1, indicating the element was removed // (since it doesn't belong to the heap and can't be found). This tests the if-else // case for when the provided element isn't found in the heap. Assert.That(heap.Remove(elem1), Is.False); // Expect Remove() to return true for elem2, indicating the element was removed // (since it belongs to the heap and can be found). This tests the if-else case for // when Count is 2 or greater. Assert.That(heap.Remove(elem2), Is.True); // Expect Remove() to return true for elem3, indicating the element was removed // (since it belongs to the heap and can be found). This tests the if-else case for // when Count equals 1. Assert.That(heap.Remove(elem3), Is.True); }
public void Pop() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Expect Pop() to return null for an empty heap. Assert.That(heap.Pop(), Is.EqualTo(null)); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Store an element and insert it into the heap. PriorityValuePair <int> elem = new PriorityValuePair <int>(1f, 2); heap.Push(elem); // Ensure that the element was inserted into the heap. Assert.That(heap.Count, Is.EqualTo(1)); Assert.That(heap.Peek(), Is.EqualTo(elem)); // Ensure that the returned element points to the same object we stored earlier. Assert.That(heap.Pop(), Is.EqualTo(elem)); // Ensure that the element was removed from the heap. Assert.That(heap.Count, Is.EqualTo(0)); }
public void Peek() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Expect Peek() to return null for an empty heap. Assert.That(heap.Peek(), Is.EqualTo(null)); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Store an element and insert it into the heap. PriorityValuePair <int> elem1 = new PriorityValuePair <int>(1f, 2); heap.Push(elem1); // Ensure that the element was inserted into the heap as the root element. Assert.That(heap.Count, Is.EqualTo(1)); Assert.That(heap.Peek(), Is.EqualTo(elem1)); // Ensure that the element was not removed from the heap. Assert.That(heap.Count, Is.EqualTo(1)); // Insert another element with higher priority than the last. PriorityValuePair <int> elem2 = new PriorityValuePair <int>(2f, 4); heap.Push(elem2); // Ensure that Peak() returns the new root element. Assert.That(heap.Peek(), Is.EqualTo(elem2)); }
public void CopyTo() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Create a new array of size 5. PriorityValuePair <int>[] arrayCopy = new PriorityValuePair <int> [5]; // Push 3 elements onto the queue. PriorityValuePair <int> elem = new PriorityValuePair <int>(3f, 6); heap.Push(1f, 2); heap.Push(elem); heap.Push(2f, 4); // Copy the heap data to the array, starting from index 1 (not 0). heap.CopyTo(arrayCopy, 1); // Expect the first array index to be unset, but all the rest to be set. // Note: The order of elements after the first can't be guaranteed, because the heap // doesn't store things in an exact linear order, but we can be sure that the elements // aren't going to be equal to null because we set them. Assert.That(arrayCopy[0], Is.EqualTo(null)); Assert.That(arrayCopy[1], Is.EqualTo(elem)); Assert.That(arrayCopy[2], Is.Not.EqualTo(null)); Assert.That(arrayCopy[3], Is.Not.EqualTo(null)); Assert.That(arrayCopy[4], Is.EqualTo(null)); }
public void Remove() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Create and store a few elements. PriorityValuePair <int> elem1 = new PriorityValuePair <int>(1.0, 2); PriorityValuePair <int> elem2 = new PriorityValuePair <int>(2.0, 4); PriorityValuePair <int> elem3 = new PriorityValuePair <int>(3.0, 6); // Expect Remove() to return false for an empty queue. Assert.That(queue.Remove(elem1), Is.False); // Enqueue 2 of the elements into the heap. queue.Enqueue(elem2); queue.Enqueue(elem3); // Expect Remove() to return false for elem1, indicating the element was removed // (since it doesn't belong to the heap and can't be found). This tests the if-else // case for when the provided element isn't found in the heap. Assert.That(queue.Remove(elem1), Is.False); // Expect Remove() to return true for elem2, indicating the element was removed // (since it belongs to the heap and can be found). This tests the if-else case for // when Count is 2 or greater. Assert.That(queue.Remove(elem2), Is.True); // Expect Remove() to return true for elem3, indicating the element was removed // (since it belongs to the heap and can be found). This tests the if-else case for // when Count equals 1. Assert.That(queue.Remove(elem3), Is.True); }
ThreadProc() { // Change state to indicate that the task runner is started. __state = TaskRunnerState.Running; // Emit an event to notify listeners that the task runner started up. if (Started != null) { Started(); } // Continue looping until Stop() is called and all critical tasks are finished. while (!IsStopping || IsStopping && HasEnqueuedCriticalTasks) { // Most of this is only important if something is in the queue. if (RunningTasks < ThreadPoolMaxThreads && __queue.Peek() != null) { // Execute the task on the thread pool. PriorityValuePair <Task> elem = __queue.Dequeue(); Task task = elem.Value; if (task != null) { // We're passing a null context here because the task is packaged with its // own execution context that will be inserted during Task.Run(). ThreadPool.QueueUserWorkItem((x) => { task.Run(); }, null); } // Mark the task as starting execution. // Note: This should run even if the task is null above, otherwise the counts // for the number of running/waiting tasks will become skewed. onRunningTask(elem); } else { // Yield the rest of the time slice. Thread.Sleep(1); } } // Wait for all critical tasks to finish running before stopping. while (HasWaitingCriticalTasks) { Thread.Sleep(1); } // Flag the task runner as stopped. __state = TaskRunnerState.Stopped; __thread = null; // Emit an event to notify listeners that the task runner stopped. if (Stopped != null) { Stopped(); } }
public void Dequeue() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Ensure that the heap is empty. Assert.That(queue.Count, Is.EqualTo(0)); // Expect Dequeue() to return null for an empty heap. Assert.That(queue.Dequeue(), Is.EqualTo(null)); // Ensure that the heap is empty. Assert.That(queue.Count, Is.EqualTo(0)); // Store an element and insert it into the heap. PriorityValuePair <int> elem = new PriorityValuePair <int>(1.0, 2); queue.Enqueue(elem); // Ensure that the element was inserted into the heap. Assert.That(queue.Count, Is.EqualTo(1)); Assert.That(queue.Peek(), Is.EqualTo(elem)); // Ensure that the PriorityAdjustment was incremented. Assert.That(queue.PriorityAdjustment, Is.EqualTo(ConcurrentPriorityQueue <int> .EPSILON)); // Ensure that the returned element points to the same object we stored earlier. Assert.That(queue.Dequeue(), Is.EqualTo(elem)); // Ensure that the element was removed from the heap. Assert.That(queue.Count, Is.EqualTo(0)); // Ensure that the PriorityAdjustment was reset once the queue became empty. Assert.That(queue.PriorityAdjustment, Is.EqualTo(0.0)); // Enqueue 5 items with the same priority. PriorityValuePair <int> elem2 = new PriorityValuePair <int>(2.0, 0); PriorityValuePair <int> elem3 = new PriorityValuePair <int>(2.0, 2); PriorityValuePair <int> elem4 = new PriorityValuePair <int>(2.0, 4); PriorityValuePair <int> elem5 = new PriorityValuePair <int>(2.0, 6); PriorityValuePair <int> elem6 = new PriorityValuePair <int>(2.0, 8); queue.Enqueue(elem2); queue.Enqueue(elem3); queue.Enqueue(elem4); queue.Enqueue(elem5); queue.Enqueue(elem6); //// Ensure that Dequeue() returns the items in the order they were enqueued. Assert.That(queue.Dequeue(), Is.EqualTo(elem2)); Assert.That(queue.Dequeue(), Is.EqualTo(elem3)); Assert.That(queue.Dequeue(), Is.EqualTo(elem4)); Assert.That(queue.Dequeue(), Is.EqualTo(elem5)); Assert.That(queue.Dequeue(), Is.EqualTo(elem6)); }
onRunningTask(PriorityValuePair <Task> elem) { #region Increment counters // Based on its priority, increment the appropriate active counter. if (elem.Priority >= MinCriticalPriority) { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__runningCriticalTasksLock); try { __runningCriticalTasks++; } finally { Monitor.Exit(__runningCriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } else { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__runningNoncriticalTasksLock); try { __runningNoncriticalTasks++; } finally { Monitor.Exit(__runningNoncriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } #endregion #region Emit events // Emit an event to notify listeners that a task has begun executing. if (TaskStarted != null) { TaskStarted(); } // Emit an event to notify listeners that the queue is empty (if so). if (QueueEmpty != null && __queue.Peek() != null) { QueueEmpty(); } #endregion }
public void SwapElements() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Enqueue an element into the queue. var elem1 = new PriorityValuePair <int>(2f, 4); heap.Push(elem1); // Ensure that the element was inserted. Assert.That(heap.Count, Is.EqualTo(1)); Assert.That(heap.Peek(), Is.EqualTo(elem1)); // Try to HeapSwapElements() while the queue only contains 1 element and expect an // InvalidOperationException to be thrown. Assert.Throws <InvalidOperationException>(() => { heap.SwapElements(0, 1); }); // Enqueue another element with higher priority than the last. var elem2 = new PriorityValuePair <int>(1f, 2); heap.Push(elem2); // Ensure that the element was inserted and that the 1st (higher priority) element is // still at the root of the heap. Assert.That(heap.Count, Is.EqualTo(2)); Assert.That(heap.Peek(), Is.EqualTo(elem1)); // Try to HeapSwapElements() with an invalid index1 and expect an // ArgumentOutOfRangeException to be thrown. Assert.Throws <ArgumentOutOfRangeException>(() => { heap.SwapElements(-1, 1); }); // Try to HeapSwapElements() with an invalid index2 and expect an // ArgumentOutOfRangeException to be thrown. Assert.Throws <ArgumentOutOfRangeException>(() => { heap.SwapElements(0, -1); }); // Actually swap elements now. heap.SwapElements(0, 1); // Ensure that the elements were swapped. Assert.That(heap.Count, Is.EqualTo(2)); Assert.That(heap.Peek(), Is.EqualTo(elem2)); Assert.That(heap.Contains(elem1), Is.True); }
public void Peek() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Ensure that the heap is empty. Assert.That(queue.Count, Is.EqualTo(0)); // Expect Peek() to return null for an empty heap. Assert.That(queue.Peek(), Is.EqualTo(null)); // Ensure that the queue is empty. Assert.That(queue.Count, Is.EqualTo(0)); // Store an element and insert it into the queue. PriorityValuePair <int> elem1 = new PriorityValuePair <int>(1.0, 2); queue.Enqueue(elem1); // Ensure that the element was inserted into the queue at the front. Assert.That(queue.Count, Is.EqualTo(1)); Assert.That(queue.Peek(), Is.EqualTo(elem1)); // Ensure that the element was not removed from the heap. Assert.That(queue.Count, Is.EqualTo(1)); // Insert another element with higher priority than the last. PriorityValuePair <int> elem2 = new PriorityValuePair <int>(2.0, 4); queue.Enqueue(elem2); // Ensure that Peek() returns the new front element. Assert.That(queue.Peek(), Is.EqualTo(elem2)); // Insert another element with the same priority as the last. PriorityValuePair <int> elem3 = new PriorityValuePair <int>(2.0, 6); queue.Enqueue(elem3); // Ensure that Peek() returns still returns the first value with that priority. Assert.That(queue.Peek(), Is.EqualTo(elem2)); // Remove the element from the queue. queue.Dequeue(); // Ensure that Peek() returns now returns the other value with the same priorty. Assert.That(queue.Peek(), Is.EqualTo(elem3)); }
public void Contains() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Create and store a new element. PriorityValuePair <int> elem = new PriorityValuePair <int>(1f, 2); // Ensure the queue contains the element. Assert.That(heap.Contains(elem), Is.False); // Push it onto the heap. heap.Push(elem); // Ensure the queue now contains the element. Assert.That(heap.Contains(elem), Is.True); }
public void Contains() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Create and store a new element. PriorityValuePair <int> elem = new PriorityValuePair <int>(1.0, 2); // Ensure the queue contains the element. Assert.That(queue.Contains(elem), Is.False); // Enqueue it in the queue. queue.Enqueue(elem); // Ensure the queue now contains the element. Assert.That(queue.Contains(elem), Is.True); }
onWaitingTask(PriorityValuePair <Task> elem) { #region Increment counters // Based on its priority, increment the appropriate waiting counter. if (elem.Priority >= MinCriticalPriority) { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__waitingCriticalTasksLock); try { __waitingCriticalTasks++; } finally { Monitor.Exit(__waitingCriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } else { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__waitingNoncriticalTasksLock); try { __waitingNoncriticalTasks++; } finally { Monitor.Exit(__waitingNoncriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } #endregion #region Emit events // Emit an event to notify listeners that a task has been enqueued. if (TaskEnqueued != null) { TaskEnqueued(); } #endregion }
public void EnqueueElement() { // Create a new priority queue. ConcurrentPriorityQueue <int> queue = new ConcurrentPriorityQueue <int>(); // Ensure that the queue is empty. Assert.That(queue.Count, Is.EqualTo(0)); // Store an element and insert it into the queue. PriorityValuePair <int> elem = new PriorityValuePair <int>(1.0, 2); queue.Enqueue(elem); // Ensure that the element was inserted into the queue. Assert.That(queue.Peek(), Is.EqualTo(elem)); // Store another element with higher priority and insert it as well. elem = new PriorityValuePair <int>(2.0, 4); queue.Enqueue(elem); // Ensure that the element was inserted into the queue and is at the front. Assert.That(queue.Peek(), Is.EqualTo(elem)); }
public void PushElement() { // Create a new heap. ConcurrentBinaryMinHeap <int> heap = new ConcurrentBinaryMinHeap <int>(); // Ensure that the heap is empty. Assert.That(heap.Count, Is.EqualTo(0)); // Store an element and insert it into the heap. PriorityValuePair <int> elem = new PriorityValuePair <int>(1f, 2); heap.Push(elem); // Ensure that the element was inserted into the heap. Assert.That(heap.Peek(), Is.EqualTo(elem)); // Store another element with higher priority and insert it as well. elem = new PriorityValuePair <int>(2f, 4); heap.Push(elem); // Ensure that the element was inserted into the queue and is at the root. Assert.That(heap.Peek(), Is.EqualTo(elem)); }
static void Main(string[] args) { ConcurrentPriorityQueue <string> queue = new ConcurrentPriorityQueue <string>(); queue.Enqueue(1000.0, "This "); queue.Enqueue(1000.0, "should "); queue.Enqueue(1000.0, "form "); queue.Enqueue(1000.0, "a "); queue.Enqueue(1000.0, "complete "); queue.Enqueue(1000.0, "and "); queue.Enqueue(1000.0, "understandable "); queue.Enqueue(1000.0, "sentence."); int numIterations = queue.Count; for (int x = 0; x < numIterations; x++) { Console.WriteLine("ITERATION " + (x + 1)); Console.WriteLine(""); // Print out the current state of the heap PriorityValuePair <string>[] heapArray = new PriorityValuePair <string> [queue.Count]; queue.CopyTo(heapArray, 0); for (int i = 0; i < heapArray.Length; i++) { Console.WriteLine(heapArray[i].Value + ", " + heapArray[i].Priority); } // Dequeue the next element PriorityValuePair <string> dequeued = queue.Dequeue(); Console.WriteLine(""); Console.WriteLine("DEQUEUED: " + dequeued.Value + ", " + dequeued.Priority); Console.WriteLine(""); } Console.ReadLine(); }
onCompletedTask(PriorityValuePair <Task> elem) { #region Decrement counters // Based on its priority, increment the appropriate active counter. if (elem.Priority >= MinCriticalPriority) { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__runningCriticalTasksLock); try { __runningCriticalTasks--; } finally { Monitor.Exit(__runningCriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__waitingCriticalTasksLock); try { __waitingCriticalTasks--; } finally { Monitor.Exit(__waitingCriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } else { // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__runningNoncriticalTasksLock); try { __runningNoncriticalTasks--; } finally { Monitor.Exit(__runningNoncriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } // Lock the thread -- CRITICAL SECTION BEGIN Monitor.Enter(__waitingNoncriticalTasksLock); try { __waitingNoncriticalTasks--; } finally { Monitor.Exit(__waitingNoncriticalTasksLock); // Unlock the thread -- CRITICAL SECTION END } } #endregion #region Emit events // Emit an event to notify listeners that a task has finished executing. if (TaskCompleted != null) { TaskCompleted(); } // Emit an event to notify listeners that all critical tasks have finished // executing (if so). if (__waitingCriticalTasks <= 0) { if (CriticalTasksCompleted != null) { CriticalTasksCompleted(); } } // Emit an event to notify listeners that all tasks have finished executing // (if so). if (__waitingCriticalTasks <= 0 && __waitingNoncriticalTasks <= 0) { if (AllTasksCompleted != null) { AllTasksCompleted(); } } #endregion }