def doWaitForMultipleEvents(self, timeout, reads=reads, writes=writes): log.msg(channel='system', event='iteration', reactor=self) if timeout is None: #timeout = INFINITE timeout = 100 else: timeout = int(timeout * 1000) if not (events or writes): # sleep so we don't suck up CPU time time.sleep(timeout / 1000.0) return canDoMoreWrites = 0 for fd in writes.keys(): if log.callWithLogger(fd, self._runWrite, fd): canDoMoreWrites = 1 if canDoMoreWrites: timeout = 0 handles = events.keys() or [self.dummyEvent] val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT | QS_ALLEVENTS) if val == WAIT_TIMEOUT: return elif val == WAIT_OBJECT_0 + len(handles): exit = win32gui.PumpWaitingMessages() if exit: self.callLater(0, self.stop) return elif val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): fd, action = events[handles[val - WAIT_OBJECT_0]] log.callWithLogger(fd, self._runAction, action, fd)
def ReceiveThread(self): from win32event import ( ResetEvent, MsgWaitForMultipleObjects, QS_ALLINPUT, WAIT_OBJECT_0, WAIT_TIMEOUT, ) from win32file import ReadFile, AllocateReadBuffer, GetOverlappedResult from win32api import GetLastError continueLoop = True overlapped = self.serial._overlappedRead hComPort = self.serial.hComPort hEvent = overlapped.hEvent stopEvent = self.stopEvent n = 1 waitingOnRead = False buf = AllocateReadBuffer(n) while continueLoop: if not waitingOnRead: ResetEvent(hEvent) hr, _ = ReadFile(hComPort, buf, overlapped) if hr == 997: waitingOnRead = True elif hr == 0: pass #n = GetOverlappedResult(hComPort, overlapped, 1) #self.HandleChar(str(buf)) else: self.PrintError("error") raise rc = MsgWaitForMultipleObjects( (hEvent, stopEvent), 0, 1000, QS_ALLINPUT ) if rc == WAIT_OBJECT_0: n = GetOverlappedResult(hComPort, overlapped, 1) if n: self.HandleChar(str(buf)) #else: # print "WAIT_OBJECT_0", n, str(buf[:n]) waitingOnRead = False elif rc == WAIT_OBJECT_0+1: continueLoop = False elif rc == WAIT_TIMEOUT: pass else: self.PrintError("unknown message")
def doEvents(self): handles = self._events.keys() if len(handles) > 0: val = None while val != WAIT_TIMEOUT: val = MsgWaitForMultipleObjects(handles, 0, 0, QS_ALLINPUT | QS_ALLEVENTS) if val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): event_id = handles[val - WAIT_OBJECT_0] if event_id in self._events: fd, action = self._events[event_id] log.callWithLogger(fd, self._runAction, action, fd) elif val == WAIT_TIMEOUT: pass else: #print 'Got an unexpected return of %r' % val return
def waitForEvents(self, timeout): from win32api import GetCurrentThreadId from win32event import INFINITE from win32event import MsgWaitForMultipleObjects, \ QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0 from pythoncom import PumpWaitingMessages import types if not isinstance(timeout, int): raise TypeError("The timeout argument is not an integer") if self.tid != GetCurrentThreadId(): raise Exception("wait for events from the same thread you inited!") if timeout < 0: cMsTimeout = INFINITE else: cMsTimeout = timeout rc = MsgWaitForMultipleObjects(self.handles, 0, cMsTimeout, QS_ALLINPUT) if WAIT_OBJECT_0 <= rc < WAIT_OBJECT_0 + len(self.handles): # is it possible? rc = 2 elif rc == WAIT_OBJECT_0 + len(self.handles): # Waiting messages PumpWaitingMessages() rc = 0 else: # Timeout rc = 1 # check for interruption self.oIntCv.acquire() if self.fInterrupted: self.fInterrupted = False rc = 1 self.oIntCv.release() return rc
def Demo( prog_id ): # First create the object object = Dispatch(prog_id) print "Thread", GetCurrentThreadId(), "creating object" created_id = object.GetCreatedThreadId() print "Object reports it was created on thread", created_id # Now create the threads, remembering the handles. handles = [] for i in range(3): # As we are not allowed to pass the object directly between # apartments, we need to marshal it. object_stream = CoMarshalInterThreadInterfaceInStream( IID_IDispatch, object ) # Build an argument tuple for the thread. args = (object_stream,) handle, id = beginthreadex(None, 0, WorkerThread, args, 0) handles.append(handle) # Now we have all the threads running, wait for them to terminate. # also remember how many times we are asked to pump messages. num_pumps = 0 while handles: # A quirk in MsgWaitForMultipleObjects means we must wait # for each event one at at time rc = MsgWaitForMultipleObjects(handles, 0, 5000, QS_ALLINPUT) if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(handles): # A thread finished - remove its handle. del handles[rc-WAIT_OBJECT_0] elif rc==WAIT_OBJECT_0 + len(handles): # Waiting message num_pumps = num_pumps + 1 PumpWaitingMessages() else: print "Nothing seems to be happening", print "but I will keep waiting anyway..." print "Pumped messages", num_pumps, "times" print "Demo of", prog_id, "finished."
def doWaitForMultipleEvents(self, timeout): log.msg(channel='system', event='iteration', reactor=self) if timeout is None: timeout = 100 # Keep track of whether we run any application code before we get to the # MsgWaitForMultipleObjects. If so, there's a chance it will schedule a # new timed call or stop the reactor or do something else that means we # shouldn't block in MsgWaitForMultipleObjects for the full timeout. ranUserCode = False # If any descriptors are trying to close, try to get them out of the way # first. for reader in self._closedAndReading.keys(): ranUserCode = True self._runAction('doRead', reader) for fd in self._writes.keys(): ranUserCode = True log.callWithLogger(fd, self._runWrite, fd) if ranUserCode: # If application code *might* have scheduled an event, assume it # did. If we're wrong, we'll get back here shortly anyway. If # we're right, we'll be sure to handle the event (including reactor # shutdown) in a timely manner. timeout = 0 if not (self._events or self._writes): # sleep so we don't suck up CPU time time.sleep(timeout) return handles = self._events.keys() or [self.dummyEvent] timeout = int(timeout * 1000) val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT) if val == WAIT_TIMEOUT: return elif val == WAIT_OBJECT_0 + len(handles): exit = win32gui.PumpWaitingMessages() if exit: self.callLater(0, self.stop) return elif val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): event = handles[val - WAIT_OBJECT_0] fd, action = self._events[event] if fd in self._reads: # Before anything, make sure it's still a valid file descriptor. fileno = fd.fileno() if fileno == -1: self._disconnectSelectable(fd, posixbase._NO_FILEDESC, False) return # Since it's a socket (not another arbitrary event added via # addEvent) and we asked for FD_READ | FD_CLOSE, check to see if # we actually got FD_CLOSE. This needs a special check because # it only gets delivered once. If we miss it, it's gone forever # and we'll never know that the connection is closed. events = WSAEnumNetworkEvents(fileno, event) if FD_CLOSE in events: self._closedAndReading[fd] = True log.callWithLogger(fd, self._runAction, action, fd)
def doWaitForProcessExit(self, processHandleKey): # Create a hidden window that will receive messages for things # like adding new handles to wait on or quitting the thread. # I use the Button class because I'm too lazy to register my own. theWindow = win32gui.CreateWindow( "Button", # lpClassName "", # lpWindowName 0, # dwStyle 0, # x 0, # y 0, # width 0, # height 0, # parent 0, # menu 0, # hInstance None # lParam ) # list of process handles to wait for handles = [] # First time through add first process handle to list handles.append(self.needWaiting[processHandleKey]) # Save window so IO thread can wake us up with it threadHandle = self.phandleKeyToThreadHandle[processHandleKey] self.threadToMsgWindow[threadHandle] = theWindow self.threadToNumEnded[threadHandle] = 0 # Signal an event so IO thread knows that window # is successfully created so it can call PostMessage. # Note that this line is intentionally placed after setting # threadToMsgWindow so that we don't attempt to lookup a msg window # in the IO thread before defining it here. self.threadToMsgWindowCreated[threadHandle] = True SetEvent(self.threadToMsgWindowCreationEvent[threadHandle]) while True: val = MsgWaitForMultipleObjects(handles, 0, INFINITE, QS_POSTMESSAGE | QS_ALLEVENTS) if val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): phandle = handles[val - WAIT_OBJECT_0] # Remove process handle from wait list handles.remove(phandle) # Tell transport process ended transport = self.phandleToTransport[phandle] phandleKey = self.phandleToPhandleKey[phandle] self.reactor.callFromThread(self.processEnded, phandle, phandleKey) elif val == WAIT_OBJECT_0 + len(handles): # We were interrupted by the IO thread calling PostMessage status, msg = win32gui.PeekMessage(theWindow, 0, 0, win32con.PM_REMOVE) while status != 0: if msg[1] == WM_NEW_PHANDLE: # Add a process handle to wait list phandleKey = msg[2] handles.append(self.needWaiting[phandleKey]) elif msg[1] == WM_CLOSE_THREAD: # Return so thread will exit return else: # Drop all other messages, since we receive all messages, not # just WM_NEW_PHANDLE and WM_CLOSE_THREAD. pass status, msg = win32gui.PeekMessage(theWindow, 0, 0, win32con.PM_REMOVE) else: raise Exception( "MsgWaitForMultipleObjects returned unknown value: %s" % str(val))