Commit e424248a authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Win32: refactor thread wait & sleep support

parent 04e1981b
...@@ -64,79 +64,36 @@ struct vlc_thread ...@@ -64,79 +64,36 @@ struct vlc_thread
#ifdef UNDER_CE #ifdef UNDER_CE
static void CALLBACK vlc_cancel_self (ULONG_PTR dummy); static void CALLBACK vlc_cancel_self (ULONG_PTR dummy);
static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles, DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles,
DWORD delay) BOOL bWaitAll, DWORD dwMilliseconds,
BOOL bAlertable)
{ {
struct vlc_thread *th = vlc_threadvar_get (thread_key); HANDLE handles[nCount + 1];
if (th == NULL) DWORD ret;
{
/* Main thread - cannot be cancelled anyway */
return WaitForMultipleObjects (count, handles, FALSE, delay);
}
HANDLE new_handles[count + 1];
memcpy(new_handles, handles, count * sizeof(HANDLE));
new_handles[count] = th->cancel_event;
DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE,
delay);
if (result == WAIT_OBJECT_0 + count)
{
vlc_cancel_self ((uintptr_t)th);
return WAIT_IO_COMPLETION;
}
else
{
return result;
}
}
DWORD SleepEx (DWORD dwMilliseconds, BOOL bAlertable) memcpy(handles, lpHandles, count * sizeof(HANDLE));
{
if (bAlertable) if (bAlertable)
{ {
DWORD result = vlc_cancelable_wait (0, NULL, dwMilliseconds); struct vlc_thread *th = vlc_threadvar_get (thread_key);
return (result == WAIT_TIMEOUT) ? 0 : WAIT_IO_COMPLETION; if (th != NULL)
}
else
{
Sleep(dwMilliseconds);
return 0;
}
}
DWORD WaitForSingleObjectEx (HANDLE hHandle, DWORD dwMilliseconds,
BOOL bAlertable)
{
if (bAlertable)
{ {
/* The MSDN documentation specifies different return codes, handles[nCount] = th->cancel_event;
* but in practice they are the same. We just check that it /* bWaitAll not implemented and not used by VLC... */
* remains so. */ assert (!bWaitAll);
#if WAIT_ABANDONED != WAIT_ABANDONED_0
# error Windows headers changed, code needs to be rewritten!
#endif
return vlc_cancelable_wait (1, &hHandle, dwMilliseconds);
} }
else else
{ bAltertable = FALSE;
return WaitForSingleObject (hHandle, dwMilliseconds);
} }
}
DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles, ret = WaitForMultipleObjects (nCount + bAlertable, handles, bWaitAll,
BOOL bWaitAll, DWORD dwMilliseconds,
BOOL bAlertable)
{
if (bAlertable)
{
/* We do not support the bWaitAll case */
assert (! bWaitAll);
return vlc_cancelable_wait (nCount, lpHandles, dwMilliseconds);
}
else
{
return WaitForMultipleObjects (nCount, lpHandles, bWaitAll,
dwMilliseconds); dwMilliseconds);
if (ret == WAIT_OBJECT_0 + nCount)
{
assert (bAlertable);
vlc_cancel_self ((uintptr_t)th);
ret = WAIT_IO_COMPLETION;
} }
return ret;
} }
#endif #endif
...@@ -167,6 +124,34 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) ...@@ -167,6 +124,34 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
return TRUE; return TRUE;
} }
static DWORD vlc_WaitForMultipleObjects (DWORD count, const HANDLE *handles,
DWORD delay)
{
DWORD ret = WaitForMultipleObjectsEx (count, handles, FALSE, delay, TRUE);
/* We do not abandon objects... this would be a bug */
assert (ret < WAIT_ABANDONED_0 || WAIT_ABANDONED_0 + count - 1 < ret);
if (unlikely(ret == WAIT_FAILED))
abort (); /* We are screwed! */
return ret;
}
static DWORD vlc_WaitForSingleObject (HANDLE handle, DWORD delay)
{
return vlc_WaitForMultipleObjects (1, &handle, delay);
}
static DWORD vlc_Sleep (DWORD delay)
{
DWORD ret = vlc_WaitForMultipleObjects (0, NULL, delay);
if (ret == WAIT_TIMEOUT)
ret = 0;
return ret;
}
/*** Mutexes ***/ /*** Mutexes ***/
void vlc_mutex_init( vlc_mutex_t *p_mutex ) void vlc_mutex_init( vlc_mutex_t *p_mutex )
{ {
...@@ -305,13 +290,11 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) ...@@ -305,13 +290,11 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{ {
vlc_testcancel (); vlc_testcancel ();
LeaveCriticalSection (&p_mutex->mutex); LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (p_condvar->handle, INFINITE, TRUE); result = vlc_WaitForSingleObject (p_condvar->handle, INFINITE);
EnterCriticalSection (&p_mutex->mutex); EnterCriticalSection (&p_mutex->mutex);
} }
while (result == WAIT_IO_COMPLETION); while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
assert (result != WAIT_FAILED);
ResetEvent (p_condvar->handle); ResetEvent (p_condvar->handle);
} }
...@@ -342,13 +325,11 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, ...@@ -342,13 +325,11 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total; DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
LeaveCriticalSection (&p_mutex->mutex); LeaveCriticalSection (&p_mutex->mutex);
result = WaitForSingleObjectEx (p_condvar->handle, delay, TRUE); result = vlc_WaitForSingleObject (p_condvar->handle, delay);
EnterCriticalSection (&p_mutex->mutex); EnterCriticalSection (&p_mutex->mutex);
} }
while (result == WAIT_IO_COMPLETION); while (result == WAIT_IO_COMPLETION);
assert (result != WAIT_ABANDONED);
assert (result != WAIT_FAILED);
ResetEvent (p_condvar->handle); ResetEvent (p_condvar->handle);
return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT; return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
...@@ -380,7 +361,7 @@ void vlc_sem_wait (vlc_sem_t *sem) ...@@ -380,7 +361,7 @@ void vlc_sem_wait (vlc_sem_t *sem)
do do
{ {
vlc_testcancel (); vlc_testcancel ();
result = WaitForSingleObjectEx (*sem, INFINITE, TRUE); result = vlc_WaitForSingleObject (*sem, INFINITE);
} }
while (result == WAIT_IO_COMPLETION); while (result == WAIT_IO_COMPLETION);
} }
...@@ -808,7 +789,7 @@ void mwait (mtime_t deadline) ...@@ -808,7 +789,7 @@ void mwait (mtime_t deadline)
delay /= 1000; delay /= 1000;
if (unlikely(delay > 0x7fffffff)) if (unlikely(delay > 0x7fffffff))
delay = 0x7fffffff; delay = 0x7fffffff;
SleepEx (delay, TRUE); vlc_Sleep (delay);
vlc_testcancel(); vlc_testcancel();
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment