B
    z‹dñ  ã               @   sf   d Z ddlmZmZmZmZ dgZddlZddlZddl	m
Z
 ddlmZ dd„ ZG d	d„ de
ƒZdS )
a×  
Python's multiprocessing.Pool class doesn't interact well with
``KeyboardInterrupt`` signals, as documented in places such as:

* `<http://stackoverflow.com/questions/1408356/>`_
* `<http://stackoverflow.com/questions/11312525/>`_
* `<http://noswap.com/blog/python-multiprocessing-keyboardinterrupt>`_

Various workarounds have been shared. Here, we adapt the one proposed in the
last link above, by John Reese, and shared as

* `<https://github.com/jreese/multiprocessing-keyboardinterrupt/>`_

Our version is a drop-in replacement for multiprocessing.Pool ... as long as
the map() method is the only one that needs to be interrupt-friendly.

Contributed by Peter K. G. Williams <peter@newton.cx>.

*Added in version 2.1.0*

é    )ÚdivisionÚprint_functionÚabsolute_importÚunicode_literalsÚInterruptiblePoolN)ÚPool)ÚTimeoutErrorc             G   s$   t   t jt j¡ | dk	r | |Ž  dS )zÚ
    We ignore SIGINT. It's up to our parent to kill us in the typical
    condition of this arising from ``^C`` on a terminal. If someone is
    manually killing us with that signal, well... nothing will happen.

    N)ÚsignalÚSIGINTÚSIG_IGN)Zactual_initializerÚrest© r   úg/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/ptemcee/interruptible_pool.pyÚ_initializer_wrapper$   s    r   c                   s0   e Zd ZdZdZd	‡ fdd„	Zd
dd„Z‡  ZS )r   aŽ  
    A modified version of :class:`multiprocessing.pool.Pool` that has better
    behavior with regard to ``KeyboardInterrupts`` in the :func:`map` method.

    :param processes: (optional)
        The number of worker processes to use; defaults to the number of CPUs.

    :param initializer: (optional)
        Either ``None``, or a callable that will be invoked by each worker
        process when it starts.

    :param initargs: (optional)
        Arguments for *initializer*; it will be called as
        ``initializer(*initargs)``.

    :param kwargs: (optional)
        Extra arguments. Python 2.7 supports a ``maxtasksperchild`` parameter.

    i  Nr   c                s(   t  t|¡}tt| ƒj|||f|Ž d S )N)Ú	functoolsÚpartialr   Úsuperr   Ú__init__)ÚselfZ	processesZinitializerZinitargsÚkwargsZnew_initializer)Ú	__class__r   r   r   F   s    zInterruptiblePool.__init__c             C   s^   |   |||¡}xJy| | j¡S  tk
r0   Y q tk
rT   |  ¡  |  ¡  ‚ Y qX qW dS )a  
        Equivalent of ``map()`` built-in, without swallowing
        ``KeyboardInterrupt``.

        :param func:
            The function to apply to the items.

        :param iterable:
            An iterable of items that will have `func` applied to them.

        N)Z	map_asyncÚgetÚwait_timeoutr   ÚKeyboardInterruptÚ	terminateÚjoin)r   ÚfuncÚiterableÚ	chunksizeÚrr   r   r   ÚmapL   s    zInterruptiblePool.map)NNr   )N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r    Ú__classcell__r   r   )r   r   r   0   s   )r$   Ú
__future__r   r   r   r   Ú__all__r	   r   Zmultiprocessing.poolr   Úmultiprocessingr   r   r   r   r   r   r   Ú<module>   s   