1
2
3
4
5
6 using System;
7 using System.IO;
8
9 namespace System.Threading
10 {
11 public enum ConditionVariableStatus : int
12 {
13 timeout = 0, no_timeout = 1
14 }
15
16 public delegate bool Predicate(void* arg);
17 public class delegate bool PredicateMethod(void* arg);
18
19 public class ConditionVariable
20 {
21 public ConditionVariable() : nativeHandle(RtmAllocateConditionVariable())
22 {
23 }
24 public ~ConditionVariable()
25 {
26 if (nativeHandle != null)
27 {
28 RtmFreeConditionVariable(nativeHandle);
29 }
30 }
31 suppress ConditionVariable(const ConditionVariable&);
32 suppress void operator=(ConditionVariable&);
33 public ConditionVariable(ConditionVariable&& that) : nativeHandle(that.nativeHandle)
34 {
35 that.nativeHandle = null;
36 }
37 public void operator=(ConditionVariable&& that)
38 {
39 Swap(nativeHandle, that.nativeHandle);
40 }
41 [nodiscard]
42 public Result<bool> NotifyOne()
43 {
44 int errorId = 0;
45 bool result = RtmNotifyOne(nativeHandle, errorId);
46 if (errorId > 0)
47 {
48 return Result<bool>(ErrorId(errorId));
49 }
50 return Result<bool>(true);
51 }
52 [nodiscard]
53 public Result<bool> NotifyAll()
54 {
55 int errorId = 0;
56 bool result = RtmNotifyAll(nativeHandle, errorId);
57 if (errorId > 0)
58 {
59 return Result<bool>(ErrorId(errorId));
60 }
61 return Result<bool>(true);
62 }
63 [nodiscard]
64 public Result<bool> Wait(RecursiveMutex& mtx)
65 {
66 int errorId = 0;
67 bool result = RtmWaitConditionVariable(nativeHandle, mtx.NativeHandle(), errorId);
68 if (errorId > 0)
69 {
70 return Result<bool>(ErrorId(errorId));
71 }
72 return Result<bool>(true);
73 }
74 [nodiscard]
75 public Result<ConditionVariableStatus> WaitFor(RecursiveMutex& mtx, const Duration& duration)
76 {
77 int errorId = 0;
78 int result = RtmWaitConditionVariableDuration(nativeHandle, mtx.NativeHandle(), duration.Rep(), errorId);
79 if (errorId > 0)
80 {
81 return Result<ConditionVariableStatus>(ErrorId(errorId));
82 }
83 return Result<ConditionVariableStatus>(cast<ConditionVariableStatus>(result));
84 }
85 [nodiscard]
86 public Result<ConditionVariableStatus> WaitUntil(RecursiveMutex& mtx, const TimePoint& tp)
87 {
88 Duration duration = tp - Now();
89 return WaitFor(mtx, duration);
90 }
91 [nodiscard]
92 public Result<bool> Wait(RecursiveMutex& mtx, Predicate predicate, void* arg)
93 {
94 while (!predicate(arg))
95 {
96 auto result = Wait(mtx);
97 if (result.Error())
98 {
99 return result;
100 }
101 }
102 return Result<bool>(true);
103 }
104 [nodiscard]
105 public Result<bool> WaitFor(RecursiveMutex& mtx, Predicate predicate, void* arg, const Duration& duration)
106 {
107 while (!predicate(arg))
108 {
109 auto result = WaitFor(mtx, duration);
110 if (result.Error())
111 {
112 return Result<bool>(ErrorId(result.GetErrorId()));
113 }
114 if (result.Value() == ConditionVariableStatus.timeout)
115 {
116 return predicate(arg);
117 }
118 }
119 return Result<bool>(true);
120 }
121 [nodiscard]
122 public Result<bool> WaitUntil(RecursiveMutex& mtx, Predicate predicate, void* arg, const TimePoint& tp)
123 {
124 Duration duration = tp - Now();
125 return WaitFor(mtx, predicate, arg, duration);
126 }
127 [nodiscard]
128 public Result<bool> Wait(RecursiveMutex& mtx, PredicateMethod predicateMethod, void* arg)
129 {
130 while (!predicateMethod(arg))
131 {
132 auto result = Wait(mtx);
133 if (result.Error())
134 {
135 return result;
136 }
137 }
138 return Result<bool>(true);
139 }
140 [nodiscard]
141 public Result<bool> WaitFor(RecursiveMutex& mtx, PredicateMethod predicateMethod, void* arg, const Duration& duration)
142 {
143 while (!predicateMethod(arg))
144 {
145 auto result = WaitFor(mtx, duration);
146 if (result.Error())
147 {
148 return Result<bool>(ErrorId(result.GetErrorId()));
149 }
150 if (result.Value() == ConditionVariableStatus.timeout)
151 {
152 return predicateMethod(arg);
153 }
154 }
155 return Result<bool>(true);
156 }
157 [nodiscard]
158 public Result<bool> WaitUntil(RecursiveMutex& mtx, PredicateMethod predicateMethod, void* arg, const TimePoint& tp)
159 {
160 Duration duration = tp - Now();
161 return WaitFor(mtx, predicateMethod, arg, duration);
162 }
163 private void* nativeHandle;
164 }