1 // =================================
 2 // Copyright (c) 2024 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 using System;
 7 using System.Collections;
 8 
 9 namespace System.Threading
10 {
11     public abstract class SynchronizedQueueBase
12     {
13         public SynchronizedQueueBase()
14         {
15         }
16         public virtual default ~SynchronizedQueueBase();
17         public bool ItemAvailableOrExiting(void* arg)
18         {
19             return IsItemAvailableOrExiting();
20         }
21         public abstract bool IsItemAvailableOrExiting();
22     }
23 
24     public class SynchronizedQueue<T> : SynchronizedQueueBase
25     {
26         public SynchronizedQueue() : base()exiting(false)
27         {
28         }
29         public bool IsEmpty() const
30         {
31             LockGuard<RecursiveMutex> lock(mtx);
32             return queue.IsEmpty();
33         }
34         [nodiscard]
35         public Result<bool> Put(const T& item)
36         {
37             if (exiting) return Result<bool>(false);
38             LockGuard<RecursiveMutex> lock(mtx);
39             queue.Put(item);
40             auto result = itemAvailableOrExiting.NotifyOne();
41             if (result.Error()) return result;
42             return Result<bool>(true);
43         }
44         public Result<T> Get()
45         {
46             auto result = itemAvailableOrExiting.Wait(mtxItemAvailableOrExitingnull);
47             if (result.Error()) return Result<T>(ErrorId(result.GetErrorId()));
48             if (exiting) return Result<T>(T());
49             if (!queue.IsEmpty())
50             {
51                 return Result<T>(queue.Get());
52             }
53             return Result<T>(T());
54         }
55         public inline bool Exiting() const
56         {
57             return exiting;
58         }
59         public Result<bool> Exit()
60         {
61             exiting = true;
62             auto result = itemAvailableOrExiting.NotifyAll();
63             if (result.Error()) return result;
64             return Result<bool>(true);
65         }
66         public override bool IsItemAvailableOrExiting()
67         {
68             return !queue.IsEmpty() || exiting;
69         }
70         private RecursiveMutex mtx;
71         private Queue<T> queue;
72         private ConditionVariable itemAvailableOrExiting;
73         private bool exiting;
74     }