diff --git a/kr3/MyPriorityQueue.Tests/MyPriorityQueue.Tests.csproj b/kr3/MyPriorityQueue.Tests/MyPriorityQueue.Tests.csproj
new file mode 100644
index 0000000..40e283d
--- /dev/null
+++ b/kr3/MyPriorityQueue.Tests/MyPriorityQueue.Tests.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net6.0
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kr3/MyPriorityQueue.Tests/Test.cs b/kr3/MyPriorityQueue.Tests/Test.cs
new file mode 100644
index 0000000..3ba0586
--- /dev/null
+++ b/kr3/MyPriorityQueue.Tests/Test.cs
@@ -0,0 +1,112 @@
+namespace MyPriorityQueue.Tests;
+
+using MyPriorityQueue;
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Threading;
+
+public class Tests
+{
+ [Test]
+ public void EnqueueSizeAndDequeueFromOneThread()
+ {
+ var priorityQueue = new PriorityQueue();
+ priorityQueue.Enqueue(1231, -1);
+ priorityQueue.Enqueue(1231, 1);
+ Assert.AreEqual(2, priorityQueue.Size);
+ priorityQueue.Enqueue(1, 23);
+ Assert.AreEqual(3, priorityQueue.Size);
+ Assert.AreEqual(1, priorityQueue.Dequeue());
+ Assert.AreEqual(2, priorityQueue.Size);
+ priorityQueue.Enqueue(12, 1);
+ Assert.AreEqual(3, priorityQueue.Size);
+ Assert.AreEqual(1231, priorityQueue.Dequeue());
+ Assert.AreEqual(2, priorityQueue.Size);
+ Assert.AreEqual(12, priorityQueue.Dequeue());
+ Assert.AreEqual(1, priorityQueue.Size);
+ Assert.AreEqual(1231, priorityQueue.Dequeue());
+ Assert.AreEqual(0, priorityQueue.Size);
+ }
+
+ [Test]
+ public void EnqueueFromDifferentThreads()
+ {
+ var priorityQueue = new PriorityQueue();
+ var threads = new Thread[3];
+ for (int i = 0; i < threads.Length; ++i)
+ {
+ var localI = i;
+ threads[i] = new Thread(() =>
+ {
+ priorityQueue.Enqueue(localI, 1);
+ });
+ }
+ foreach (var thread in threads)
+ {
+ thread.Start();
+ }
+ foreach (var thread in threads)
+ {
+ thread.Join();
+ }
+ Assert.AreEqual(3, priorityQueue.Size);
+ }
+
+ [Test]
+ public void DequeueFromDifferentThreadsAndSavingFIFO()
+ {
+ var priorityQueue = new PriorityQueue();
+ priorityQueue.Enqueue("true", 1);
+ priorityQueue.Enqueue("false", 1);
+ priorityQueue.Enqueue("abobus", 1);
+ var values = new string[3];
+ var threads = new Thread[3];
+ for (int i = 0; i < threads.Length; ++i)
+ {
+ var localI = i;
+ threads[i] = new Thread(() =>
+ {
+ values[localI] = priorityQueue.Dequeue();
+ });
+ }
+ foreach (var thread in threads)
+ {
+ thread.Start();
+ }
+ foreach (var thread in threads)
+ {
+ thread.Join();
+ }
+ var correctValues = new string[3];
+ correctValues[0] = "true";
+ correctValues[1] = "false";
+ correctValues[2] = "abobus";
+ Assert.AreEqual(correctValues, values);
+ Assert.AreEqual(0, priorityQueue.Size);
+ }
+
+ [Test]
+ public void EnqueueAndDequeueFromDifferentThreadsWithoutExceptions()
+ {
+ var priorityQueue = new PriorityQueue();
+
+ var threads = new Thread[2];
+ threads[0] = new Thread(() =>
+ {
+ priorityQueue.Dequeue();
+ });
+ threads[1] = new Thread(() =>
+ {
+ priorityQueue.Enqueue("ololo", 131);
+ });
+ foreach (var thread in threads)
+ {
+ thread.Start();
+ }
+ foreach (var thread in threads)
+ {
+ thread.Join();
+ }
+ Assert.AreEqual(0, priorityQueue.Size);
+ }
+}
diff --git a/kr3/MyPriorityQueue/IPriorityQueue.cs b/kr3/MyPriorityQueue/IPriorityQueue.cs
new file mode 100644
index 0000000..ada326b
--- /dev/null
+++ b/kr3/MyPriorityQueue/IPriorityQueue.cs
@@ -0,0 +1,26 @@
+namespace MyPriorityQueue;
+
+///
+/// Interface of thread-safe priority queue
+///
+/// Type of value
+public interface IPriorityQueue
+{
+ ///
+ /// Add value ant its priority to the priority queue
+ ///
+ /// Given value
+ /// Given priority
+ void Enqueue(TValue value, int priority);
+
+ ///
+ /// Removes and returns the first founded value with the highest priority from the priority queue
+ ///
+ /// Value with the highest priority
+ TValue Dequeue();
+
+ ///
+ /// Returns the quantity of elements
+ ///
+ int Size { get; }
+}
diff --git a/kr3/MyPriorityQueue/MyPriorityQueue.csproj b/kr3/MyPriorityQueue/MyPriorityQueue.csproj
new file mode 100644
index 0000000..74abf5c
--- /dev/null
+++ b/kr3/MyPriorityQueue/MyPriorityQueue.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
diff --git a/kr3/MyPriorityQueue/MyPriorityQueue.sln b/kr3/MyPriorityQueue/MyPriorityQueue.sln
new file mode 100644
index 0000000..883d07f
--- /dev/null
+++ b/kr3/MyPriorityQueue/MyPriorityQueue.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32210.238
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyPriorityQueue", "MyPriorityQueue.csproj", "{B1F6ADA8-0C8E-4016-912A-B0193040CA8D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyPriorityQueue.Tests", "..\MyPriorityQueue.Tests\MyPriorityQueue.Tests.csproj", "{EA3D469B-6AD6-451A-9F64-D2479A4702A9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B1F6ADA8-0C8E-4016-912A-B0193040CA8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B1F6ADA8-0C8E-4016-912A-B0193040CA8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B1F6ADA8-0C8E-4016-912A-B0193040CA8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B1F6ADA8-0C8E-4016-912A-B0193040CA8D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EA3D469B-6AD6-451A-9F64-D2479A4702A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EA3D469B-6AD6-451A-9F64-D2479A4702A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EA3D469B-6AD6-451A-9F64-D2479A4702A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EA3D469B-6AD6-451A-9F64-D2479A4702A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {42B04315-5D4D-4FA7-9A03-E4C34222BD0B}
+ EndGlobalSection
+EndGlobal
diff --git a/kr3/MyPriorityQueue/PriorityQueue.cs b/kr3/MyPriorityQueue/PriorityQueue.cs
new file mode 100644
index 0000000..5e269eb
--- /dev/null
+++ b/kr3/MyPriorityQueue/PriorityQueue.cs
@@ -0,0 +1,53 @@
+namespace MyPriorityQueue;
+
+using System.Collections.Generic;
+using System.Linq;
+
+///
+/// Realisation of thread-safe priority queue interface
+///
+/// Type of value
+public class PriorityQueue : IPriorityQueue
+{
+ private readonly SortedList> elementsByPriority = new();
+ private int counter = 0;
+ private readonly object locker = new();
+
+ public void Enqueue(TValue value, int priority)
+ {
+ lock (locker)
+ {
+ if (!elementsByPriority.ContainsKey(priority))
+ {
+ elementsByPriority[priority] = new Queue();
+ }
+ elementsByPriority[priority].Enqueue(value);
+ counter++;
+ Monitor.PulseAll(locker);
+ }
+ }
+
+ public TValue Dequeue()
+ {
+ lock (locker)
+ {
+ while (counter == 0)
+ {
+ Monitor.Wait(locker);
+ }
+
+ var maxPriority = elementsByPriority.Keys.Last();
+ var element = elementsByPriority[maxPriority].Dequeue();
+
+ if (elementsByPriority[maxPriority].Count == 0)
+ {
+ elementsByPriority.Remove(maxPriority);
+ }
+ counter--;
+
+ return element;
+ }
+ }
+
+ public int Size => counter;
+}
diff --git a/kr3/MyPriorityQueue/Program.cs b/kr3/MyPriorityQueue/Program.cs
new file mode 100644
index 0000000..30ec1d2
--- /dev/null
+++ b/kr3/MyPriorityQueue/Program.cs
@@ -0,0 +1,8 @@
+namespace MyPriorityQueue;
+
+public static class Program
+{
+ public static void Main(string[] args)
+ {
+ }
+}
\ No newline at end of file