
[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	 d d l m
 Z
 m Z d d l m Z d d l m Z m Z d d l m Z m Z d	 e j f d
     YZ d   Z d	 d g Z d S(   s  
A kqueue()/kevent() based implementation of the Twisted main loop.

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

    | from twisted.internet import kqreactor
    | kqreactor.install()

This reactor only works on FreeBSD and requires PyKQueue 1.3, which is
available at:  U{http://people.freebsd.org/~dwhite/PyKQueue/}



You're going to need to patch PyKqueue::

    =====================================================
    --- PyKQueue-1.3/kqsyscallmodule.c	Sun Jan 28 21:59:50 2001
    +++ PyKQueue-1.3/kqsyscallmodule.c.new	Tue Jul 30 18:06:08 2002
    @@ -137,7 +137,7 @@
     }
     
     statichere PyTypeObject KQEvent_Type = {
    -  PyObject_HEAD_INIT(NULL)
    +  PyObject_HEAD_INIT(&PyType_Type)
       0,                             // ob_size
       "KQEvent",                     // tp_name
       sizeof(KQEventObject),         // tp_basicsize
    @@ -291,13 +291,14 @@
     
       /* Build timespec for timeout */
       totimespec.tv_sec = timeout / 1000;
    -  totimespec.tv_nsec = (timeout % 1000) * 100000;
    +  totimespec.tv_nsec = (timeout % 1000) * 1000000;
     
       // printf("timespec: sec=%d nsec=%d\n", totimespec.tv_sec, totimespec.tv_nsec);
     
       /* Make the call */
    -
    +  Py_BEGIN_ALLOW_THREADS
       gotNumEvents = kevent (self->fd, changelist, haveNumEvents, triggered, wantNumEvents, &totimespec);
    +  Py_END_ALLOW_THREADS
     
       /* Don't need the input event list anymore, so get rid of it */
       free (changelist);
    @@ -361,7 +362,7 @@
     statichere PyTypeObject KQueue_Type = {
            /* The ob_type field must be initialized in the module init function
             * to be portable to Windows without using C++. */
    -	PyObject_HEAD_INIT(NULL)
    +	PyObject_HEAD_INIT(&PyType_Type)
            0,			/*ob_size*/
            "KQueue",			/*tp_name*/
            sizeof(KQueueObject),	/*tp_basicsize*/

iN(   t
   implements(   t   EVFILT_READt   EVFILT_WRITEt	   EV_DELETEt   EV_ADD(   t   kqueuet   kevent(   t   IReactorFDSet(   t   logt   failure(   t   maint	   posixbaset   KQueueReactorc           B   s   e  Z d  Z e e  d   Z d   Z d   Z d   Z d   Z	 d   Z
 d   Z d   Z d	   Z d
   Z d   Z e Z RS(   sQ  
    A reactor that uses kqueue(2)/kevent(2).

    @ivar _kq: A L{kqueue} which will be used to check for I/O readiness.

    @ivar _selectables: A dictionary mapping integer file descriptors to
        instances of L{FileDescriptor} which have been registered with the
        reactor.  All L{FileDescriptors} which are currently receiving read or
        write readiness notifications will be present as values in this
        dictionary.

    @ivar _reads: A dictionary mapping integer file descriptors to arbitrary
        values (this is essentially a set).  Keys in this dictionary will be
        registered with C{_kq} for read readiness notifications which will be
        dispatched to the corresponding L{FileDescriptor} instances in
        C{_selectables}.

    @ivar _writes: A dictionary mapping integer file descriptors to arbitrary
        values (this is essentially a set).  Keys in this dictionary will be
        registered with C{_kq} for write readiness notifications which will be
        dispatched to the corresponding L{FileDescriptor} instances in
        C{_selectables}.
    c         C   s;   t    |  _ i  |  _ i  |  _ i  |  _ t j j |   d S(   sn   
        Initialize kqueue object, file descriptor tracking dictionaries, and the
        base class.
        N(   R   t   _kqt   _readst   _writest   _selectablesR   t   PosixReactorBaset   __init__(   t   self(    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyR   d   s
    			c         G   s#   |  j  j t |   g d d  d  S(   Ni    (   R   R   (   R   t   args(    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   _updateRegistrationp   s    c         C   sO   | j    } | |  j k rK | |  j | <d |  j | <|  j | t t  n  d S(   sI   Add a FileDescriptor for notification of data available to read.
        i   N(   t   filenoR   R   R   R   R   (   R   t   readert   fd(    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt	   addReaders   s
    c         C   sO   | j    } | |  j k rK | |  j | <d |  j | <|  j | t t  n  d S(   sJ   Add a FileDescriptor for notification of data available to write.
        i   N(   R   R   R   R   R   R   (   R   t   writerR   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt	   addWriter|   s
    c         C   s[   | j    } | |  j k rW |  j | =| |  j k rA |  j | =n  |  j | t t  n  d S(   sH   Remove a Selectable for notification of data available to read.
        N(   R   R   R   R   R   R   R   (   R   R   R   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   removeReader   s    
c         C   s[   | j    } | |  j k rW |  j | =| |  j k rA |  j | =n  |  j | t t  n  d S(   sI   Remove a Selectable for notification of data available to write.
        N(   R   R   R   R   R   R   R   (   R   R   R   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   removeWriter   s    
c         C   sJ   |  j  g  |  j D] } |  j | ^ q g  |  j D] } |  j | ^ q0  S(   sD   
        Remove all selectables, and return a list of them.
        (   t
   _removeAllR   R   R   (   R   R   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt	   removeAll   s     c         C   s!   g  |  j  D] } |  j | ^ q
 S(   N(   R   R   (   R   R   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt
   getReaders   s    c         C   s!   g  |  j  D] } |  j | ^ q
 S(   N(   R   R   (   R   R   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt
   getWriters   s    c   
      C   s   | d k r d } n t | d  } y% |  j j g  t |  j  |  } Wn- t k
 ry } | d t j k rs d S  n X|  j	 } xh | D]` } d } | j
 | j } } y |  j | }	 Wn t k
 r q n Xt j |	 | |	 | |  q Wd S(   s   Poll the kqueue for new events.i  i    N(   t   Nonet   intR   R   t   lenR   t   OSErrort   errnot   EINTRt   _doWriteOrReadt   identt   filtert   KeyErrorR   t   callWithLogger(
   R   t   timeoutt   lt   et   _drdwt   eventt   whyR   R*   t
   selectable(    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   doKEvent   s$    	%	c         C   s   yX | t  k r | j   } n  | t k r9 | j   } n  | j   | k sW t j } n  Wn! t j   d } t	 j
   n X| r |  j |  |  j |  | j t j |   n  d  S(   Ni   (   R   t   doReadR   t   doWriteR   R
   t   CONNECTION_LOSTt   syst   exc_infoR   t   deferrR   R   t   connectionLostR	   t   Failure(   R   R3   R   R*   R2   (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyR(      s    (   t   __name__t
   __module__t   __doc__R    R   R   R   R   R   R   R   R   R    R!   R4   R(   t   doIteration(    (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyR   J   s   
							
	
						c          C   s   t    }  t j |   d  S(   N(   R   R
   t   installReactor(   t   k(    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   install   s    	RC   (   R?   R&   R8   t   zope.interfaceR    t	   kqsyscallR   R   R   R   R   R   t   twisted.internet.interfacesR   t   twisted.pythonR   R	   t   twisted.internetR
   R   R   R   RC   t   __all__(    (    (    s>   /usr/lib/python2.7/dist-packages/twisted/internet/kqreactor.pyt   <module>;   s   "	