ó
Gh\c           @   s  d  d l  m Z m Z m Z m Z y d  d l m Z m Z Wn' e k
 re d  d l m Z m Z n Xd  d l	 Z	 d  d l
 Z d  d l m Z d Z d „  Z d e f d „  ƒ  YZ e ƒ  a d	 „  Z d
 e f d „  ƒ  YZ i  a d „  Z d e f d „  ƒ  YZ d S(   iÿÿÿÿ(   t   Lockt   Threadt   BoundedSemaphoret   currentThread(   t   Queuet   EmptyN(   t   getglobaluit   STOP_MONITORc         C   sF   x t  | ƒ D] } |  j ƒ  q Wx t  | ƒ D] } |  j ƒ  q. Wd S(   sj   Block until `semaphore` gets back to its original state, ie all acquired
    resources have been released.N(   t   ranget   acquiret   release(   t	   semaphoret   originalstatet   i(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   semaphorereset"   s    t   accountThreadsc           B   s;   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   sn   Store the list of all threads in the software so it can be used to find out
    what's running and what's not.c         C   s   t  ƒ  |  _ g  |  _ d  S(   N(   R    t   lockt   list(   t   self(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   __init__0   s    c         C   s$   |  j   |  j j | ƒ Wd  QXd  S(   N(   R   R   t   append(   R   t   thread(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   add4   s    
c         C   s$   |  j   |  j j | ƒ Wd  QXd  S(   N(   R   R   t   remove(   R   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR   8   s    
c         C   s:   |  j  + t |  j ƒ d k  r# d  S|  j j ƒ  SWd  QXd  S(   Ni   (   R   t   lenR   t   Nonet   pop(   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR   <   s    
c         C   s7   x0 t  r2 |  j ƒ  } | d  k r% Pn  | j ƒ  q Wd  S(   N(   t   TrueR   R   t   join(   R   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   waitB   s
    	(   t   __name__t
   __module__t   __doc__R   R   R   R   R   (    (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR   ,   s   				c          C   sÆ   t  ƒ  }  x¶ t rÁ y˜ t j t d ƒ } | j d k	 r‰ t | j t ƒ rQ t ‚ n  |  j | ƒ t	 d t
 | j ƒ t | j ƒ f ƒ ‚ n  | j t k rœ Pn |  j | ƒ Wq t k
 r½ q Xq Wd S(   sK  An infinite "monitoring" loop watching for finished ExitNotifyThread's.

    This one is supposed to run in the main thread.
    :param callback: the function to call when a thread terminated. That
                     function is called with a single argument -- the
                     ExitNotifyThread that has terminated. The monitor will
                     not continue to monitor for other threads until
                     'callback' returns, so if it intends to perform long
                     calculations, it should start a new thread itself -- but
                     NOT an ExitNotifyThread, or else an infinite loop
                     may result.
                     Furthermore, the monitor will hold the lock all the
                     while the other thread is waiting.
    :type callback:  a callable function
    i<   sn   thread has 'exit_exception' set to '%s' [%s] but this value is unexpected and the ui did not stop the program.N(   R   R   t   exitedThreadst   gett   exit_exceptionR   t
   isinstancet
   SystemExitt   threadExceptiont   AssertionErrort   reprt   typet   exit_messageR   t   threadExitedR   (   t   uiR   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   monitorP   s    			%t   ExitNotifyThreadc           B   sJ   e  Z d  Z d „  Z d „  Z d d „ Z e d „  ƒ Z e d „  ƒ Z	 RS(   sË  This class is designed to alert a "monitor" to the fact that a
    thread has exited and to provide for the ability for it to find out
    why.  All instances are made daemon threads (setDaemon(True), so we
    bail out when the mainloop dies.

    The thread can set instance variables self.exit_message for a human
    readable reason of the thread exit.

    There is one instance of this class at runtime. The main thread waits for
    the monitor to end.c         O   sE   t  t |  ƒ j | | Ž  |  j t ƒ d  |  _ d  |  _ d  |  _ d  S(   N(	   t   superR.   R   t	   setDaemonR   R   R*   t	   _exit_exct   _exit_stacktrace(   R   t   argst   kwargs(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR   ’   s
    		c         C   sW   y t  j |  ƒ Wn/ t k
 rB } t j ƒ  } |  j | | ƒ n Xt j |  t ƒ d S(   s.   Allow profiling of a run and store exceptions.N(	   R   t   runt	   Exceptiont	   tracebackt
   format_exct   set_exit_exceptionR!   t   putR   (   R   t   et   tb(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR5   ›   s    c         C   s   | |  _  | |  _ d S(   sb   Sets Exception and stacktrace of a thread, so that other
        threads can query its exit statusN(   R1   R2   (   R   t   exct   st(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR9   ¨   s    	c         C   s   |  j  S(   sˆ   Returns the cause of the exit, one of:
        Exception() -- the thread aborted with this exception
        None -- normal termination.(   R1   (   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR#   ¯   s    c         C   s   |  j  S(   s4   Returns a string representing the stack trace if set(   R2   (   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   exit_stacktrace·   s    N(
   R   R   R    R   R5   R   R9   t   propertyR#   R?   (    (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR.   †   s   
			c         C   s#   |  t  k r t | ƒ t  |  <n  d S(   s³   Initialize the instance-limited thread implementation.

    Run up to intancemax threads for the given limitNamespace. This allows to
    honor maxsyncaccounts and maxconnections.N(   t   limitedNamespacesR   (   t   limitNamespacet   instancemax(    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   initInstanceLimitÄ   s    t   InstanceLimitedThreadc           B   s#   e  Z d  „  Z d „  Z d „  Z RS(   c         O   s&   | |  _  t t |  ƒ j | | Ž  d  S(   N(   RB   R/   RE   R   (   R   RB   R3   R4   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR   Ñ   s    	c         C   s"   t  |  j j ƒ  t j |  ƒ d  S(   N(   RA   RB   R	   R.   t   start(   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyRF   Õ   s    c         C   s@   z t  j |  ƒ Wd  t r; t |  j r; t |  j j ƒ  n  Xd  S(   N(   R.   R5   RA   RB   R
   (   R   (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyR5   Ü   s    (   R   R   R   RF   R5   (    (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyRE   Ð   s   		(   t	   threadingR    R   R   R   R   R   t   ImportErrort   queueR7   t   os.patht   ost   offlineimap.uiR   R   R   t   objectR   R!   R-   R.   RA   RD   RE   (    (    (    s0   /usr/share/offlineimap/offlineimap/threadutil.pyt   <module>   s    "	
"		6<	