
[XMc           @   s.  d  Z  d d l Z d d l Z d d l m Z d d l m Z m Z m Z m	 Z	 m
 Z
 d d l m Z m Z d d l m Z m Z m Z m Z d d l Z d d l m Z d d l m Z m Z m Z d d	 l m Z m Z d d
 l m Z d d l m Z d e j f d     YZ  d   Z! d d g Z" d S(   s  
A win32event based implementation of the Twisted main loop.

This requires pywin32 (formerly win32all) or ActivePython to be installed.

To install the event loop (and you should do this before any connections,
listeners or connectors are added)::

    from twisted.internet import win32eventreactor
    win32eventreactor.install()

Maintainer: Itamar Shtull-Trauring


LIMITATIONS:
 1. WaitForMultipleObjects and thus the event loop can only handle 64 objects.
 2. Process running has some problems (see Process docstring).


TODO:
 1. Event loop handling of writes is *very* problematic (this is causing failed tests).
    Switch to doing it the correct way, whatever that means (see below).
 2. Replace icky socket loopback waker with event based waker (use dummyEvent object)
 3. Switch everyone to using Free Software so we don't have to deal with proprietary APIs.


ALTERNATIVE SOLUTIONS:
 - IIRC, sockets can only be registered once. So we switch to a structure
   like the poll() reactor, thus allowing us to deal with write events in
   a decent fashion. This should allow us to pass tests, but we're still
   limited to 64 events.

Or:

 - Instead of doing a reactor, we make this an addon to the select reactor.
   The WFMO event loop runs in a separate thread. This means no need to maintain
   separate code for networking, 64 event limit doesn't apply to sockets,
   we can run processes and other win32 stuff in default event loop. The
   only problem is that we're stuck with the icky socket based waker.
   Another benefit is that this could be extended to support >64 events
   in a simpler manner than the previous solution.

The 2nd solution is probably what will get implemented.
iN(   t
   implements(   t   WSAEventSelectt   FD_READt   FD_CLOSEt	   FD_ACCEPTt
   FD_CONNECT(   t   CreateEventt   MsgWaitForMultipleObjects(   t   WAIT_OBJECT_0t   WAIT_TIMEOUTt   QS_ALLINPUTt   QS_ALLEVENTS(   t	   posixbase(   t   logt
   threadablet   failure(   t   IReactorFDSett   IReactorProcess(   t   IReactorWin32Events(   t   Processt   Win32Reactorc           B   s   e  Z d  Z e e e e  e d d d d  Z	 d   Z
 d   Z d   Z d   Z d   Z d   Z d   Z d	   Z d
   Z d   Z d   Z d   Z d   Z d   Z e Z d i  d d d d d d  Z RS(   s  
    Reactor that uses Win32 event APIs.

    @ivar _reads: A dictionary mapping L{FileDescriptor} instances to a
        win32 event object used to check for read events for that descriptor.

    @ivar _writes: A dictionary mapping L{FileDescriptor} instances to a
        arbitrary value.  Keys in this dictionary will be given a chance to
        write out their data.

    @ivar _events: A dictionary mapping win32 event object to tuples of
        L{FileDescriptor} instances and event masks.
    i    c         C   s/   i  |  _  i  |  _ i  |  _ t j j |   d  S(   N(   t   _readst   _writest   _eventsR   t   PosixReactorBaset   __init__(   t   self(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyR   Z   s    			c         C   s<   t  d d d d  } t | | |  | | f |  j | <| S(   s9   
        Make a win32 event object for a socket.
        i    N(   R   t   NoneR   R   (   R   t   fdt   actiont   whyt   event(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   _makeSocketEventa   s    c         C   s   | | f |  j  | <d S(   s:   
        Add a new win32 event to the event loop.
        N(   R   (   R   R   R   R   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   addEventk   s    c         C   s   |  j  | =d S(   s"   
        Remove an event.
        N(   R   (   R   R   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   removeEventr   s    c         C   s>   | |  j  k r: |  j | d t t Bt Bt B |  j  | <n  d S(   sY   
        Add a socket FileDescriptor for notification of data available to read.
        t   doReadN(   R   R    R   R   R   R   (   R   t   reader(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt	   addReadery   s    c         C   s#   | |  j  k r d |  j  | <n  d S(   sZ   
        Add a socket FileDescriptor for notification of data available to write.
        i   N(   R   (   R   t   writer(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt	   addWriter   s    c         C   s1   | |  j  k r- |  j |  j  | =|  j  | =n  d S(   sH   Remove a Selectable for notification of data available to read.
        N(   R   R   (   R   R$   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   removeReader   s    c         C   s    | |  j  k r |  j  | =n  d S(   sI   Remove a Selectable for notification of data available to write.
        N(   R   (   R   R&   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   removeWriter   s    c         C   s   |  j  |  j |  j  S(   sD   
        Remove all selectables, and return a list of them.
        (   t
   _removeAllR   R   (   R   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt	   removeAll   s    c         C   s   |  j  j   S(   N(   R   t   keys(   R   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt
   getReaders   s    c         C   s   |  j  j   S(   N(   R   R,   (   R   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt
   getWriters   s    c         C   s  t  j d d d d d |   | d  k r1 d } n t | d  } |  j pP |  j sh t j | d  d  Sd	 } x8 |  j j   D]' } t  j	 | |  j
 |  r~ d
 } q~ q~ W| r d	 } n  |  j j   p |  j g } t | d	 | t t B } | t k r d  S| t t |  k r>t j   } | r|  j d	 |  j  d  SnY | t k r| t t |  k  r|  j | | t \ } } t  j	 | |  j | |  n  d  S(   Nt   channelt   systemR   t	   iterationt   reactorid   i  g     @@i    i   (   R   t   msgR   t   intR   R   t   timet   sleepR,   t   callWithLoggert	   _runWritet
   dummyEventR   R
   R   R	   R   t   lent   win32guit   PumpWaitingMessagest	   callLatert   stopt
   _runAction(   R   t   timeoutt   canDoMoreWritesR   t   handlest   valt   exitR   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   doWaitForMultipleEvents   s2    		"c         C   s   d } y | j    } Wn! t j   d } t j   n X| r |  j |  |  j |  y | j t j	 |   Wq t j   q Xn | d  k r d Sd  S(   Ni    i   (   t   doWritet   syst   exc_infoR   t   deferrR(   R)   t   connectionLostR   t   FailureR   (   R   R   t   closed(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyR8      s    c         C   s`   y t  | |    } Wn! t j   d } t j   n X| r\ |  j | | | d k  n  d  S(   Ni   R#   (   t   getattrRG   RH   R   RI   t   _disconnectSelectable(   R   R   R   RL   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyR?      s    c
   
      C   s   | d k	 r t d   n  | d k	 r6 t d   n  | rK t d   n  |	 d k	 rf t d   n  |  j | |  \ } } t |  | | | | |  S(   s   Spawn a process.s,   Setting UID is unsupported on this platform.s,   Setting GID is unsupported on this platform.s&   PTYs are unsupported on this platform.sG   Custom child file descriptor mappings are unsupported on this platform.N(   R   t
   ValueErrort   _checkProcessArgsR   (
   R   t   processProtocolt
   executablet   argst   envt   patht   uidt   gidt   usePTYt   childFDs(    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   spawnProcess   s    N(    (   t   __name__t
   __module__t   __doc__R    R   R   R   R   R   R9   R   R    R!   R"   R%   R'   R(   R)   R+   R-   R.   RE   R8   R?   t   doIterationRZ   (    (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyR   H   s&   		
										"		
c          C   s3   t  j d  t   }  d d  l } | j |   d  S(   Ni   i(   R   t   initR   t   maint   installReactor(   t   rR`   (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   install   s    	Rc   (#   R]   R5   RG   t   zope.interfaceR    t	   win32fileR   R   R   R   R   t
   win32eventR   R   R   R	   R
   R   R;   t   twisted.internetR   t   twisted.pythonR   R   R   t   twisted.internet.interfacesR   R   R   t   twisted.internet._dumbwin32procR   R   R   Rc   t   __all__(    (    (    sF   /usr/lib/python2.7/dist-packages/twisted/internet/win32eventreactor.pyt   <module>0   s   ("	