From 95f9b03a023e679e44769f709585a8cf876fc7b3 Mon Sep 17 00:00:00 2001 From: ArtiomPatov Date: Wed, 21 Dec 2022 12:57:31 +0300 Subject: [PATCH 1/2] initial commit --- .../PriorityQueue.Tests.csproj | 25 ++++++ .../PriorityQueue.Tests/PriorityQueueTests.cs | 90 +++++++++++++++++++ PriorityQueue/PriorityQueue.Tests/Usings.cs | 1 + PriorityQueue/PriorityQueue.sln | 22 +++++ PriorityQueue/PriorityQueue/PriorityQueue.cs | 90 +++++++++++++++++++ .../PriorityQueue/PriorityQueue.csproj | 10 +++ 6 files changed, 238 insertions(+) create mode 100644 PriorityQueue/PriorityQueue.Tests/PriorityQueue.Tests.csproj create mode 100644 PriorityQueue/PriorityQueue.Tests/PriorityQueueTests.cs create mode 100644 PriorityQueue/PriorityQueue.Tests/Usings.cs create mode 100644 PriorityQueue/PriorityQueue.sln create mode 100644 PriorityQueue/PriorityQueue/PriorityQueue.cs create mode 100644 PriorityQueue/PriorityQueue/PriorityQueue.csproj diff --git a/PriorityQueue/PriorityQueue.Tests/PriorityQueue.Tests.csproj b/PriorityQueue/PriorityQueue.Tests/PriorityQueue.Tests.csproj new file mode 100644 index 0000000..353285f --- /dev/null +++ b/PriorityQueue/PriorityQueue.Tests/PriorityQueue.Tests.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + + PiorityQueue.Tests + + + + + + + + + + + + + + + diff --git a/PriorityQueue/PriorityQueue.Tests/PriorityQueueTests.cs b/PriorityQueue/PriorityQueue.Tests/PriorityQueueTests.cs new file mode 100644 index 0000000..842bf37 --- /dev/null +++ b/PriorityQueue/PriorityQueue.Tests/PriorityQueueTests.cs @@ -0,0 +1,90 @@ +namespace PriorityQueue.Tests; + +using PriorityQueue; + +public class Tests +{ + private PriorityQueue _priorityQueue = new (); + + [SetUp] + public void Setup() + { + _priorityQueue = new PriorityQueue(); + var tasks = new Task[10]; + + for (var i = 0; i < 10; i++) + { + var priority = i; + tasks[i] = Task.Run(() => EnqueueValues(priority)); + } + + Task.WaitAll(tasks); + } + + [Test] + public void DequeueShouldReturnFirstAddedValue() + { + var actualValue = _priorityQueue.Dequeue(); + Assert.That(actualValue, Is.EqualTo(0)); + } + + [Test] + public void TestNumberOfElements() + { + Assert.That(_priorityQueue.Size, Is.EqualTo(100)); + } + + [Test] + public void DequeueShouldReturnAllElementsInCorrectOrder() + { + for (var i = 0; i < 10; i++) + { + for (var j = 0; j < 10; j++) + { + var actualValue = _priorityQueue.Dequeue(); + Assert.That(actualValue, Is.EqualTo(j)); + } + } + } + + [Test] + public void ThreadsShouldWaitIfThereIsNoElementsInTheQueue() + { + for (var i = 0; i < 10; i++) + { + for (var j = 0; j < 10; j++) + { + var actualValue = _priorityQueue.Dequeue(); + } + } + + var tasks = new Task[5]; + for (var taskNumber = 0; taskNumber < 5; taskNumber++) + { + tasks[taskNumber] = Task.Run(() => DequeueValueAndCompare(5)); + } + + for (var i = 0; i < 5; i++) + { + _priorityQueue.Enqueue(i, i); + } + + Task.WaitAll(tasks); + + Assert.That(_priorityQueue.Size, Is.EqualTo(0)); + } + + private void DequeueValueAndCompare(int expectedValue) + { + var actualValue = _priorityQueue.Dequeue(); + Assert.That(actualValue, Is.LessThan(expectedValue)); + } + + private void EnqueueValues(int priority) + { + for (var value = 0; value < 10; value++) + { + _priorityQueue.Enqueue(value, priority); + } + } +} \ No newline at end of file diff --git a/PriorityQueue/PriorityQueue.Tests/Usings.cs b/PriorityQueue/PriorityQueue.Tests/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/PriorityQueue/PriorityQueue.Tests/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/PriorityQueue/PriorityQueue.sln b/PriorityQueue/PriorityQueue.sln new file mode 100644 index 0000000..1cab51d --- /dev/null +++ b/PriorityQueue/PriorityQueue.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriorityQueue", "PriorityQueue\PriorityQueue.csproj", "{A729599D-41D7-4A91-A884-3A50422DDC7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriorityQueue.Tests", "PriorityQueue.Tests\PriorityQueue.Tests.csproj", "{EEB7DAD5-E485-455F-A363-5DD9765E2AE4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A729599D-41D7-4A91-A884-3A50422DDC7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A729599D-41D7-4A91-A884-3A50422DDC7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A729599D-41D7-4A91-A884-3A50422DDC7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A729599D-41D7-4A91-A884-3A50422DDC7E}.Release|Any CPU.Build.0 = Release|Any CPU + {EEB7DAD5-E485-455F-A363-5DD9765E2AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEB7DAD5-E485-455F-A363-5DD9765E2AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEB7DAD5-E485-455F-A363-5DD9765E2AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEB7DAD5-E485-455F-A363-5DD9765E2AE4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/PriorityQueue/PriorityQueue/PriorityQueue.cs b/PriorityQueue/PriorityQueue/PriorityQueue.cs new file mode 100644 index 0000000..ed82c53 --- /dev/null +++ b/PriorityQueue/PriorityQueue/PriorityQueue.cs @@ -0,0 +1,90 @@ +namespace PriorityQueue; + +using System.Linq; + +/// +/// Thread safe priority queue. +/// +/// Type of queue elements. +public class PriorityQueue +{ + private List> _queueElementList = new (); + + /// + /// Gets count of elements in the queue. + /// + public int Size => _queueElementList.Count; + + /// + /// Enqueues value with given priority. + /// + /// Element value. + /// Priority of the element. + public void Enqueue(TValue value, int priority) + { + lock (_queueElementList) + { + var newElement = new QueueElement(value, priority); + _queueElementList.Add(newElement); + + Monitor.PulseAll(_queueElementList); + } + } + + /// + /// Gets element with the highest priority and removes it from the queue. + /// + /// + public TValue Dequeue() + { + lock (_queueElementList) + { + while (Size == 0) + { + Monitor.Wait(_queueElementList); + } + + return GetAndRemove().Value; + } + } + + private QueueElement GetAndRemove() + { + var maxElement = _queueElementList.Max() ?? throw new ArgumentNullException(); + _queueElementList.Remove(maxElement); + return maxElement; + } + + /// + /// Class for elements of the queue. + /// + /// Elements value type. + private class QueueElement : IComparable> + { + /// + /// Element priority. + /// + public int Priority { get; } + + /// + /// Element value. + /// + public TValue Value { get; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// + public QueueElement(TValue value, int priority) + { + Priority = priority; + Value = value; + } + + public int CompareTo(QueueElement? other) + { + return this.Priority.CompareTo((other ?? throw new ArgumentNullException()).Priority); + } + } +} \ No newline at end of file diff --git a/PriorityQueue/PriorityQueue/PriorityQueue.csproj b/PriorityQueue/PriorityQueue/PriorityQueue.csproj new file mode 100644 index 0000000..66ba088 --- /dev/null +++ b/PriorityQueue/PriorityQueue/PriorityQueue.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + enable + enable + Queue + + + From c94c0bb4bb965aeec3ac3ea063f1751fde2b93fe Mon Sep 17 00:00:00 2001 From: ArtiomPatov Date: Wed, 21 Dec 2022 13:00:12 +0300 Subject: [PATCH 2/2] update ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8eaa4e..e3c033d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.x' + dotnet-version: '7.x' - name: Build run: for dir in */; do cd $dir; for sln in *.sln; do dotnet build $sln; cd ..; done; done shell: bash