1
2
3
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(mtx, ItemAvailableOrExiting, null);
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 }