1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.IO;
  8 
  9 namespace System.Threading
 10 {
 11     public enum ConditionVariableStatus : int
 12     {
 13         timeout = 0no_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(nativeHandlethat.nativeHandle);
 40         }
 41         [nodiscard]
 42         public Result<bool> NotifyOne()
 43         {
 44             int errorId = 0;
 45             bool result = RtmNotifyOne(nativeHandleerrorId);
 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(nativeHandleerrorId);
 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(nativeHandlemtx.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& mtxconst Duration& duration)
 76         {
 77             int errorId = 0;
 78             int result = RtmWaitConditionVariableDuration(nativeHandlemtx.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& mtxconst TimePoint& tp)
 87         {
 88             Duration duration = tp - Now();
 89             return WaitFor(mtxduration);
 90         }
 91         [nodiscard]
 92         public Result<bool> Wait(RecursiveMutex& mtxPredicate predicatevoid* 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& mtxPredicate predicatevoid* argconst Duration& duration)
106         {
107             while (!predicate(arg))
108             {
109                 auto result = WaitFor(mtxduration);
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& mtxPredicate predicatevoid* argconst TimePoint& tp)
123         {
124             Duration duration = tp - Now();
125             return WaitFor(mtxpredicateargduration);
126         }
127         [nodiscard]
128         public Result<bool> Wait(RecursiveMutex& mtxPredicateMethod predicateMethodvoid* 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& mtxPredicateMethod predicateMethodvoid* argconst Duration& duration)
142         {
143             while (!predicateMethod(arg))
144             {
145                 auto result = WaitFor(mtxduration);
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& mtxPredicateMethod predicateMethodvoid* argconst TimePoint& tp)
159         {
160             Duration duration = tp - Now();
161             return WaitFor(mtxpredicateMethodargduration);
162         }
163         private void* nativeHandle;
164     }