예제 #1
0
    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)
예제 #2
0
    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")
예제 #3
0
 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
예제 #4
0
    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
예제 #5
0
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."
예제 #6
0
    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)
예제 #7
0
    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))