a
    K)XT"                     @   s  d Z dZdZdZddlZddlZddlmZ ejd dkrTddl	m
Z
 dd	l	mZ nNejd d
krejd dk rddlm
Z
 dd	lmZ nddl
m
Z
 dd	l
mZ ddlZejZe Ze ZdadadZdddZdd ZdddZG dd deZG dd dZdddZdS )z
* Experimental *

Like the map function, but can use a pool of threads.

Really easy to use threads.  eg.  tmap(f, alist)

If you know how to use the map function, you can use threads.
zRene Dudfieldz0.3.0zPython license    N)geterror   )Queue)Empty         @   c                 C   s   | r
| a nt a tt adS )z Does a little test to see if threading is worth it.
          Sets up a global worker queue if it's worth it.

        Calling init() is not required, but is generally better to do.
    N)_use_workersbenchmark_workersWorkerQueue_wq)Znumber_of_workers r   m/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python3.9/site-packages/pygame_sdl2/threads/__init__.pyinit4   s    r   c                   C   s   t   da dadS )z cleans up everything.
    NF)r   stopr
   r   r   r   r   quitG   s    r   c                    s  ddl  ddl ddl}| s* fdd}n| }|sZg }tdD ]}| ddd q>n|}| d }d}d	}tdtD ]}	t|	}
| }td
D ]"}tdt	
   t|||
d}q| }|
  || }td|	|f  ||k r|}|	}|}|	| dkr| qq||S )aX   does a little test to see if workers are at all faster.
        Returns the number of workers which works best.
        Takes a little bit of time to run, so you should only really call
          it once.
        You can pass in benchmark data, and functions if you want.
        a_bench_func - f(data)
        the_data - data to work on.
    r   Nc                    s    j | dS )N)i   i@  )Z	transformZscalexpygamer   r   doiti   s    zbenchmark_workers.<locals>.doit
   )   r       i    zactive count:%s)worker_queuez#total time num_workers:%s: time:%s:r   )r   Zpygame.transformtimerangeappendZSurfaceMAX_WORKERS_TO_TESTr   print	threadingactiveCounttmapr   )Za_bench_funcZthe_datar   r   Zthedatar   bestZbest_numberZ	last_bestnum_workerswqt1Zxxresultst2Z
total_timer   r   r   r   P   s>    r   c                   @   s>   e Zd ZdddZdd Zdd Zdd	 Zd
d Zdd ZdS )r   r   c                 C   s   t  | _g | _| | d S N)r   queuepool_setup_workers)selfr'   r   r   r   __init__   s    zWorkerQueue.__init__c                 C   sJ   g | _ t|D ]}| j t| jd q| j D ]}|d |  q.dS )zd Sets up the worker threads
              NOTE: undefined behaviour if you call this again.
        )targetTN)r.   r   r    Thread
threadloop	setDaemonstart)r0   r'   _Za_threadr   r   r   r/      s    

zWorkerQueue._setup_workersc                 O   s   | j |||f dS )z7 puts a function on a queue for running later.
        N)r-   put)r0   fargsZkwArgsr   r   r   do   s    zWorkerQueue.doc                 C   s$   | j t | jD ]}|  qdS )zK Stops the WorkerQueue, waits for all of the threads to finish up.
        N)r-   r8   STOPr.   join)r0   threadr   r   r   r      s    
zWorkerQueue.stopc                 C   sh   | j  }|tu r,| j t | j   qdq z(|d |d i |d  W | j   q | j   0 q dS )z4 Loops until all of the tasks are finished.
        r   r   r   N)r-   getr<   r8   	task_done)r0   r:   r   r   r   r4      s    

zWorkerQueue.threadloopc                 C   s   | j   dS )z- waits until all tasks are complete.
        N)r-   r=   )r0   r   r   r   wait   s    zWorkerQueue.waitN)r   )	__name__
__module____qualname__r1   r/   r;   r   r4   rA   r   r   r   r   r      s   
r   c                   @   s"   e Zd ZdZdddZdd ZdS )
FuncResultzy Used for wrapping up a function call so that the results are stored
         inside the instances result attribute.
    Nc                 C   s   || _ d| _|| _|| _dS )z f - is the function we that we call 
            callback(result) - this is called when the function(f) returns
            errback(exception) - this is called when the function(f) raises
                                   an exception.
        N)r9   	exceptioncallbackerrback)r0   r9   rG   rH   r   r   r   r1      s    zFuncResult.__init__c                 O   sZ   z(| j |i || _| jr&| | j W n, tyT   t | _| jrP| | j Y n0 d S r,   )r9   resultrG   	Exceptionr   rF   rH   )r0   r:   kwargsr   r   r   __call__   s    zFuncResult.__call__)NN)rB   rC   rD   __doc__r1   rL   r   r   r   r   rE      s   
rE   r   Tc                 C   s  |r
|}n$t rt }n|dkr&t| |S t|}t|jdkrFt| |S g }|D ]"}|t|  ||d | qN|r|  |j	
 rtd|st s|  |j	
 r|j	 }	|	turtd|rttdd |}
|
r|
d jtdd |S ||gS dS )a'   like map, but uses a thread pool to execute.
        num_workers - the number of worker threads that will be used.  If pool
                        is passed in, then the num_workers arg is ignored.
        worker_queue - you can optionally pass in an existing WorkerQueue.
        wait - True means that the results are returned when everything is finished.
               False means that we return the [worker_queue, results] right away instead. 
               results, is returned as a list of FuncResult instances.
        stop_on_error - 
    r   r   zbuggy threadmapc                 S   s   | j S r,   )rF   r   r   r   r   <lambda>0      ztmap.<locals>.<lambda>c                 S   s   | j S r,   )rI   r   r   r   r   rN   4  rO   N)r   mapr   lenr.   r    rE   r;   rA   r-   qsizerJ   r   r?   r<   listfilterrF   )r9   Zseq_argsr'   r   rA   Zstop_on_errorr(   r*   saZumZ
error_onesr   r   r   r%      s:    





r%   )r   )NN)r   NTT)rM   
__author____version____license__	tracebacksysZpygame.compatr   version_infor-   r   r   Z	Py25Queuer#   r3   objectr<   ZFINISHr   r
   r!   r   r   r   r   rE   r%   r   r   r   r   <module>   s4   

	
H: