
    ^jk                        d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
 e
rddl	mZmZ  G d d	e          Z G d
 d          ZdS )a
  Experimental multithreaded Job system.

This module provides the `JobExecutor` class, which allows submitting
batches of highly parallizable work in the form of functions and arguments.
This is commonly known as "task-based multithreading" or a "multithreaded
job system".

..note:: This module is only really useful with the recent Python 3.13
         releases that are built with experimental free-threading support.
         With typical Python releases that contain a GIL, this is not of
         much practical use.
    )annotationsN)Queue)EventThread)TYPE_CHECKING)CallableAnyc                  4     e Zd ZdZd fd
ZddZddZ xZS )_Workerz$A worker thread to pop and run jobs.	workqueuer   	exiteventr   indexintreturnNonec                    t                                          d           || _        || _        || _        |                                  d S )NT)daemon)super__init___queue_exit_indexstart)selfr   r   r   	__class__s       S/home/agentuser/manim-venv/lib/python3.11/site-packages/pyglet/experimental/jobs.pyr   z_Worker.__init__   sD    %%%


    c                    | j         }| j        }|                                sF|                                \  }} ||  |                                 |                                DdS dS )zParallel thread of execution.N)r   r   is_setget	task_done)r   r   r   funcargss        r   runz_Worker.run#   st    
,,.. 	JD$D$KK ,,.. 	 	 	 	 	r   strc                &    | j          d| j         dS )Nz(id=))name	native_idr   s    r   __repr__z_Worker.__repr__,   s    )222222r   )r   r   r   r   r   r   r   r   r   r   r   r%   )__name__
__module____qualname____doc__r   r$   r+   __classcell__)r   s   @r   r   r      sk        ..        3 3 3 3 3 3 3 3r   r   c                  <    e Zd ZdZdddZddZddZddZddZdS )JobExecutoraG  A light-weight multithreaded job system.

    A JobExecutor loosely mimics the design of the Executor classes from the
    `concurrent.futures` module, but does not share any code with those classes.
    Instead, it is a more light-weight implementation intended for execution of
    highly parallizable functions (jobs). A key difference is that JobExecutor
    does not return `Futures`. Submitted jobs must be self-contained, or handle
    returning values by other mechanisms. The :py:meth:`~sync` method can be
    used to wait for all currently submitted jobs to complete.
    Nmax_workers
int | Noner   r   c                     |pt          j                    dz   _        t                       _        t                       _         fdt           j                  D              _        dS )zCreate an instance of a JobExecutor.

        Args:
            max_workers: The number of threads to use. If `None`, will
                         create half as many threads as reported CPU cores.
           c                F    g | ]}t          j        j        |          S  )r   r   
_exitevent).0ir   s     r   
<listcomp>z(JobExecutor.__init__.<locals>.<listcomp>F   s)    dddadoqAAdddr   N)	os	cpu_count_max_workersr   r;   r   r   range_threads)r   r5   s   ` r   r   zJobExecutor.__init__<   s^     (>2<>>Q+>''ggdddd5QUQbKcKcdddr   r"   r   r#   r	   c                z    	 | j                             ||f           dS # t          $ r t          d          w xY w)a  Submit a job to be executed on .

        A "job" consists of a function to be called, alone with any arguments
        that should be passed to it. Jobs are automatically executed by the next
        free worker thread. No values are returned when jobs are submitted,
        and the functions should also not return any values; return values are
        lost.

        Args:
            func: A function to execute.
            *args: Any arguments to pass to the function.
        z&cannot submit new tasks after shutdownN)r   putAttributeErrorRuntimeError)r   r"   r#   s      r   submitzJobExecutor.submitH   sT    	IKOOT4L))))) 	I 	I 	IGHHH	Is     :c                    | j         sdS | j                                         t          | j                  D ]}|                     d            | j                                         d| _        d| _         dS )a9  Shut down the JobExecutor, terminating all worker threads.

        All JobExecutor workers are Daemon Threads, so it is not strictly
        necessary to call shutdown() at program termination. However, if
        it is no longer needed, shutdown() can be called to free up the
        thread resources.
        Nc                     d S Nr:   r:   r   r   <lambda>z&JobExecutor.shutdown.<locals>.<lambda>f   s     r   )r   r;   setrB   rA   rH   rC   clear)r   _s     r   shutdownzJobExecutor.shutdownZ   s~     { 	Ft()) 	& 	&AKK%%%%r   c                8    | j                                          dS )a  Wait for all currently submitted jobs to complete.

        This method will wait until the internal queue is empty, AND all
        currently submitted jobs have completed execution. It can be used
        to fence between separate batches of jobs that should not be run
        at the same time. For example::

            for chunk in worklist:
                executor.submit(some_function, chunk)

            executor.sync()

            window.draw()

        N)r   joinr*   s    r   synczJobExecutor.synck   s      	r   r%   c                0    | j         j         d| j         dS )Nz	(workers=r'   )r   r.   rC   r*   s    r   r+   zJobExecutor.__repr__}   s     .)DDDMDDDDr   rK   )r5   r6   r   r   )r"   r   r#   r	   r   r   r,   r-   )	r.   r/   r0   r1   r   rH   rP   rS   r+   r:   r   r   r4   r4   0   s        	 	
e 
e 
e 
e 
eI I I I$   "   $E E E E E Er   r4   )r1   
__future__r   r?   queuer   	threadingr   r   typingr   r   r	   r   r4   r:   r   r   <module>rY      s     # " " " " " 				       # # # # # # # #             %$$$$$$$$3 3 3 3 3f 3 3 3,NE NE NE NE NE NE NE NE NE NEr   