o
    ¯bí  ã                   @   s\   d Z ddlmZ ddlmZ ddlmZ ddlmZ G dd„ dƒZ	eeƒG d	d
„ d
ƒƒZ
dS )zZ
Implementation of a L{Team} of workers; a thread-pool that can allocate work to
workers.
é    )Údeque)Úimplementeré   )ÚIWorker)ÚQuitc                   @   s   e Zd ZdZdd„ ZdS )Ú
StatisticsaÓ  
    Statistics about a L{Team}'s current activity.

    @ivar idleWorkerCount: The number of idle workers.
    @type idleWorkerCount: L{int}

    @ivar busyWorkerCount: The number of busy workers.
    @type busyWorkerCount: L{int}

    @ivar backloggedWorkCount: The number of work items passed to L{Team.do}
        which have not yet been sent to a worker to be performed because not
        enough workers are available.
    @type backloggedWorkCount: L{int}
    c                 C   s   || _ || _|| _d S ©N)ÚidleWorkerCountÚbusyWorkerCountÚbackloggedWorkCount)Úselfr	   r
   r   © r   ú8/usr/lib/python3/dist-packages/twisted/_threads/_team.pyÚ__init__#   s   
zStatistics.__init__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r      s    r   c                   @   s\   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	d
„Zddd„Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚTeamax  
    A composite L{IWorker} implementation.

    @ivar _quit: A L{Quit} flag indicating whether this L{Team} has been quit
        yet.  This may be set by an arbitrary thread since L{Team.quit} may be
        called from anywhere.

    @ivar _coordinator: the L{IExclusiveWorker} coordinating access to this
        L{Team}'s internal resources.

    @ivar _createWorker: a callable that will create new workers.

    @ivar _logException: a 0-argument callable called in an exception context
        when there is an unhandled error from a task passed to L{Team.do}

    @ivar _idle: a L{set} of idle workers.

    @ivar _busyCount: the number of workers currently busy.

    @ivar _pending: a C{deque} of tasks - that is, 0-argument callables passed
        to L{Team.do} - that are outstanding.

    @ivar _shouldQuitCoordinator: A flag indicating that the coordinator should
        be quit at the next available opportunity.  Unlike L{Team._quit}, this
        flag is only set by the coordinator.

    @ivar _toShrink: the number of workers to shrink this L{Team} by at the
        next available opportunity; set in the coordinator.
    c                 C   s@   t ƒ | _|| _|| _|| _tƒ | _d| _tƒ | _	d| _
d| _dS )a   
        @param coordinator: an L{IExclusiveWorker} which will coordinate access
            to resources on this L{Team}; that is to say, an
            L{IExclusiveWorker} whose C{do} method ensures that its given work
            will be executed in a mutually exclusive context, not in parallel
            with other work enqueued by C{do} (although possibly in parallel
            with the caller).

        @param createWorker: A 0-argument callable that will create an
            L{IWorker} to perform work.

        @param logException: A 0-argument callable called in an exception
            context when the work passed to C{do} raises an exception.
        r   FN)r   Ú_quitÚ_coordinatorÚ_createWorkerÚ_logExceptionÚsetÚ_idleÚ
_busyCountr   Ú_pendingÚ_shouldQuitCoordinatorÚ	_toShrink)r   ÚcoordinatorÚcreateWorkerÚlogExceptionr   r   r   r   I   s   
zTeam.__init__c                 C   s   t t| jƒ| jt| jƒƒS )z›
        Gather information on the current status of this L{Team}.

        @return: a L{Statistics} describing the current state of this L{Team}.
        )r   Úlenr   r   r   ©r   r   r   r   Ú
statisticsd   s   zTeam.statisticsc                    s$   ˆj  ¡  ˆjj‡ ‡fdd„ƒ}dS )z—
        Increase the the number of idle workers by C{n}.

        @param n: The number of new idle workers to create.
        @type n: L{int}
        c                     s2   t ˆ ƒD ]} ˆ ¡ }|d u r d S ˆ |¡ qd S r   )Úranger   Ú_recycleWorker)ÚxÚworker©Únr   r   r   ÚcreateOneWorkeru   s   üz"Team.grow.<locals>.createOneWorkerN©r   Úcheckr   Údo)r   r*   r+   r   r)   r   Úgrowl   s   
z	Team.growNc                    s$   ˆj  ¡  ˆj ‡ ‡fdd„¡ dS )zß
        Decrease the number of idle workers by C{n}.

        @param n: The number of idle workers to shut down, or L{None} (or
            unspecified) to shut down all workers.
        @type n: L{int} or L{None}
        c                      s
   ˆ  ˆ ¡S r   )Ú_quitIdlersr   r)   r   r   Ú<lambda>†   ó   
 zTeam.shrink.<locals>.<lambda>Nr,   )r   r*   r   r)   r   Úshrink}   s   
zTeam.shrinkc                 C   sp   |du rt | jƒ| j }t|ƒD ]}| jr| j ¡  ¡  q|  jd7  _q| jr4| jdkr6| j ¡  dS dS dS )z|
        The implmentation of C{shrink}, performed by the coordinator worker.

        @param n: see L{Team.shrink}
        Nr   r   )	r"   r   r   r%   ÚpopÚquitr   r   r   )r   r*   r'   r   r   r   r0   ˆ   s   ÿzTeam._quitIdlersc                    s$   ˆ j  ¡  ˆ j ‡ ‡fdd„¡ dS )zu
        Perform some work in a worker created by C{createWorker}.

        @param task: the callable to run
        c                      s
   ˆ   ˆ¡S r   )Ú_coordinateThisTaskr   ©r   Útaskr   r   r1   Ÿ   r2   zTeam.do.<locals>.<lambda>Nr,   r7   r   r7   r   r.   ˜   s   
zTeam.doc                    sX   ˆ j rˆ j  ¡ nˆ  ¡ ‰ˆdu rˆ j ˆ¡ dS ˆ  jd7  _ˆj‡ ‡‡fdd„ƒ}dS )zø
        Select a worker to dispatch to, either an idle one or a new one, and
        perform it.

        This method should run on the coordinator worker.

        @param task: the task to dispatch
        @type task: 0-argument callable
        Nr   c                     s@   zˆƒ  W n t y   ˆ  ¡  Y nw ˆ jj‡ ‡fdd„ƒ} d S )Nc                      s   ˆ  j d8  _ ˆ  ˆ¡ d S )Nr   )r   r&   r   ©r   r(   r   r   ÚidleAndPendingº   s   z@Team._coordinateThisTask.<locals>.doWork.<locals>.idleAndPending)ÚBaseExceptionr   r   r.   )r:   ©r   r8   r(   r   r   ÚdoWork³   s   
ÿz(Team._coordinateThisTask.<locals>.doWork)r   r4   r   r   Úappendr   r.   )r   r8   r=   r   r<   r   r6   ¡   s   
zTeam._coordinateThisTaskc                 C   sl   | j  |¡ | jr|  | j ¡ ¡ dS | jr|  ¡  dS | jdkr4|  jd8  _| j  |¡ | 	¡  dS dS )zÐ
        Called only from coordinator.

        Recycle the given worker into the idle pool.

        @param worker: a worker created by C{createWorker} and now idle.
        @type worker: L{IWorker}
        r   r   N)
r   Úaddr   r6   Úpopleftr   r0   r   Úremover5   r9   r   r   r   r&   ¿   s   	
ýzTeam._recycleWorkerc                    s"   ˆ j  ¡  ˆ jj‡ fdd„ƒ}dS )zA
        Stop doing work and shut down all idle workers.
        c                      s   dˆ _ ˆ  ¡  d S )NT)r   r0   r   r#   r   r   ÚstartFinishingÛ   s   z!Team.quit.<locals>.startFinishingN)r   r   r   r.   )r   rB   r   r#   r   r5   Ô   s   
z	Team.quitr   )r   r   r   r   r   r$   r/   r3   r0   r.   r6   r&   r5   r   r   r   r   r   )   s    

	r   N)r   Úcollectionsr   Úzope.interfacer   Ú r   Ú_conveniencer   r   r   r   r   r   r   Ú<module>   s   