a
    ”$a@  ã                   @   sä   d Z ddlZddlZzddlmZmZ W nR eyz   ddlmZ zddlmZ W n" eyt   G dd„ deƒZY n0 Y n0 ddlmZm	Z	m
Z
mZ d	ZG d
d„ deƒZG dd„ dejjƒZG dd„ dejjƒZG dd„ deƒZdS )z*
Runner.py: Task scheduling and execution
é    N)ÚQueueÚPriorityQueue)r   )r   c                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )r   c                 C   s   || _ g | _d S ©N)ÚmaxsizeÚqueue)Úselfr   © r   úh/home/jack/SDK/ZBT-AX3000-OpenWrt-21.02/build_dir/hostpkg/samba-4.14.12/third_party/waf/waflib/Runner.pyÚ_init   s    zPriorityQueue._initc                 C   s   t  | j|¡ d S r   )ÚheapqÚheappushr   )r   Úitemr   r   r	   Ú_put   s    zPriorityQueue._putc                 C   s   t  | j¡S r   )r   Úheappopr   ©r   r   r   r	   Ú_get   s    zPriorityQueue._getN)Ú__name__Ú
__module__Ú__qualname__r
   r   r   r   r   r   r	   r      s   r   )ÚUtilsÚTaskÚErrorsÚLogsé   c                   @   sT   e Z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„ ZdS )ÚPriorityTasksc                 C   s
   g | _ d S r   ©Úlstr   r   r   r	   Ú__init__"   s    zPriorityTasks.__init__c                 C   s
   t | jƒS r   )Úlenr   r   r   r   r	   Ú__len__$   s    zPriorityTasks.__len__c                 C   s
   t | jƒS r   )Úiterr   r   r   r   r	   Ú__iter__&   s    zPriorityTasks.__iter__c                 C   s   dd  dd„ | jD ƒ¡ S )NzPriorityTasks: [%s]z
  c                 s   s   | ]}t |ƒV  qd S r   )Ústr©Ú.0Úxr   r   r	   Ú	<genexpr>)   ó    z(PriorityTasks.__str__.<locals>.<genexpr>)Újoinr   r   r   r   r	   Ú__str__(   s    zPriorityTasks.__str__c                 C   s
   g | _ d S r   r   r   r   r   r	   Úclear*   s    zPriorityTasks.clearc                 C   s   t  | j|¡ d S r   ©r   r   r   ©r   Útaskr   r   r	   Úappend,   s    zPriorityTasks.appendc                 C   s   t  | j|¡ dS )zDeprecated, do not useNr+   r,   r   r   r	   Ú
appendleft.   s    zPriorityTasks.appendleftc                 C   s   t  | j¡S r   )r   r   r   r   r   r   r	   Úpop1   s    zPriorityTasks.popc                 C   sD   | j r|D ]}|  |¡ q
n$t|tƒr8|| _ t |¡ n|j | _ d S r   )r   r.   Ú
isinstanceÚlistr   Úheapify)r   r   r%   r   r   r	   Úextend3   s    
zPriorityTasks.extendN)r   r   r   r   r   r!   r)   r*   r.   r/   r0   r4   r   r   r   r	   r   !   s   r   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚConsumerz©
	Daemon thread object that executes a task. It shares a semaphore with
	the coordinator :py:class:`waflib.Runner.Spawner`. There is one
	instance per task to consume.
	c                 C   s0   t jj | ¡ || _|| _|  d¡ |  ¡  d S ©Né   )r   Ú	threadingÚThreadr   r-   ÚspawnerÚ	setDaemonÚstart)r   r:   r-   r   r   r	   r   D   s
    
zConsumer.__init__c              	   C   sz   zH| j jjs| j j | j¡ W | j j ¡  | j jj | j¡ d| _d| _ n,| j j ¡  | j jj | j¡ d| _d| _ 0 dS )z
		Processes a single task
		N)	r:   ÚmasterÚstopÚprocess_taskr-   ÚsemÚreleaseÚoutÚputr   r   r   r	   ÚrunL   s    
ýzConsumer.runN)r   r   r   Ú__doc__r   rD   r   r   r   r	   r5   >   s   r5   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚSpawnerzÉ
	Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and
	spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each
	:py:class:`waflib.Task.Task` instance.
	c                 C   s:   t jj | ¡ || _t j |j¡| _|  d¡ |  	¡  d S r6   )
r   r8   r9   r   r=   Ú	SemaphoreÚnumjobsr@   r;   r<   )r   r=   r   r   r	   r   _   s
    
zSpawner.__init__c                 C   s$   z|   ¡  W n ty   Y n0 dS )zb
		Spawns new consumers to execute tasks by delegating to :py:meth:`waflib.Runner.Spawner.loop`
		N)ÚloopÚ	Exceptionr   r   r   r	   rD   g   s    zSpawner.runc                 C   s>   | j }|j ¡ }| j ¡  |js.| |jj¡ t	| |ƒ qdS )zd
		Consumes task objects from the producer; ends when the producer has no more
		task to provide.
		N)
r=   ÚreadyÚgetr@   Úacquirer>   Úlog_displayÚ	generatorÚbldr5   )r   r=   r-   r   r   r	   rI   q   s    

zSpawner.loopN)r   r   r   rE   r   rD   rI   r   r   r   r	   rF   Y   s   
rF   c                   @   sš   e Zd ZdZd&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„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%S )'ÚParallelzE
	Schedule the tasks obtained from the build context for execution.
	é   c                 C   s†   || _ || _tƒ | _tƒ | _tƒ | _tdƒ| _t	dƒ| _
d| _d| _d| _g | _d| _d| _t t¡| _d| _| j dkr‚t| ƒ| _dS )ze
		The initialization requires a build context reference
		for computing the total number of jobs.
		r   FNr7   )rH   rP   r   ÚoutstandingÚ	postponedÚsetÚ
incompleter   rK   r   rB   ÚcountÚ	processedr>   ÚerrorÚbiterÚdirtyr   ÚdefaultdictÚrevdepsr:   rF   )r   rP   Újr   r   r	   r   ‚   s"    


zParallel.__init__c                 C   s   | j s
dS | j  ¡ S )zS
		Obtains the next Task instance to run

		:rtype: :py:class:`waflib.Task.Task`
		N)rS   r0   r   r   r   r	   Úget_next_taskÁ   s    zParallel.get_next_taskc                 C   s   | j  |¡ dS )zä
		Adds the task to the list :py:attr:`waflib.Runner.Parallel.postponed`.
		The order is scrambled so as to consume as many tasks in parallel as possible.

		:param tsk: task instance
		:type tsk: :py:class:`waflib.Task.Task`
		N)rT   r.   ©r   Útskr   r   r	   ÚpostponeË   s    zParallel.postponec           
      C   s´  | j | jt kr|  ¡  q | js°| j r<|  ¡  | jrÒq°n–| jrÒz| j| jk}W n tyd   Y nf0 |rÊg }| jD ]@}dd„ |j	D ƒ}| 
dt|ƒ|f ¡ |st| 
dt|ƒ ¡ qtt dd |¡ ¡‚| j| _| jrò| j | j¡ | j ¡  q| j s| jrn| jD ]@}|j	D ]}|js qq| j |¡ | j 
|¡  q®q| js°| jr\q°t d| j ¡‚qt| jƒ}|  |¡\}}	| j |¡ | j |	¡ | j ¡ | _q°qdS )	z¿
		Pulls a next group of tasks to execute in :py:attr:`waflib.Runner.Parallel.outstanding`.
		Ensures that all tasks in the current build group are complete before processing the next one.
		c                 S   s   g | ]}|j st|ƒ‘qS r   )ÚhasrunÚidr#   r   r   r	   Ú
<listcomp>ï   r'   z-Parallel.refill_task_list.<locals>.<listcomp>z%s	-> %rz>
  task %r dependencies are done, check its *runnable_status*?z/Deadlock detected: check the task build order%sÚ zBroken revdeps detected on %rN)rW   rH   ÚGAPÚget_outrS   rT   ZdeadlockrX   ÚAttributeErrorÚ	run_afterr.   Úreprrd   r   ÚWafErrorr(   r4   r*   rV   rc   Úremover>   rY   ÚnextrZ   Úprio_and_splitÚupdaterP   Útotal)
r   Zcondr   ra   Údepsr%   ÚkÚtasksrK   Úwaitingr   r   r	   Úrefill_task_listÕ   sT    






zParallel.refill_task_listc           
      C   sÜ   t |ddƒrØt|jƒ}tƒ }dd„ }|| j| jƒD ]h}|jD ]\}t|tjƒr€||vr˜| 	|¡ |j
|@ D ]}| j|  	|¡ qhq<||v r<| j|  	|¡ q<q2|  |j¡\}}	| j |¡ | j |	¡ |  jt|jƒ7  _dS )aE  
		If a task provides :py:attr:`waflib.Task.Task.more_tasks`, then the tasks contained
		in that list are added to the current build and will be processed before the next build group.

		The priorities for dependent tasks are not re-calculated globally

		:param tsk: task instance
		:type tsk: :py:attr:`waflib.Task.Task`
		Ú
more_tasksNc                 s   s$   | D ]
}|V  q|D ]
}|V  qd S r   r   )ÚaÚbr%   r   r   r	   Úiteri  s    z&Parallel.add_more_tasks.<locals>.iteri)ÚgetattrrU   rw   rS   rV   rj   r1   r   Ú	TaskGroupÚaddÚprevr]   ro   r4   rp   rq   r   )
r   ra   ZmoreÚgroups_donerz   r%   rs   r^   rK   ru   r   r   r	   Úadd_more_tasks  s"    



zParallel.add_more_tasksc                    sÖ   ‡ fdd„}|ˆ j v r|ˆ j | D ]R}t|tjƒrj|j |¡ |jsr|jD ]}|j |¡ ||ƒ qHg |_q ||ƒ q ˆ j |= t|dƒrÒ|j	}z| 
|¡ W n ty¬   Y n&0 |jrÒ| ¡ sÒ|j ¡ }ˆ  |¡ q®d S )Nc                    s<   | ˆ j v r8| jD ]}|js q8qˆ j  | ¡ ˆ j | ¡ d S r   )rV   rj   rc   rm   rS   r.   )r%   rs   r   r   r	   Útry_unfreeze5  s    

z,Parallel.mark_finished.<locals>.try_unfreezeÚ	semaphore)r]   r1   r   r|   r~   rm   rn   rj   Úhasattrr‚   rA   ÚKeyErrorru   Ú	is_lockedr0   Ú	_add_task)r   ra   r   r%   rs   r@   r   r   r	   Úmark_finished4  s*    





zParallel.mark_finishedc                 C   s<   | j  ¡ }| js|  |¡ |  |¡ |  jd8  _d| _|S )zè
		Waits for a Task that task consumers add to :py:attr:`waflib.Runner.Parallel.out` after execution.
		Adds more Tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`.

		:rtype: :py:attr:`waflib.Task.Task`
		r7   T)rB   rL   r>   r€   r‡   rW   r[   r`   r   r   r	   rh   _  s    


zParallel.get_outc                 C   s   | j  |¡ dS )z¥
		Enqueue a Task to :py:attr:`waflib.Runner.Parallel.ready` so that consumers can run them.

		:param tsk: task instance
		:type tsk: :py:attr:`waflib.Task.Task`
		N)rK   rC   r`   r   r   r	   Úadd_tasko  s    zParallel.add_taskc              	   C   s®   t |dƒr@|j}z| |¡ W n  ty>   |j |¡ Y d S 0 |  jd7  _|  jd7  _| jdkr | 	|j
j¡ z|  |¡ W | j |¡ qª| j |¡ 0 n
|  |¡ d S )Nr‚   r7   )rƒ   r‚   rM   Ú
IndexErrorru   r}   rW   rX   rH   rN   rO   rP   r?   rB   rC   rˆ   )r   ra   r@   r   r   r	   r†   y  s    

zParallel._add_taskc                 C   s"   |  ¡  |jtjkr|  |¡ dS )zG
		Processes a task and attempts to stop the build in case of errors
		N)Úprocessrc   r   ÚSUCCESSÚerror_handlerr`   r   r   r	   r?     s    zParallel.process_taskc                 C   s   t j|_|  |¡ dS )z'
		Mark a task as skipped/up-to-date
		N)r   ÚSKIPPEDrc   r‡   r`   r   r   r	   Úskip•  s    zParallel.skipc                 C   s   t j|_|  |¡ dS )zA
		Mark a task as failed because of unsatisfiable dependencies
		N)r   ÚCANCELEDrc   r‡   r`   r   r   r	   Úcancelœ  s    zParallel.cancelc                 C   s   | j jsd| _| j |¡ dS )zã
		Called when a task cannot be executed. The flag :py:attr:`waflib.Runner.Parallel.stop` is set,
		unless the build is executed with::

			$ waf build -k

		:param tsk: task instance
		:type tsk: :py:attr:`waflib.Task.Task`
		TN)rP   Úkeepr>   rY   r.   r`   r   r   r	   rŒ   £  s    
zParallel.error_handlerc                 C   sº   z
|  ¡ W S  ty´   |  jd7  _t ¡ |_| js˜| jjr˜|  	|¡ | jjdkrxt
jdksd| jsp| j |¡ d| _nt
jdkrŽ| j |¡ tj Y S tj|_|  |¡ tj Y S 0 dS )z©
		Obtains the task status to decide whether to run it immediately or not.

		:return: the exit status, for example :py:attr:`waflib.Task.ASK_LATER`
		:rtype: integer
		r7   TN)Úrunnable_statusrJ   rX   Ú	tracebackÚ
format_excÚerr_msgr>   rP   r‘   rŽ   r   ÚverboserY   r.   r   Ú	EXCEPTIONrc   rŒ   r`   r   r   r	   Útask_status±  s"    





zParallel.task_statusc                 C   sD  | j  ¡ | _| jsî|  ¡  |  ¡ }|s2| jrîqnqî|jrH|  jd7  _q| jrPqî|  |¡}|t	j
krp|  |¡ q|t	jkr†|  |¡ q|t	jkr´|  jd7  _|  |¡ |  |¡ q|t	jkrtjdkrÔ| j |¡ |  jd7  _|  |¡ q| jr| jr|  ¡  qî| j d¡ | js@| jr(J ‚| jr4J ‚| jr@J ‚dS )aÃ  
		Obtains Task instances from the BuildContext instance and adds the ones that need to be executed to
		:py:class:`waflib.Runner.Parallel.ready` so that the :py:class:`waflib.Runner.Spawner` consumer thread
		has them executed. Obtains the executed Tasks back from :py:class:`waflib.Runner.Parallel.out`
		and marks the build as failed by setting the ``stop`` flag.
		If only one job is used, then executes the tasks one by one, without consumers.
		r7   N)rP   rq   r>   rv   r_   rW   rc   rX   r˜   r   ÚRUN_MEr†   Ú	ASK_LATERrb   ÚSKIP_MErŽ   r€   Ú	CANCEL_MEr   r–   rY   r.   r   rh   rK   rC   rT   rV   )r   ra   Ústr   r   r	   r<   Î  sD    







zParallel.startc              	      s  |D ]
}d|_ q| j‰ tƒ }|D ]X}|jD ]L}t|tjƒrh||vrv| |¡ |jD ]}ˆ |  |¡ qRq*ˆ |  |¡ q*q ‡ ‡fdd„‰|D ]>}|j dkrœqŒzˆ|ƒ W qŒ t	j
yÈ   |  |ˆ ¡ Y qŒ0 qŒg }g }|D ].}|jD ]}|jsâ| |¡  qØqâ| |¡ qØ||fS )a<  
		Label input tasks with priority values, and return a pair containing
		the tasks that are ready to run and the tasks that are necessarily
		waiting for other tasks to complete.

		The priority system is really meant as an optional layer for optimization:
		dependency cycles are found quickly, and builds should be more efficient.
		A high priority number means that a task is processed first.

		This method can be overridden to disable the priority system::

			def prio_and_split(self, tasks):
				return tasks, []

		:return: A pair of task lists
		:rtype: tuple
		r   c                    s–   t | tjƒr$t‡fdd„| jD ƒƒS | jdkr|d| _| ˆ v rlˆ |  }| jt|ƒ t‡fdd„|D ƒƒ | _n| j| _d| _n| jdkrt	 
d¡‚| jS )Nc                 3   s   | ]}ˆ |ƒV  qd S r   r   ©r$   rs   ©Úvisitr   r	   r&   1  r'   z9Parallel.prio_and_split.<locals>.visit.<locals>.<genexpr>r   r7   c                 3   s   | ]}ˆ |ƒV  qd S r   r   rž   rŸ   r   r	   r&   8  r'   rR   zDependency cycle found!)r1   r   r|   Úsumrn   ÚvisitedÚtree_weightr   Ú
prio_orderr   rl   )ÚnZrev©Úreverser    r   r	   r    /  s    
(

z&Parallel.prio_and_split.<locals>.visit)r¢   r]   rU   rj   r1   r   r|   r}   r~   r   rl   Údebug_cyclesrc   r.   )r   rt   r%   r   rs   r^   rK   ru   r   r¦   r	   ro   
  s:    





zParallel.prio_and_splitc                    s>   i ‰|D ]}dˆ|< q‡ ‡‡fdd„‰|D ]}ˆ|g ƒ q*d S )Nr   c                    s²   t | tjƒr&| jD ]}ˆ||ƒ qd S ˆ|  dkrfdˆ| < ˆ  | g ¡D ]}ˆ|| g| ƒ qFdˆ| < nHˆ|  dkr®g }|D ]}| t|ƒ¡ || u rz qšqzt dd 	|¡ ¡‚d S )Nr   r7   rR   z4Task dependency cycle in "run_after" constraints: %srf   )
r1   r   r|   rn   rL   r.   rk   r   rl   r(   )r¥   Úaccrs   r   ra   ©r§   Útmpr    r   r	   r    Z  s     

z$Parallel.debug_cycles.<locals>.visitr   )r   rt   r§   r%   r   rª   r	   r¨   U  s    
zParallel.debug_cyclesN)rR   )r   r   r   rE   r   r_   rb   rv   r€   r‡   rh   rˆ   r†   r?   rŽ   r   rŒ   r˜   r<   ro   r¨   r   r   r   r	   rQ   ~   s$   
?

;$+
<KrQ   )rE   r   r“   r   r   r   ÚImportErrorÚwaflibr   r   r   r   rg   Úobjectr   r8   r9   r5   rF   rQ   r   r   r   r	   Ú<module>   s   	%