
    Ϫf*                       d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
mZ ddlmZmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ  ed      Z ed      Z G d de      Z G d de      Z e       Z  G d d      Z!y)z
twisted.python.threadpool: a pool of threads to which we dispatch tasks.

In most cases you can just use C{reactor.callInThread} and friends
instead of creating a thread pool directly.
    )annotations)Threadcurrent_thread)AnyCallableListOptionalTypeVar)	ParamSpecProtocol	TypedDict)pool)contextlog)
deprecated)Failure)Version_P_Rc                      e Zd ZddZy)_SupportsQsizec                     y N selfs    ;/usr/lib/python3/dist-packages/twisted/python/threadpool.pyqsizez_SupportsQsize.qsize   s        Nreturnint__name__
__module____qualname__r   r   r   r   r   r      s    r   r   c                  "    e Zd ZU ded<   ded<   y)_Stater"   minmaxN)r$   r%   r&   __annotations__r   r   r   r(   r(   "   s    	H	Hr   r(   c                  b   e Zd ZdZdZdZdZdZdZe	Z
 e  e edddd	      d
      e            Z ee      Z	 d	 	 	 	 	 ddZedd       Zedd       Zedd       Zed d       ZeZd!dZd!dZd"dZd!dZd#dZd$dZ	 	 	 	 	 	 	 	 d%dZ	 	 	 	 	 	 	 	 	 	 d&dZd!dZ 	 d'	 	 	 	 	 d(dZ!d!dZ"y))
ThreadPoola  
    This class (hopefully) generalizes the functionality of a pool of threads
    to which work can be dispatched.

    L{callInThread} and L{stop} should only be called from a single thread.

    @ivar started: Whether or not the thread pool is currently running.
    @type started: L{bool}

    @ivar threads: List of workers currently running in this thread pool.
    @type threads: L{list}

    @ivar _pool: A hook for testing.
    @type _pool: callable compatible with L{_pool}
          FNTwisted      r   zthreading.current_thread)versionreplacementc                     |dk\  sJ d       ||k  sJ d       | _         | _        | _        g  _        d fd}d fd} j	                  ||       _        y)	ac  
        Create a new threadpool.

        @param minthreads: minimum number of threads in the pool
        @type minthreads: L{int}

        @param maxthreads: maximum number of threads in the pool
        @type maxthreads: L{int}

        @param name: The name to give this threadpool; visible in log messages.
        @type name: native L{str}
        r   minimum is negativeminimum is greater than maximumc                      j                   | dj                         i|}j                  j                  |       |S )Nname)threadFactory_generateNamethreadsappend)akwthreadr   s      r   trackingThreadFactoryz2ThreadPool.__init__.<locals>.trackingThreadFactory`   sJ    'T''++-13F LL'Mr   c                 6     j                   sy j                  S )Nr   )startedr*   r   s   r   currentLimitz)ThreadPool.__init__.<locals>.currentLimitg   s    <<88Or   N)r>   r   r?   r   r!   r   r    )r)   r*   r9   r<   _pool_team)r   
minthreads
maxthreadsr9   rA   rD   s   `     r   __init__zThreadPool.__init__J   sf     Q5 55Z'J)JJ'	%'		
 ZZ.CD
r   c                h    | j                   j                         }|j                  |j                  z   S )a  
        For legacy compatibility purposes, return a total number of workers.

        @return: the current number of workers, both idle and busy (but not
            those that have been quit by L{ThreadPool.adjustPoolsize})
        @rtype: L{int}
        )rF   
statisticsidleWorkerCountbusyWorkerCount)r   statss     r   workerszThreadPool.workersn   s-     

%%'$$u'<'<<<r   c                R    dg| j                   j                         j                  z  S )z
        For legacy compatibility purposes, return the number of busy workers as
        expressed by a list the length of that number.

        @return: the number of workers currently processing a work item.
        @rtype: L{list} of L{None}
        N)rF   rK   rM   r   s    r   workingzThreadPool.workingz   s$     v

--/????r   c                R    dg| j                   j                         j                  z  S )a,  
        For legacy compatibility purposes, return the number of idle workers as
        expressed by a list the length of that number.

        @return: the number of workers currently alive (with an allocated
            thread) but waiting for new work.
        @rtype: L{list} of L{None}
        N)rF   rK   rL   r   s    r   waiterszThreadPool.waiters   s$     v

--/????r   c                *      G  fdd      } |       S )z
        For legacy compatibility purposes, return an object with a C{qsize}
        method that indicates the amount of work not yet allocated to a worker.

        @return: an object with a C{qsize} method.
        c                      e Zd Zd fdZy)$ThreadPool._queue.<locals>.NotAQueuec                L    j                   j                         j                  S )a  
                Pretend to be a Python threading Queue and return the
                number of as-yet-unconsumed tasks.

                @return: the amount of backlogged work not yet dispatched to a
                    worker.
                @rtype: L{int}
                )rF   rK   backloggedWorkCount)qr   s    r   r   z*ThreadPool._queue.<locals>.NotAQueue.qsize   s     zz,,.BBBr   Nr    r#   r   s   r   	NotAQueuerV      s	    	Cr   rZ   r   )r   rZ   s   ` r   _queuezThreadPool._queue   s    
	C 
	C {r   c                    d| _         d| _        | j                          | j                  j	                         j
                  }|r| j                  j                  |       yy)z'
        Start the threadpool.
        FTN)joinedrC   adjustPoolsizerF   rK   rX   grow)r   backlogs     r   startzThreadPool.start   sN     **'')==JJOOG$ r   c                :    | j                   j                  d       y)z
        Increase the number of available workers for the thread pool by 1, up
        to the maximum allowed by L{ThreadPool.max}.
        r2   N)rF   r_   r   s    r   startAWorkerzThreadPool.startAWorker   s    
 	

r   c                T    d| j                   xs t        |        d| j                   S )z
        Generate a name for a new pool thread.

        @return: A distinctive name for the thread.
        @rtype: native L{str}
        zPoolThread--)r9   idrO   r   s    r   r;   zThreadPool._generateName   s)     TYY2"T(31T\\NCCr   c                :    | j                   j                  d       y)zn
        Decrease the number of available workers by 1, by quitting one as soon
        as it's idle.
        r2   N)rF   shrinkr   s    r   stopAWorkerzThreadPool.stopAWorker   s    
 	

!r   c                t    t        | d|       t        j                  | | j                  | j                         y )N__dict__)setattrr-   rI   r)   r*   )r   states     r   __setstate__zThreadPool.__setstate__   s(    j%(D$((DHH5r   c                D    t        | j                  | j                        S )N)r)   r*   )r(   r)   r*   r   s    r   __getstate__zThreadPool.__getstate__   s    $((11r   c                2     | j                   d|g|i | y)a   
        Call a callable object in a separate thread.

        @param func: callable object to be called in separate thread

        @param args: positional arguments to be passed to C{func}

        @param kw: keyword args to be passed to C{func}
        N)callInThreadWithCallback)r   funcargsr?   s       r   callInThreadzThreadPool.callInThread   s      	&%%dD>4>2>r   c                    | j                   ryt        j                  j                         j                  d   dfdfd_        |_        | j                  j                         y)a$  
        Call a callable object in a separate thread and call C{onResult} with
        the return value, or a L{twisted.python.failure.Failure} if the
        callable raises an exception.

        The callable is allowed to block, but the C{onResult} function must not
        block and should perform as little work as possible.

        A typical action for C{onResult} for a threadpool used with a Twisted
        reactor would be to schedule a L{twisted.internet.defer.Deferred} to
        fire in the main reactor thread using C{.callFromThread}.  Note that
        C{onResult} is called inside the separate thread, not inside the
        reactor thread.

        @param onResult: a callable with the signature C{(success, result)}.
            If the callable returns normally, C{onResult} is called with
            C{(True, result)} where C{result} is the return value of the
            callable.  If the callable throws an exception, C{onResult} is
            called with C{(False, failure)}.

            Optionally, C{onResult} may be L{None}, in which case it is not
            called at all.

        @param func: callable object to be called in separate thread

        @param args: positional arguments to be passed to C{func}

        @param kw: keyword arguments to be passed to C{func}
        Nc                     	 j                         } d}d _         j                  j                  ||        d _        y |st	        j
                  |        y y # t        $ r t               } d}Y ]w xY w)NTF)theWorkBaseExceptionr   onResultr   err)resultok	inContexts     r   r   z6ThreadPool.callInThreadWithCallback.<locals>.inContext  sy    "**,
 !%I!!-""2v.%)	"  !  s   A A32A3c                 8    t        j                  g i S r   )r   call)rt   ctxrs   r?   s   r   <lambda>z5ThreadPool.callInThreadWithCallback.<locals>.<lambda>  s%    GLL%
%
 "%
 r   r!   None)	r]   r   theContextTrackercurrentContextcontextsry   r{   rF   do)r   r{   rs   rt   r?   r   r   s     ```@@r   rr   z#ThreadPool.callInThreadWithCallback   sX    H ;;''668AA"E	 $
	 &	

i r   c                    d| _         d| _        | j                  j                          | j                  D ]  }|j                           y)z9
        Shutdown the threads in the threadpool.
        TFN)r]   rC   rF   quitr<   join)r   r@   s     r   stopzThreadPool.stop$  s<     

ll 	FKKM	r   c                   || j                   }|| j                  }|dk\  sJ d       ||k  sJ d       || _         || _        | j                  sy| j                  | j                  kD  r2| j                  j                  | j                  | j                  z
         | j                  | j                   k  r3| j                  j                  | j                   | j                  z
         yy)z
        Adjust the number of available threads by setting C{min} and C{max} to
        new values.

        @param minthreads: The new value for L{ThreadPool.min}.

        @param maxthreads: The new value for L{ThreadPool.max}.
        Nr   r6   r7   )r)   r*   rC   rO   rF   rh   r_   )r   rG   rH   s      r   r^   zThreadPool.adjustPoolsize.  s     JJQ5 55Z'J)JJ'|| <<$(("JJdllTXX56<<$(("JJOODHHt||34 #r   c                    t        j                  d| j                          t        j                  d| j                          t        j                  d| j                          y)zw
        Dump some plain-text informational messages to the log about the state
        of this L{ThreadPool}.
        z	waiters: z	workers: ztotal: N)r   msgrS   rQ   r<   r   s    r   	dumpStatszThreadPool.dumpStatsM  sI    
 	)DLL>*+)DLL>*+'$,,()r   )r.   r/   N)rG   r"   rH   r"   r9   zOptional[str]r    )r!   z
list[None])r!   r   r   )r!   str)rm   r(   r!   r   )r!   r(   )rs   zCallable[_P, object]rt   _P.argsr?   	_P.kwargsr!   r   )
r{   z&Optional[Callable[[bool, _R], object]]rs   zCallable[_P, _R]rt   r   r?   r   r!   r   )NN)rG   Optional[int]rH   r   r!   r   )#r$   r%   r&   __doc__r)   r*   r]   rC   r9   r   r:   staticmethodr   r   r   currentThreadrE   rI   propertyrO   rQ   rS   r[   rY   ra   rc   r;   ri   rn   rp   ru   rr   r   r^   r   r   r   r   r-   r-   *   s     C
CFGDM 	

Ir1a02	
 	M E PT"E"E/2"E?L"EH 	= 	= @ @ 	@ 	@  , 	A
%D62?(?18?@I?	??!8?! ?! 	?!
 ?! 
?!B MQ5'5<I5	5>*r   r-   N)"r   
__future__r   	threadingr   r   typingr   r   r   r	   r
   r   r   r   twisted._threadsr   rE   twisted.pythonr   r   twisted.python.deprecater   twisted.python.failurer   twisted.python.versionsr   r   r   r   r(   object
WorkerStopr-   r   r   r   <module>r      sl   
 # , 9 9 1 1 * ' / * +t_T]X 
Y 
 X
j* j*r   