|
|
|
@ -62,7 +62,8 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) |
|
|
|
int blocking = 1; |
|
|
|
double timeout; |
|
|
|
PyObject *timeout_obj = Py_None; |
|
|
|
DWORD res, full_msecs, msecs, start, ticks; |
|
|
|
DWORD res, full_msecs, nhandles; |
|
|
|
HANDLE handles[2], sigint_event; |
|
|
|
|
|
|
|
static char *kwlist[] = {"block", "timeout", NULL}; |
|
|
|
|
|
|
|
@ -96,53 +97,40 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) |
|
|
|
Py_RETURN_TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
/* check whether we can acquire without blocking */ |
|
|
|
/* check whether we can acquire without releasing the GIL and blocking */ |
|
|
|
if (WaitForSingleObject(self->handle, 0) == WAIT_OBJECT_0) { |
|
|
|
self->last_tid = GetCurrentThreadId(); |
|
|
|
++self->count; |
|
|
|
Py_RETURN_TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
msecs = full_msecs; |
|
|
|
start = GetTickCount(); |
|
|
|
|
|
|
|
for ( ; ; ) { |
|
|
|
HANDLE handles[2] = {self->handle, sigint_event}; |
|
|
|
/* prepare list of handles */ |
|
|
|
nhandles = 0; |
|
|
|
handles[nhandles++] = self->handle; |
|
|
|
if (_PyOS_IsMainThread()) { |
|
|
|
sigint_event = _PyOS_SigintEvent(); |
|
|
|
assert(sigint_event != NULL); |
|
|
|
handles[nhandles++] = sigint_event; |
|
|
|
} |
|
|
|
|
|
|
|
/* do the wait */ |
|
|
|
Py_BEGIN_ALLOW_THREADS |
|
|
|
/* do the wait */ |
|
|
|
Py_BEGIN_ALLOW_THREADS |
|
|
|
if (sigint_event != NULL) |
|
|
|
ResetEvent(sigint_event); |
|
|
|
res = WaitForMultipleObjects(2, handles, FALSE, msecs); |
|
|
|
Py_END_ALLOW_THREADS |
|
|
|
|
|
|
|
/* handle result */ |
|
|
|
if (res != WAIT_OBJECT_0 + 1) |
|
|
|
break; |
|
|
|
|
|
|
|
/* got SIGINT so give signal handler a chance to run */ |
|
|
|
Sleep(1); |
|
|
|
|
|
|
|
/* if this is main thread let KeyboardInterrupt be raised */ |
|
|
|
if (PyErr_CheckSignals()) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
/* recalculate timeout */ |
|
|
|
if (msecs != INFINITE) { |
|
|
|
ticks = GetTickCount(); |
|
|
|
if ((DWORD)(ticks - start) >= full_msecs) |
|
|
|
Py_RETURN_FALSE; |
|
|
|
msecs = full_msecs - (ticks - start); |
|
|
|
} |
|
|
|
} |
|
|
|
res = WaitForMultipleObjects(nhandles, handles, FALSE, full_msecs); |
|
|
|
Py_END_ALLOW_THREADS |
|
|
|
|
|
|
|
/* handle result */ |
|
|
|
switch (res) { |
|
|
|
case WAIT_TIMEOUT: |
|
|
|
Py_RETURN_FALSE; |
|
|
|
case WAIT_OBJECT_0: |
|
|
|
case WAIT_OBJECT_0 + 0: |
|
|
|
self->last_tid = GetCurrentThreadId(); |
|
|
|
++self->count; |
|
|
|
Py_RETURN_TRUE; |
|
|
|
case WAIT_OBJECT_0 + 1: |
|
|
|
errno = EINTR; |
|
|
|
return PyErr_SetFromErrno(PyExc_IOError); |
|
|
|
case WAIT_FAILED: |
|
|
|
return PyErr_SetFromWindowsErr(0); |
|
|
|
default: |
|
|
|
|