
    e                         d dl mZmZmZ d dlmZmZ d dlZd dlm	Z	 dZ
d Z G d d      Z e       ad	 Z G d
 de      Zi ad Z G d de      Zy)    )LockThreadBoundedSemaphore)QueueEmptyN)getglobaluiSTOP_MONITORc                     t        |      D ]  }| j                           t        |      D ]  }| j                           y)zjBlock until `semaphore` gets back to its original state, ie all acquired
    resources have been released.N)rangeacquirerelease)	semaphoreoriginalstateis      1/usr/share/offlineimap3/offlineimap/threadutil.pysemaphoreresetr      sF     =!  =!     c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)accountThreadsznStore the list of all threads in the software so it can be used to find out
    what's running and what's not.c                 0    t               | _        g | _        y N)r   locklistselfs    r   __init__zaccountThreads.__init__,   s    F		r   c                 |    | j                   5  | j                  j                  |       d d d        y # 1 sw Y   y xY wr   )r   r   appendr   threads     r   addzaccountThreads.add0   0    YY 	%IIV$	% 	% 	%   2;c                 |    | j                   5  | j                  j                  |       d d d        y # 1 sw Y   y xY wr   )r   r   remover   s     r   r%   zaccountThreads.remove4   r"   r#   c                     | j                   5  t        | j                        dk  r
	 d d d        y | j                  j                         cd d d        S # 1 sw Y   y xY w)N   )r   lenr   popr   s    r   r)   zaccountThreads.pop8   sJ    YY 	#499~!	# 	# 99==?	# 	# 	#s   AAAc                 L    	 | j                         }|y |j                          $r   )r)   joinr   s     r   waitzaccountThreads.wait>   s&    XXZF~KKM	 r   N)	__name__
__module____qualname____doc__r   r!   r%   r)   r,    r   r   r   r   (   s     &%%#r   r   c                     t               } 	 	 t        j                  dd      }|j                  it	        |j                  t
              rt
        | j                  |       t        dt        |j                        dt        |j                        d      |j                  t        k(  ry| j                  |       	 # t        $ r Y w xY w)zAn infinite "monitoring" loop watching for finished ExitNotifyThread's.

    This one is supposed to run in the main thread.
    T<   Nz$thread has 'exit_exception' set to 'z' [zC] but this value is unexpected and the ui did not stop the program.)r   exitedThreadsgetexit_exception
isinstance
SystemExitthreadExceptionAssertionErrorreprtypeexit_messager	   threadExitedr   )uir    s     r   monitorr@   M   s     
B
	 #&&tR0F $$0f33Z@ %$""6*$ '+6+@+@&A4H]H]C^&` a a $$4'; <  		s   BB? ,B? ?	C
Cc                   P     e Zd ZdZ fdZd ZddZed        Zed        Z	 xZ
S )ExitNotifyThreada  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                 x    t        t        | 
  |i | | j                  d       d | _        d | _        d | _        y )NT)superrB   r   	setDaemonr=   	_exit_exc_exit_stacktrace)r   argskwargs	__class__s      r   r   zExitNotifyThread.__init__   s=    .?? 	t  $r   c                     	 t        j                  |        t        j                  | d       y# t        $ r0}t        j                         }| j                  ||       Y d}~Kd}~ww xY w)z.Allow profiling of a run and store exceptions.NT)r   run	Exception	traceback
format_excset_exit_exceptionr4   put)r   etbs      r   rL   zExitNotifyThread.run   sX    	+JJt 	$%  	+%%'B##Ar**	+s   . 	A'&A""A'c                      || _         || _        y)zbSets Exception and stacktrace of a thread, so that other
        threads can query its exit statusN)rF   rG   )r   excsts      r   rP   z#ExitNotifyThread.set_exit_exception   s      "r   c                     | j                   S )zReturns the cause of the exit, one of:
        Exception() -- the thread aborted with this exception
        None -- normal termination.)rF   r   s    r   r6   zExitNotifyThread.exit_exception   s     ~~r   c                     | j                   S )z4Returns a string representing the stack trace if set)rG   r   s    r   exit_stacktracez ExitNotifyThread.exit_stacktrace   s     $$$r   r   )r-   r.   r/   r0   r   rL   rP   propertyr6   rY   __classcell__rJ   s   @r   rB   rB   x   s?    	%&#   % %r   rB   c                 :    | t         vrt        |      t         | <   yy)zInitialize the instance-limited thread implementation.

    Run up to intancemax threads for the given limitNamespace. This allows to
    honor maxsyncaccounts and maxconnections.N)limitedNamespacesr   )limitNamespaceinstancemaxs     r   initInstanceLimitra      s"     ..,<[,I.) /r   c                   *     e Zd Z fdZd Zd Z xZS )InstanceLimitedThreadc                 :    || _         t        t        |   |i | y r   )r_   rD   rc   r   )r   r_   rH   rI   rJ   s       r   r   zInstanceLimitedThread.__init__   s     ,#T3TDVDr   c                 p    t         | j                     j                          t        j	                  |        y r   )r^   r_   r   rB   startr   s    r   rf   zInstanceLimitedThread.start   s)     	$--.668t$r   c                 *   	 t         j                  |        t        r6t        | j                     r"t        | j                     j	                          y y y # t        r6t        | j                     r"t        | j                     j	                          w w w xY wr   )rB   rL   r^   r_   r   r   s    r   rL   zInstanceLimitedThread.run   sz    	A  & %6t7J7J%K!$"5"56>>@ &L  %6t7J7J%K!$"5"56>>@ &L s   A >B)r-   r.   r/   r   rf   rL   r[   r\   s   @r   rc   rc      s    E%Ar   rc   )	threadingr   r   r   queuer   r   rN   offlineimap.uir   r	   r   r   r4   r@   rB   r^   ra   rc   r1   r   r   <module>rk      sd   $ 5 4   & D (V5%v 5%x  	JA, Ar   