
    e0                         d dl Z d dlZd dlZd dlZd dlZddlmZ ddlmZ  G d de	      Z
 G d de      Z G d	 d
e      Zy)    N   )ForkedProcess)ClosedErrorc                       e Zd ZdZy)CanceledErrorzJRaised when the progress dialog is canceled during a processing operation.N)__name__
__module____qualname____doc__     E/usr/lib/python3/dist-packages/pyqtgraph/multiprocess/parallelizer.pyr   r      s    Tr   r   c                   F    e Zd ZdZd
dZd Zd Zd Zd Ze	d        Z
d	 Zy)ParallelizeaL  
    Class for ultra-simple inline parallelization on multi-core CPUs
    
    Example::
    
        ## Here is the serial (single-process) task:
        
        tasks = [1, 2, 4, 8]
        results = []
        for task in tasks:
            result = processTask(task)
            results.append(result)
        print(results)
        
        
        ## Here is the parallelized version:
        
        tasks = [1, 2, 4, 8]
        results = []
        with Parallelize(tasks, workers=4, results=results) as tasker:
            for task in tasker:
                result = processTask(task)
                tasker.results.append(result)
        print(results)
        
        
    The only major caveat is that *result* in the example above must be picklable,
    since it is automatically sent via pipe back to the parent process.
    Nc                 l   d| _         |.d| _         t        |t              rd|i}ddlm}  |d
i || _        || j                         }t        t        d      sd}|| _	        |t        |      }t        |      | _        || _        |j                         | _        | j                   | j                  d	<   y)aH  
        ===============  ===================================================================
        **Arguments:**
        tasks            list of objects to be processed (Parallelize will determine how to 
                         distribute the tasks). If unspecified, then each worker will receive
                         a single task with a unique id number.
        workers          number of worker processes or None to use number of CPUs in the 
                         system
        progressDialog   optional dict of arguments for ProgressDialog
                         to update while tasks are processed
        randomReseed     If True, each forked process will reseed its random number generator
                         to ensure independent results. Works with the built-in random
                         and numpy.random.
        kwds             objects to be shared by proxy with child processes (they will 
                         appear as attributes of the tasker)
        ===============  ===================================================================
        FNT	labelText   )ProgressDialogforkr   _taskStartedr   )showProgress
isinstancestrwidgets.ProgressDialogr   progressDlgsuggestedWorkerCounthasattrosworkersrangelisttasksreseedcopykwdsr   )selfr"   r   blockprogressDialograndomReseedr%   r   s           r   __init__zParallelize.__init__.   s    * "% $D.#."-~!>?-??D?//1Gr6"G='NE%[
"IIK	$($5$5		.!r   c                 n    d | _         | j                  dk(  r| j                         S | j                         S )Nr   )procr   	runSerialrunParallelr&   s    r   	__enter__zParallelize.__enter__W   s1    	<<1>>####%%r   c                 B   | j                   6|d   d u}	 |rt        j                  |  t        j                  |rdnd       y | j
                  r	 | j                  j                  d d d        y y # t        j                  |rd       w d       w xY w# t        $ r Y y w xY wNr   r   )	r,   sys
excepthookr   _exitr   r   __exit__	Exception)r&   exc_infoexceptOccurreds      r   r6   zParallelize.__exit__^   s    99 %a[4N5!NNH- n!4   $$--dD$? ! n4!4 ! s   A/ B / B	BBc                 $   | j                   rH| j                  j                          | j                  j                  t	        | j
                               t        j                         g i| _        t        | d | j
                  | j                        S N)r   r   r0   
setMaximumlenr"   r   getpidprogressTaskerr%   r/   s    r   r-   zParallelize.runSerialq   sd    &&(''DJJ8b)dD$**dii88r   c                    g | _         | j                  }t        |      D cg c]  }g  }}d}t        t        | j                              D ]&  }|||z     j                  | j                  |          ( t        |      D ]o  }t        d | j                  | j                        }|j                  s$|| _
        t        | |||   |j                        c S | j                   j                  |       q t        | j                   D cg c]  }|j                  g f c}      | _        	 | j                   rH| j"                  j%                          | j"                  j'                  t        | j                               | j                   d d  }g | _        d}t        |      dkD  rd}g }	|D ]  }	 |j+                         }
|
dkD  r|dz  } |	D ]S  }|j/                  |       	 	 t1        j2                  |j                  d      \  }}| j(                  j                  |       U | j                   r;| j"                  j9                         r!|D ]  }|j;                           t=               |dkD  r|dz  }n
|dk(  r|dz  }t?        tA        |d      d      }tC        jD                  |       t        |      dkD  r| j                   r| j"                  jG                  d d d        | j                   D ]  }|jI                           	 t        | j(                        t        | j                         k  r6tK        d	t        | j                         t        | j(                        fz        | j(                  D ]  }|dk7  s	tK        d
       g S c c}w c c}w # t,        $ r6 |	j                  |       | j                   r| xj"                  dz  c_        Y &w xY w# t4        $ r}|j6                  dk(  rY d }~ d }~ww xY w# | j                   r| j"                  jG                  d d d        | j                   D ]  }|jI                           w xY w)Nr   )targetpreProxyr)   g{Gz?r      gffffff?g      ?gMb@?zGParallelizer started %d processes but only received exit codes from %d.zZError occurred in parallel-executed subprocess (console output may have more information).)&childsr   r    r=   r"   appendr   r%   r#   isParentr,   r@   forkedProxiesdictchildPidr?   r   r   r0   r<   	exitCodesprocessRequestsr   remover   waitpidOSErrorerrnowasCanceledkillr   maxmintimesleepr6   joinr7   )r&   r   ichunksr,   chactiveChildspollIntervalwaitingChildrenremnpidexitcodeexcodes                  r   r.   zParallelize.runParallely   s    ,,#Gn-"--s4::' 	4A1W9$$TZZ]3	4 w 	)A tyyt{{[D== 	dD&)T5G5GHH""4(	) $++FBr{{B/FG8	    **,  ++C

O<  ;;q>LDNLl#a'"#& 	2B2..0q5+q0O		2  &B ''+	&,.JJr{{A,FMC NN11(;!&  $$)9)9)E)E)G* "	"'/) #Q& C'L$) C'L"3|S#96B

<(U l#a'X     ))$d;kk 	t~~T[[!11eilmqmxmxiy{~  @D  @N  @N  |O  iP  P  Q  QNN 	~Dqy |}}	~ 	g . G. ' 2

2,, ,,1,	2  ' &!xx1} ( !&&.     ))$d;kk 	sn   	NN'BO9 ,NO9  >OBO9 ;OO9 OO9 	O6O1*O9 0O11O66O9 9AQc                     dt         j                  v r	 i } d }t        d      5 }|D ]e  }t        j                  d|      }||j                         d   }t        j                  d|      }|Gt        |j                         d         | |<   g 	 d d d        t        | j                               S t        j                         S # 1 sw Y   6xY w#  t        j                         cY S xY w)Nlinuxz/proc/cpuinfozphysical id\s+:\s+(\d+)r   zcpu cores\s+:\s+(\d+))r3   platformopenrematchgroupsintsumvaluesmultiprocessing	cpu_count)coresr`   fdlinems        r   r   z Parallelize.suggestedWorkerCount   s    cll"3/* <b " <HH%?F="#((*Q-CHH%=tD=),QXXZ]);E#J<< 5<<>**
 #,,..< <3&0022s)   C A	C-!C C C	C C(c                 .   | j                   rkt        | j                  |         dkD  r| xj                  dz  c_        |t	        j
                         k(  r$| j                  j                         r
t               | j                  |   j                  |       y r2   )	r   r=   r?   r   r   r>   rQ   r   rF   )r&   r`   rX   r%   s       r   r   zParallelize._taskStarted   ss     4==%&*  A% biik!##//1'/)c!!!$r   )NNTNT)r   r	   r
   r   r*   r0   r6   r-   r.   staticmethodr   r   r   r   r   r   r      s<    <'6R&&9Xv / /,	%r   r   c                   $    e Zd Zd Zd Zd Zd Zy)r@   c                 x    || _         || _        || _        |j                         D ]  \  }}t	        | ||        y r;   )r,   parr"   itemssetattr)r&   parallelizerprocessr"   r%   kvs          r   r*   zTasker.__init__   s<    	
JJL 	 DAqD!Q	 r   c              #      K   t        | j                        D ]6  \  }}|| _        | j                  t	        j
                         |d       | 8 | j                  | j                  j                          y y w)Noff)	_callSync)	enumerater"   indexr   r   r>   r,   close)r&   rX   tasks      r   __iter__zTasker.__iter__   sh      , 	GAtDJbiik1>J		
 99 IIOO !s   A7A9c                 R    | j                   | j                   j                          yy)z
        Process requests from parent.
        Usually it is not necessary to call this unless you would like to 
        receive messages (such as exit requests) during an iteration.
        N)r,   rL   r/   s    r   r|   zTasker.process
  s#     99 II%%' !r   c                 .    | j                   j                  S )z7
        Return the number of parallel workers
        )rx   r   r/   s    r   
numWorkerszTasker.numWorkers  s     xxr   N)r   r	   r
   r*   r   r|   r   r   r   r   r@   r@      s     	( r   r@   )rn   r   rh   r3   rU   	processesr   remoteproxyr   r7   r   objectr   r@   r   r   r   <module>r      sA     	 	 
  $ $	I 	e%& e%P  V   r   