1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Threading
  9 {
 10     public enum ConditionVariableStatus : int
 11     {
 12         timeout = 0no_timeout = 1
 13     }
 14 
 15     public delegate bool Predicate(void* arg);
 16     public class delegate bool PredicateMethod(void* arg);
 17     
 18     public class ConditionVariable
 19     {
 20         public nothrow ConditionVariable() : nativeHandle(RtAllocateConditionVariable())
 21         {
 22         }
 23         public ~ConditionVariable()
 24         {
 25             if (nativeHandle != null)
 26             {
 27                 RtFreeConditionVariable(nativeHandle);
 28             }
 29         }
 30         suppress ConditionVariable(const ConditionVariable&);
 31         suppress void operator=(ConditionVariable&);
 32         public nothrow ConditionVariable(ConditionVariable&& that) : nativeHandle(that.nativeHandle)
 33         {
 34             that.nativeHandle = null;
 35         }
 36         public nothrow void operator=(ConditionVariable&& that)
 37         {
 38             Swap(nativeHandlethat.nativeHandle);
 39         }
 40         public void NotifyOne()
 41         {
 42             int result = RtNotifyOne(nativeHandle);
 43             if (result < 0)
 44             {
 45                 string message = RtGetError(result);
 46                 RtDisposeError(result);
 47                 throw ThreadingException(message);
 48             }
 49         }
 50         public void NotifyAll()
 51         {
 52             int result = RtNotifyAll(nativeHandle);
 53             if (result < 0)
 54             {
 55                 string message = RtGetError(result);
 56                 RtDisposeError(result);
 57                 throw ThreadingException(message);
 58             }
 59         }
 60         public void Wait(RecursiveMutex& mtx)
 61         {
 62             int result = RtWaitConditionVariable(nativeHandlemtx.NativeHandle());
 63             if (result < 0)
 64             {
 65                 string message = RtGetError(result);
 66                 RtDisposeError(result);
 67                 throw ThreadingException(message);
 68             }
 69         }
 70         public ConditionVariableStatus WaitFor(RecursiveMutex& mtxconst Duration& duration)
 71         {
 72             int result = RtWaitConditionVariableDuration(nativeHandlemtx.NativeHandle()duration.Rep());
 73             if (result < 0)
 74             {
 75                 string message = RtGetError(result);
 76                 RtDisposeError(result);
 77                 throw ThreadingException(message);
 78             }
 79             return cast<ConditionVariableStatus>(result);
 80         }
 81         public ConditionVariableStatus WaitUntil(RecursiveMutex& mtxconst TimePoint& tp)
 82         {
 83             Duration duration = tp - Now();
 84             return WaitFor(mtxduration);
 85         }
 86         public void Wait(RecursiveMutex& mtxPredicate predicatevoid* arg)
 87         {
 88             while (!predicate(arg))
 89             {
 90                 Wait(mtx);
 91             }
 92         }
 93         public bool WaitFor(RecursiveMutex& mtxPredicate predicatevoid* argconst Duration& duration)
 94         {
 95             while (!predicate(arg))
 96             {
 97                 if (WaitFor(mtxduration) == ConditionVariableStatus.timeout)
 98                 {
 99                     return predicate(arg);
100                 }
101             }
102             return true;
103         }
104         public bool WaitUntil(RecursiveMutex& mtxPredicate predicatevoid* argconst TimePoint& tp)
105         {
106             Duration duration = tp - Now();
107             return WaitFor(mtxpredicateargduration);
108         }
109         public void Wait(RecursiveMutex& mtxPredicateMethod predicateMethodvoid* arg)
110         {
111             while (!predicateMethod(arg))
112             {
113                 Wait(mtx);
114             }
115         }
116         public bool WaitFor(RecursiveMutex& mtxPredicateMethod predicateMethodvoid* argconst Duration& duration)
117         {
118             while (!predicateMethod(arg))
119             {
120                 if (WaitFor(mtxduration) == ConditionVariableStatus.timeout)
121                 {
122                     return predicateMethod(arg);
123                 }
124             }
125             return true;
126         }
127         public bool WaitUntil(RecursiveMutex& mtxPredicateMethod predicateMethodvoid* argconst TimePoint& tp)
128         {
129             Duration duration = tp - Now();
130             return WaitFor(mtxpredicateMethodargduration);
131         }
132         private void* nativeHandle;
133     }
134 }