[pypy-svn] r78641 - in pypy/branch/fast-forward/pypy: config module/_multiprocessing module/rctime rlib
afa at codespeak.net
afa at codespeak.net
Tue Nov 2 17:16:14 CET 2010
Author: afa
Date: Tue Nov 2 17:16:11 2010
New Revision: 78641
Modified:
pypy/branch/fast-forward/pypy/config/pypyoption.py
pypy/branch/fast-forward/pypy/module/_multiprocessing/__init__.py
pypy/branch/fast-forward/pypy/module/_multiprocessing/interp_semaphore.py
pypy/branch/fast-forward/pypy/module/rctime/__init__.py
pypy/branch/fast-forward/pypy/module/rctime/interp_time.py
pypy/branch/fast-forward/pypy/rlib/rwin32.py
Log:
Implement interruptible time.sleep() on Windows.
+ _multiprocessing uses the same ConsoleCtrlHandler handler
Modified: pypy/branch/fast-forward/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/pypyoption.py (original)
+++ pypy/branch/fast-forward/pypy/config/pypyoption.py Tue Nov 2 17:16:11 2010
@@ -62,7 +62,10 @@
-module_dependencies = {}
+module_dependencies = {
+ '_multiprocessing': [('objspace.usemodules.rctime', True),
+ ('objspace.usemodules.thread', True)],
+ }
module_suggests = {
# the reason you want _rawffi is for ctypes, which
# itself needs the interp-level struct module
Modified: pypy/branch/fast-forward/pypy/module/_multiprocessing/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_multiprocessing/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/_multiprocessing/__init__.py Tue Nov 2 17:16:11 2010
@@ -16,7 +16,3 @@
if sys.platform == 'win32':
interpleveldefs['win32'] = 'interp_win32.win32_namespace(space)'
-
- def startup(self, space):
- from pypy.module._multiprocessing.interp_semaphore import CounterState
- space.fromcache(CounterState).startup(space)
Modified: pypy/branch/fast-forward/pypy/module/_multiprocessing/interp_semaphore.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_multiprocessing/interp_semaphore.py (original)
+++ pypy/branch/fast-forward/pypy/module/_multiprocessing/interp_semaphore.py Tue Nov 2 17:16:11 2010
@@ -27,67 +27,6 @@
'ReleaseSemaphore', [rwin32.HANDLE, rffi.LONG, rffi.LONGP],
rwin32.BOOL)
- CtrlHandler_type = lltype.Ptr(lltype.FuncType([], rwin32.BOOL))
- _CreateEvent = rwin32.winexternal(
- 'CreateEventA', [rffi.VOIDP, rwin32.BOOL, rwin32.BOOL, rwin32.LPCSTR],
- rwin32.HANDLE)
- _SetEvent = rwin32.winexternal(
- 'SetEvent', [rwin32.HANDLE], rwin32.BOOL)
- _ResetEvent = rwin32.winexternal(
- 'ResetEvent', [rwin32.HANDLE], rwin32.BOOL)
-
- # This is needed because the handler function must have the "WINAPI"
- # calling convention, which is not supported by lltype.Ptr.
- eci = ExternalCompilationInfo(
- separate_module_sources=['''
- #include <windows.h>
-
- static BOOL (*CtrlHandlerRoutine)(
- DWORD dwCtrlType);
-
- static BOOL WINAPI winapi_CtrlHandlerRoutine(
- DWORD dwCtrlType)
- {
- return CtrlHandlerRoutine(dwCtrlType);
- }
-
- BOOL pypy_multiprocessing_setCtrlHandlerRoutine(BOOL (*f)(DWORD))
- {
- CtrlHandlerRoutine = f;
- SetConsoleCtrlHandler(winapi_CtrlHandlerRoutine, TRUE);
- }
-
- '''],
- export_symbols=['pypy_multiprocessing_setCtrlHandlerRoutine'],
- )
- _setCtrlHandlerRoutine = rffi.llexternal(
- 'pypy_multiprocessing_setCtrlHandlerRoutine',
- [CtrlHandler_type], rwin32.BOOL,
- compilation_info=eci)
-
- def ProcessingCtrlHandler():
- _SetEvent(globalState.sigint_event)
- return 0
-
- class GlobalState:
- def __init__(self):
- self.init()
-
- def init(self):
- self.sigint_event = rwin32.NULL_HANDLE
-
- def startup(self, space):
- # Initialize the event handle used to signal Ctrl-C
- globalState.sigint_event = _CreateEvent(
- rffi.NULL, True, False, rffi.NULL)
- if globalState.sigint_event == rwin32.NULL_HANDLE:
- raise wrap_windowserror(
- space, rwin32.lastWindowsError("CreateEvent"))
- if not _setCtrlHandlerRoutine(ProcessingCtrlHandler):
- raise wrap_windowserror(
- space, rwin32.lastWindowsError("SetConsoleCtrlHandler"))
-
-
else:
from pypy.rlib import rposix
@@ -187,25 +126,12 @@
def handle_w(space, w_handle):
return rffi.cast(SEM_T, space.uint_w(w_handle))
- class GlobalState:
- def init(self):
- pass
-
- def startup(self, space):
- pass
-
-globalState = GlobalState()
-
class CounterState:
def __init__(self, space):
self.counter = 0
def _freeze_(self):
self.counter = 0
- globalState.init()
-
- def startup(self, space):
- globalState.startup(space)
def getCount(self):
value = self.counter
@@ -250,10 +176,12 @@
start = _GetTickCount()
while True:
- handles = [self.handle, globalState.sigint_event]
+ from pypy.module.rctime.interp_time import State
+ interrupt_event = space.fromcache(State).get_interrupt_event()
+ handles = [self.handle, interrupt_event]
# do the wait
- _ResetEvent(globalState.sigint_event)
+ rwin32.ResetEvent(interrupt_event)
res = rwin32.WaitForMultipleObjects(handles, timeout=msecs)
if res != rwin32.WAIT_OBJECT_0 + 1:
Modified: pypy/branch/fast-forward/pypy/module/rctime/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/rctime/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/rctime/__init__.py Tue Nov 2 17:16:11 2010
@@ -2,6 +2,8 @@
from pypy.interpreter.mixedmodule import MixedModule
import os
+_WIN = os.name == "nt"
+
class Module(MixedModule):
applevel_name = 'time'
@@ -27,6 +29,10 @@
}
def startup(self, space):
+ if _WIN:
+ from pypy.module.rctime.interp_time import State
+ space.fromcache(State).startup(space)
+
# this machinery is needed to expose constants
# that have to be initialized one time only
from pypy.module.rctime import interp_time
Modified: pypy/branch/fast-forward/pypy/module/rctime/interp_time.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/rctime/interp_time.py (original)
+++ pypy/branch/fast-forward/pypy/module/rctime/interp_time.py Tue Nov 2 17:16:11 2010
@@ -14,6 +14,89 @@
_POSIX = os.name == "posix"
_WIN = os.name == "nt"
+if _WIN:
+ # Interruptible sleeps on Windows:
+ # We install a specific Console Ctrl Handler which sets an 'event'.
+ # time.sleep() will actually call WaitForSingleObject with the desired
+ # timeout. On Ctrl-C, the signal handler is called, the event is set,
+ # and the wait function exits.
+ from pypy.rlib import rwin32
+ from pypy.interpreter.error import wrap_windowserror, wrap_oserror
+ from pypy.module.thread import ll_thread as thread
+
+ # This is needed because the handler function must have the "WINAPI"
+ # calling convention, which is not supported by lltype.Ptr.
+ CtrlHandler_type = lltype.Ptr(lltype.FuncType([], rwin32.BOOL))
+ eci = ExternalCompilationInfo(
+ separate_module_sources=['''
+ #include <windows.h>
+
+ static BOOL (*CtrlHandlerRoutine)(
+ DWORD dwCtrlType);
+
+ static BOOL WINAPI winapi_CtrlHandlerRoutine(
+ DWORD dwCtrlType)
+ {
+ return CtrlHandlerRoutine(dwCtrlType);
+ }
+
+ BOOL pypy_timemodule_setCtrlHandlerRoutine(BOOL (*f)(DWORD))
+ {
+ CtrlHandlerRoutine = f;
+ SetConsoleCtrlHandler(winapi_CtrlHandlerRoutine, TRUE);
+ }
+
+ '''],
+ export_symbols=['pypy_timemodule_setCtrlHandlerRoutine'],
+ )
+ _setCtrlHandlerRoutine = rffi.llexternal(
+ 'pypy_timemodule_setCtrlHandlerRoutine',
+ [CtrlHandler_type], rwin32.BOOL,
+ compilation_info=eci)
+
+ def ProcessingCtrlHandler():
+ rwin32.SetEvent(globalState.interrupt_event)
+ # allow other default handlers to be called.
+ # Default Python handler will setup the
+ # KeyboardInterrupt exception.
+ return 0
+
+ class GlobalState:
+ def __init__(self):
+ self.init()
+
+ def init(self):
+ self.interrupt_event = rwin32.NULL_HANDLE
+
+ def startup(self, space):
+ # Initialize the event handle used to signal Ctrl-C
+ try:
+ globalState.interrupt_event = rwin32.CreateEvent(
+ rffi.NULL, True, False, rffi.NULL)
+ except WindowsError, e:
+ raise wrap_windowserror(space, e)
+ if not _setCtrlHandlerRoutine(ProcessingCtrlHandler):
+ raise wrap_windowserror(
+ space, rwin32.lastWindowsError("SetConsoleCtrlHandler"))
+
+ globalState = GlobalState()
+
+ class State:
+ def __init__(self, space):
+ self.main_thread = 0
+
+ def _freeze_(self):
+ self.main_thread = 0
+ globalState.init()
+
+ def startup(self, space):
+ self.main_thread = thread.get_ident()
+ globalState.startup(space)
+
+ def get_interrupt_event(self):
+ return globalState.interrupt_event
+
+
_includes = ["time.h"]
if _POSIX:
_includes.append('sys/time.h')
@@ -166,9 +249,37 @@
errno = rposix.get_errno()
return os.strerror(errno)
-def sleep(secs):
- pytime.sleep(secs)
-sleep.unwrap_spec = [float]
+if sys.platform != 'win32':
+ def sleep(space, secs):
+ pytime.sleep(secs)
+else:
+ from pypy.rlib import rwin32
+ from errno import EINTR
+ def _simple_sleep(space, secs, interruptible):
+ if secs == 0.0 or not interruptible:
+ pytime.sleep(secs)
+ else:
+ millisecs = int(secs * 1000)
+ interrupt_event = space.fromcache(State).get_interrupt_event()
+ rwin32.ResetEvent(interrupt_event)
+ rc = rwin32.WaitForSingleObject(interrupt_event, millisecs)
+ if rc == rwin32.WAIT_OBJECT_0:
+ # Yield to make sure real Python signal handler
+ # called.
+ pytime.sleep(0.001)
+ raise wrap_oserror(space,
+ OSError(EINTR, "sleep() interrupted"))
+ def sleep(space, secs):
+ # as decreed by Guido, only the main thread can be
+ # interrupted.
+ main_thread = space.fromcache(State).main_thread
+ interruptible = (main_thread == thread.get_ident())
+ MAX = sys.maxint / 1000.0 # > 24 days
+ while secs > MAX:
+ _simple_sleep(space, MAX, interruptible)
+ secs -= MAX
+ _simple_sleep(space, secs, interruptible)
+sleep.unwrap_spec = [ObjSpace, float]
def _get_module_object(space, obj_name):
w_module = space.getbuiltinmodule('time')
Modified: pypy/branch/fast-forward/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rwin32.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rwin32.py Tue Nov 2 17:16:11 2010
@@ -275,3 +275,16 @@
return res
finally:
lltype.free(handle_array, flavor='raw')
+
+ _CreateEvent = winexternal(
+ 'CreateEventA', [rffi.VOIDP, BOOL, BOOL, LPCSTR], HANDLE)
+ def CreateEvent(*args):
+ handle = _CreateEvent(*args)
+ if handle == NULL_HANDLE:
+ raise lastWindowsError("CreateEvent")
+ return handle
+ SetEvent = winexternal(
+ 'SetEvent', [HANDLE], BOOL)
+ ResetEvent = winexternal(
+ 'ResetEvent', [HANDLE], BOOL)
+
More information about the Pypy-commit
mailing list