Index: trunk/ab5.0/ablib/src/Classes/System/Threading/WaitHandle.ab
===================================================================
--- trunk/ab5.0/ablib/src/Classes/System/Threading/WaitHandle.ab	(revision 581)
+++ trunk/ab5.0/ablib/src/Classes/System/Threading/WaitHandle.ab	(revision 599)
@@ -24,5 +24,5 @@
 
 	' Methods
-	Virtual Sub WaitHandle()
+	Sub WaitHandle()
 	End Sub
 
@@ -43,59 +43,78 @@
 
 	Function WaitOne() As Boolean
-		Return WaitOne(INFINITE, FALSE)
-	End Function
-
-	Function WaitOne(millisecondsTimeout As Long, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForSingleObject(h, millisecondsTimeout As DWord), 1)
-	End Function
-
-	Function WaitOne(timeout As System.TimeSpan, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForSingleObject(h, timeout.TotalMilliseconds() As DWord), 1)
-	End Function
-
-	Static Function WaitAll(count As DWord, handles As *HANDLE) As Boolean
-		Return WaitAll(count, handles, INFINITE, FALSE)
-	End Function
-
-	Static Function WaitAll(count As DWord, handles As *HANDLE, millisecondsTimeout As Long, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForMultipleObjects(count, handles, TRUE, millisecondsTimeout), count)
-	End Function
-
-	Static Function WaitAll(count As DWord, handles As *HANDLE, timeout As System.TimeSpan, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForMultipleObjects(count, handles, TRUE, timeout.TotalMilliseconds() As DWord), count)
-	End Function
-
-	Static Function WaitAny(count As DWord, handles As *HANDLE) As Boolean
-		Return WaitAny(count, handles, INFINITE, FALSE)
-	End Function
-
-	Static Function WaitAny(count As DWord, handles As *HANDLE, millisecondsTimeout As Long, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForMultipleObjects(count, handles, FALSE, millisecondsTimeout), count)
-	End Function
-
-	Static Function WaitAny(count As DWord, handles As *HANDLE, timeout As System.TimeSpan, exitContext As Boolean) As Boolean
-		Return WaitHandle.AfterWait(WaitForMultipleObjects(count, handles, FALSE, timeout.TotalMilliseconds() As DWord), count)
+		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<WaitHandle>) As Boolean
+		Return waitImpl(handles, TRUE, INFINITE As DWord)
+	End Function
+
+	Static Function WaitAll(handles As Collections.Generic.IList<WaitHandle>, millisecondsTimeout As Long) As Boolean
+		ThrowIfInvalidLongValue(millisecondsTimeout)
+		Return waitImpl(handles, TRUE, millisecondsTimeout As DWord)
+	End Function
+
+	Static Function WaitAll(handles As Collections.Generic.IList<WaitHandle>, millisecondsTimeout As DWord) As Boolean
+		Return waitImpl(handles, TRUE, millisecondsTimeout)
+	End Function
+
+	Static Function WaitAll(handles As Collections.Generic.IList<WaitHandle>, timeout As System.TimeSpan) As Boolean
+		Return WaitAny(handles, timeout.TotalMilliseconds() As Long)
+	End Function
+
+	Static Function WaitAny(handles As Collections.Generic.IList<WaitHandle>) As Boolean
+		Return waitImpl(handles, FALSE, INFINITE As DWord)
+	End Function
+
+	Static Function WaitAny(handles As Collections.Generic.IList<WaitHandle>, millisecondsTimeout As Long) As Boolean
+		ThrowIfInvalidLongValue(millisecondsTimeout)
+		Return waitImpl(handles, FALSE, millisecondsTimeout As DWord)
+	End Function
+
+	Static Function WaitAny(handles As Collections.Generic.IList<WaitHandle>, millisecondsTimeout As DWord) As Boolean
+		Return waitImpl(handles, FALSE, millisecondsTimeout)
+	End Function
+
+	Static Function WaitAny(handles As Collections.Generic.IList<WaitHandle>, 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, FALSE)
-	End Function
-
-	Static Function SignalAndWait (toSignal As WaitHandle, toWaitOn As WaitHandle, timeout As System.TimeSpan, exitContext As Boolean) As Boolean
-		Return SignalAndWait(toSignal, toWaitOn, timeout.TotalMilliseconds() As Long, FALSE)
-	End Function
-
-	Static Function SignalAndWait(toSignal As WaitHandle, toWaitOn As WaitHandle, millisecondsTimeout As Long, exitContext As Boolean) 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 WaitHandle.AfterWait(pSignalObjectAndWait(toSignal.Handle, toWaitOn.Handle, millisecondsTimeout As DWord, FALSE), 1)
-	End Function
-
-Public
-	Function WaitTimeout() As Long
-		Return WAIT_TIMEOUT
-	End Function
+		Return afterWait(pSignalObjectAndWait(toSignal.Handle, toWaitOn.Handle, millisecondsTimeout As DWord, FALSE), 1)
+	End Function
+
+	Static Const WaitTimeout = WAIT_TIMEOUT
 
 Protected
@@ -105,13 +124,41 @@
 	h As HANDLE
 
-	Static Function AfterWait(ret As DWord, n As DWord) As Boolean
+	/*!
+	@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<WaitHandle>, 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 AbandonedMutexException
+				Throw New AbandonedMutexException
 				Debug
 				ExitThread(0)
-			'Case WAIT_FAILED
+			Case WAIT_FAILED
+				ActiveBasic.Windows.ThrowWithLastError()
 			Case Else
 				If WAIT_OBJECT_0 <= ret And ret < WAIT_OBJECT_0 + n Then
@@ -123,4 +170,33 @@
 		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<WaitHandle>) 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
 
