' Classes/System/Threading/WaitHandle.ab Namespace System Namespace Threading Namespace Detail TypeDef PFNSignalObjectAndWait = *Function(hObjectToSignal As HANDLE, hObjectToWaitOn As HANDLE, dwMilliseconds As DWord, bAlertable As DWord) As DWord End Namespace Class WaitHandle Implements System.IDisposable Public ' Properties ' Const Function SafeWaitHandle() As SafeWaitHandle ' Sub SafeWaitHandle(h As SafeWaitHandle) Const Virtual Function Handle() As HANDLE Return h End Function Virtual Sub Handle(newHandle As HANDLE) h = newHandle End Sub ' Methods Sub WaitHandle() End Sub Virtual Sub ~WaitHandle() This.Dispose() End Sub Virtual Sub Close() This.Dispose() End Sub Virtual Sub Dispose() Dim hDisposing = InterlockedExchangePointer(h, 0) If hDisposing <> 0 Then CloseHandle(hDisposing) End If End Sub Function WaitOne() As Boolean Return WaitOne(INFINITE As DWord) End Function Function WaitOne(millisecondsTimeout As DWord) As Boolean If h = 0 Then Throw New ObjectDisposedException("WaitHandle.WaitOne") End If Return afterWait(WaitForSingleObject(h, millisecondsTimeout As DWord), 1) End Function Function WaitOne(millisecondsTimeout As Long) As Boolean ThrowIfInvalidLongValue(millisecondsTimeout) Return WaitOne(millisecondsTimeout As DWord) End Function Function WaitOne(timeout As System.TimeSpan) As Boolean Return WaitOne(timeout.TotalMilliseconds() As Long) End Function Static Function WaitAll(handles As Collections.Generic.IList) As Boolean Return waitImpl(handles, TRUE, INFINITE As DWord) End Function Static Function WaitAll(handles As Collections.Generic.IList, millisecondsTimeout As Long) As Boolean ThrowIfInvalidLongValue(millisecondsTimeout) Return waitImpl(handles, TRUE, millisecondsTimeout As DWord) End Function Static Function WaitAll(handles As Collections.Generic.IList, millisecondsTimeout As DWord) As Boolean Return waitImpl(handles, TRUE, millisecondsTimeout) End Function Static Function WaitAll(handles As Collections.Generic.IList, timeout As System.TimeSpan) As Boolean Return WaitAny(handles, timeout.TotalMilliseconds() As Long) End Function Static Function WaitAny(handles As Collections.Generic.IList) As Boolean Return waitImpl(handles, FALSE, INFINITE As DWord) End Function Static Function WaitAny(handles As Collections.Generic.IList, millisecondsTimeout As Long) As Boolean ThrowIfInvalidLongValue(millisecondsTimeout) Return waitImpl(handles, FALSE, millisecondsTimeout As DWord) End Function Static Function WaitAny(handles As Collections.Generic.IList, millisecondsTimeout As DWord) As Boolean Return waitImpl(handles, FALSE, millisecondsTimeout) End Function Static Function WaitAny(handles As Collections.Generic.IList, timeout As System.TimeSpan) As Boolean Return WaitAny(handles, timeout.TotalMilliseconds() As Long) End Function Static Function SignalAndWait(toSignal As WaitHandle, toWaitOn As WaitHandle) As Boolean Return SignalAndWait(toSignal, toWaitOn, INFINITE) End Function Static Function SignalAndWait(toSignal As WaitHandle, toWaitOn As WaitHandle, timeout As System.TimeSpan) As Boolean Return SignalAndWait(toSignal, toWaitOn, timeout.TotalMilliseconds() As Long) End Function Static Function SignalAndWait(toSignal As WaitHandle, toWaitOn As WaitHandle, timeout As Long) As Boolean Return SignalAndWait(toSignal, toWaitOn, timeout As DWord) End Function Static Function SignalAndWait(toSignal As WaitHandle, toWaitOn As WaitHandle, millisecondsTimeout As DWord) As Boolean Dim pSignalObjectAndWait = GetProcAddress(GetModuleHandle("Kernel32.dll"), ToMBStr("SignalObjectAndWait")) As Detail.PFNSignalObjectAndWait If pSignalObjectAndWait = 0 Then Throw New PlatformNotSupportedException("WaitHandle.SignalAndWait: This platform doesn't supoort this operation.") End If Return afterWait(pSignalObjectAndWait(toSignal.Handle, toWaitOn.Handle, millisecondsTimeout As DWord, FALSE), 1) End Function Static Const WaitTimeout = WAIT_TIMEOUT Protected Static Const InvalidHandle = INVALID_HANDLE_VALUE As HANDLE Private h As HANDLE /*! @brief WaitAll/WaitAnyの実装 @param[in] handles 待機ハンドル @param[in] waitAll WaitAllならTRUE、WaitAnyならFALSE @param[in] millisecondsTimeout タイムアウトまでの時間。-1 As DWordなら無限に待ち続ける。 @return シグナルが発生したらTrue、タイムアウトになったらFalse。 @date 2008/08/27 @auther Egtra */ Static Function waitImpl(handles As Collections.Generic.IList, waitAll As BOOL, millisecondsTimeout As DWord) As Boolean ' If ActiveBasic.IsNothing(handles) Then ' Throw New ArgumentNullException("handles") ' End If Dim count = handles.Count If count > MAXIMUM_WAIT_OBJECTS Then Throw New InvalidOperationException("handles.Count > MAXIMUM_WAIT_OBJECTS") End If Return afterWait(WaitForMultipleObjects(count, ToArrayOfHANDLE(handles), waitAll, millisecondsTimeout), count) End Function /*! @brief 待機が終了した後の処理を行う。 @param[in] ret 待機関数の戻り値 @param[in] n 待機させたハンドルの数 @return シグナルが発生したらTrue、タイムアウトになったらFalse。 @auther Egtra */ Static Function afterWait(ret As DWord, n As DWord) As Boolean Select Case ret Case WAIT_TIMEOUT Return False Case WAIT_ABANDONED Throw New AbandonedMutexException Debug ExitThread(0) Case WAIT_FAILED ActiveBasic.Windows.ThrowWithLastError() Case Else If WAIT_OBJECT_0 <= ret And ret < WAIT_OBJECT_0 + n Then Return True End If ' ObjectDisposedException? Debug ExitThread(0) End Select End Function /*! @brief WaitHandleのリストをHANDLE配列にする。 @param[in] handles 変換元 @return 変換済みの配列の要素を指すポインタ @date 2008/08/27 @auther Egtra */ Static Function ToArrayOfHANDLE(handles As Collections.Generic.IList) As *HANDLE Dim count = handles.Count ToArrayOfHANDLE = GC_malloc(count * SizeOf(HANDLE)) Dim i As Long For i = 0 To ELM(count) ToArrayOfHANDLE[i] = handles.Item[i].h Next End Function /*! @brief Long値が0以上か-1でない場合、例外を投げる。 @param[in] x テストする値 @throw ArgumentOutOfRangeException -1未満の値のとき @date 2008/08/27 @auther Egtra */ Static Sub ThrowIfInvalidLongValue(x As Long) If x < -1 Then Throw New ArgumentOutOfRangeException("millisecondsTimeout") End If End Sub End Class End Namespace 'Threading End Namespace 'System