}
}
+ [Test]
+ public void WaitOneWithTimeoutAndSpuriousWake ()
+ {
+ /* This is to test that WaitEvent.WaitOne is not going to wait largely
+ * more than its timeout. In this test, it shouldn't wait more than
+ * 1500 milliseconds, with its timeout being 1000ms */
+
+ using (ManualResetEvent mre = new ManualResetEvent (false))
+ using (ManualResetEvent ready = new ManualResetEvent (false)) {
+ var thread = new Thread (() => {
+ ready.Set ();
+ mre.WaitOne (1000);
+ });
+
+ thread.Start ();
+ ready.WaitOne ();
+
+ Thread.Sleep (10); // wait a bit so we enter mre.WaitOne
+
+ DateTime end = DateTime.Now.AddMilliseconds (500);
+ while (DateTime.Now < end) {
+ thread.Suspend ();
+ thread.Resume ();
+ }
+
+ Assert.IsTrue (thread.Join (1000), "#1");
+ }
+ }
+
+ [Test]
+ public void WaitAnyWithTimeoutAndSpuriousWake ()
+ {
+ /* This is to test that WaitEvent.WaitAny is not going to wait largely
+ * more than its timeout. In this test, it shouldn't wait more than
+ * 1500 milliseconds, with its timeout being 1000ms */
+
+ using (ManualResetEvent mre1 = new ManualResetEvent (false))
+ using (ManualResetEvent mre2 = new ManualResetEvent (false))
+ using (ManualResetEvent ready = new ManualResetEvent (false)) {
+ var thread = new Thread (() => {
+ ready.Set ();
+ WaitHandle.WaitAny (new [] { mre1, mre2 }, 1000);
+ });
+
+ thread.Start ();
+ ready.WaitOne ();
+
+ Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAny ({mre1, mre2})
+
+ DateTime end = DateTime.Now.AddMilliseconds (500);
+ while (DateTime.Now < end) {
+ thread.Suspend ();
+ thread.Resume ();
+ }
+
+ Assert.IsTrue (thread.Join (1000), "#1");
+ }
+ }
+
+ [Test]
+ public void WaitAllWithTimeoutAndSpuriousWake ()
+ {
+ /* This is to test that WaitEvent.WaitAll is not going to wait largely
+ * more than its timeout. In this test, it shouldn't wait more than
+ * 1500 milliseconds, with its timeout being 1000ms */
+
+ using (ManualResetEvent mre1 = new ManualResetEvent (false))
+ using (ManualResetEvent mre2 = new ManualResetEvent (false))
+ using (ManualResetEvent ready = new ManualResetEvent (false)) {
+ var thread = new Thread (() => {
+ ready.Set ();
+ WaitHandle.WaitAll (new [] { mre1, mre2 }, 1000);
+ });
+
+ thread.Start ();
+ ready.WaitOne ();
+
+ Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAll ({mre1, mre2})
+
+ DateTime end = DateTime.Now.AddMilliseconds (500);
+ while (DateTime.Now < end) {
+ thread.Suspend ();
+ thread.Resume ();
+ }
+
+ Assert.IsTrue (thread.Join (1000), "#1");
+ }
+ }
}
}
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/mono-time.h>
static gboolean own_if_signalled(gpointer handle)
{
int thr_ret;
gboolean apc_pending = FALSE;
gpointer current_thread = wapi_get_current_thread_handle ();
+ gint64 now, end;
if (current_thread == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
goto done;
}
+ if (timeout != INFINITE)
+ end = mono_100ns_ticks () + timeout * 1000 * 10;
+
do {
/* Check before waiting on the condition, just in case
*/
goto done;
}
- waited = _wapi_handle_timedwait_signal_handle (handle, timeout, alertable, FALSE, &apc_pending);
+ if (timeout == INFINITE) {
+ waited = _wapi_handle_timedwait_signal_handle (handle, INFINITE, alertable, FALSE, &apc_pending);
+ } else {
+ now = mono_100ns_ticks ();
+ if (end < now) {
+ ret = WAIT_TIMEOUT;
+ goto done;
+ }
+
+ waited = _wapi_handle_timedwait_signal_handle (handle, (end - now) / 10 / 1000, alertable, FALSE, &apc_pending);
+ }
if(waited==0 && !apc_pending) {
/* Condition was signalled, so hopefully
int thr_ret;
gboolean apc_pending = FALSE;
gpointer current_thread = wapi_get_current_thread_handle ();
+ gint64 now, end;
if (current_thread == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
goto done;
}
+ if (timeout != INFINITE)
+ end = mono_100ns_ticks () + timeout * 1000 * 10;
+
do {
/* Check before waiting on the condition, just in case
*/
goto done;
}
- waited = _wapi_handle_timedwait_signal_handle (wait, timeout, alertable, FALSE, &apc_pending);
+ if (timeout == INFINITE) {
+ waited = _wapi_handle_timedwait_signal_handle (wait, INFINITE, alertable, FALSE, &apc_pending);
+ } else {
+ now = mono_100ns_ticks ();
+ if (end < now) {
+ ret = WAIT_TIMEOUT;
+ goto done;
+ }
+
+ waited = _wapi_handle_timedwait_signal_handle (wait, (end - now) / 10 / 1000, alertable, FALSE, &apc_pending);
+ }
if (waited==0 && !apc_pending) {
/* Condition was signalled, so hopefully
gboolean poll;
gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
gboolean apc_pending = FALSE;
+ gint64 now, end;
if (current_thread == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
if (timeout == 0) {
return WAIT_TIMEOUT;
}
+
+ if (timeout != INFINITE)
+ end = mono_100ns_ticks () + timeout * 1000 * 10;
+
/* Have to wait for some or all handles to become signalled
*/
if (!done) {
/* Enter the wait */
- ret = _wapi_handle_timedwait_signal (timeout, poll, &apc_pending);
+ if (timeout == INFINITE) {
+ ret = _wapi_handle_timedwait_signal (INFINITE, poll, &apc_pending);
+ } else {
+ now = mono_100ns_ticks ();
+ if (end < now) {
+ ret = WAIT_TIMEOUT;
+ } else {
+ ret = _wapi_handle_timedwait_signal ((end - now) / 10 / 1000, poll, &apc_pending);
+ }
+ }
} else {
/* No need to wait */
ret = 0;