B
    È S]ç  ã               @   s²   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 ddlm	Z	 dgZ
ejdkrxe
dg7 Z
G d	d„ deƒZne
d
g7 Z
G dd
„ d
eƒZG dd„ deƒZeƒ ZejZdS )é    Né   )Úprocess)Ú	reduction)ÚutilÚstopZwin32Ú	DupSocketc               @   s    e Zd ZdZdd„ Zdd„ ZdS )r   zPicklable wrapper for a socket.c                s(   |  ¡ ‰ ‡ fdd„}t |ˆ j¡| _d S )Nc                s   ˆ   |¡}|  |¡ d S )N)ÚshareZ
send_bytes)ÚconnÚpidr   )Únew_sock© ú0lib/python3.7/multiprocessing/resource_sharer.pyÚsend   s    
z DupSocket.__init__.<locals>.send)ÚdupÚ_resource_sharerÚregisterÚcloseÚ_id)ÚselfZsockr   r   )r   r   Ú__init__   s    zDupSocket.__init__c          	   C   s*   t  | j¡}| ¡ }t |¡S Q R X dS )z1Get the socket.  This should only be called once.N)r   Úget_connectionr   Z
recv_bytesÚsocketZ	fromshare)r   r	   r   r   r   r   Údetach$   s    zDupSocket.detachN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r      s   ÚDupFdc               @   s    e Zd ZdZdd„ Zdd„ ZdS )r   z-Wrapper for fd which can be used at any time.c                s4   t  |¡‰ ‡ fdd„}‡ fdd„}t ||¡| _d S )Nc                s   t  | ˆ |¡ d S )N)r   Zsend_handle)r	   r
   )Únew_fdr   r   r   1   s    zDupFd.__init__.<locals>.sendc                  s   t  ˆ ¡ d S )N)Úosr   r   )r   r   r   r   3   s    zDupFd.__init__.<locals>.close)r   r   r   r   r   )r   Úfdr   r   r   )r   r   r   /   s    
zDupFd.__init__c          	   C   s"   t  | j¡}t |¡S Q R X dS )z-Get the fd.  This should only be called once.N)r   r   r   r   Zrecv_handle)r   r	   r   r   r   r   7   s    zDupFd.detachN)r   r   r   r   r   r   r   r   r   r   r   -   s   c               @   sN   e Zd ZdZdd„ Zdd„ Zedd„ ƒZdd	d
„Zdd„ Z	dd„ Z
dd„ ZdS )Ú_ResourceSharerz.Manager for resources using background thread.c             C   s@   d| _ i | _g | _t ¡ | _d | _d | _d | _t	 
| tj¡ d S )Nr   )Ú_keyÚ_cacheÚ
_old_locksÚ	threadingÚLockÚ_lockÚ	_listenerÚ_addressÚ_threadr   Zregister_after_forkr!   Ú
_afterfork)r   r   r   r   r   ?   s    
z_ResourceSharer.__init__c          	   C   sN   | j > | jdkr|  ¡  |  jd7  _||f| j| j< | j| jfS Q R X dS )z+Register resource, returning an identifier.Nr   )r'   r)   Ú_startr"   r#   )r   r   r   r   r   r   r   I   s    
z_ResourceSharer.registerc             C   s<   ddl m} | \}}||t ¡ jd}| |t ¡ f¡ |S )z<Return connection from which to receive identified resource.r   )ÚClient)Úauthkey)Ú
connectionr-   r   Úcurrent_processr.   r   r   Úgetpid)Zidentr-   ÚaddressÚkeyÚcr   r   r   r   R   s
    z_ResourceSharer.get_connectionNc          	   C   sº   ddl m} | jž | jdk	r¬|| jt ¡ jd}| d¡ | ¡  | j	 
|¡ | j	 ¡ rdt d¡ | j ¡  d| _	d| _d| _x | j ¡ D ]\}\}}|ƒ  qŒW | j ¡  W dQ R X dS )z:Stop the background thread and clear registered resources.r   )r-   N)r.   z._ResourceSharer thread did not stop when asked)r/   r-   r'   r)   r   r0   r.   r   r   r*   ÚjoinZis_aliver   Zsub_warningr(   r#   ÚitemsÚclear)r   Ztimeoutr-   r4   r3   r   r   r   r   r   r   [   s"    





z_ResourceSharer.stopc             C   sn   x | j  ¡ D ]\}\}}|ƒ  qW | j  ¡  | j | j¡ t ¡ | _| jd k	rX| j 	¡  d | _d | _
d | _d S )N)r#   r6   r7   r$   Úappendr'   r%   r&   r(   r   r)   r*   )r   r3   r   r   r   r   r   r+   p   s    




z_ResourceSharer._afterforkc             C   sj   ddl m} | jd kstdƒ‚t d¡ |t ¡ jd| _| jj	| _
tj| jd}d|_| ¡  || _d S )Nr   )ÚListenerzAlready have Listenerz0starting listener and thread for sending handles)r.   )ÚtargetT)r/   r9   r(   ÚAssertionErrorr   Údebugr   r0   r.   r2   r)   r%   ZThreadÚ_serveZdaemonÚstartr*   )r   r9   Útr   r   r   r,   ~   s    

z_ResourceSharer._startc          	   C   sª   t tdƒr t tjtdtjƒ¡ x„y\| j ¡ H}| ¡ }|d krBP |\}}| j	 
|¡\}}z|||ƒ W d |ƒ  X W d Q R X W q"   t ¡ sœtjt ¡ Ž  Y q"X q"W d S )NÚpthread_sigmaskr   )ÚhasattrÚsignalr@   Ú	SIG_BLOCKÚrangeÚNSIGr(   ZacceptZrecvr#   Úpopr   Z
is_exitingÚsysÚ
excepthookÚexc_info)r   r	   Úmsgr3   Zdestination_pidr   r   r   r   r   r=   ‰   s     
z_ResourceSharer._serve)N)r   r   r   r   r   r   Ústaticmethodr   r   r+   r,   r=   r   r   r   r   r!   =   s   
		
r!   )r   rB   r   rG   r%   Ú r   Úcontextr   r   Ú__all__ÚplatformÚobjectr   r   r!   r   r   r   r   r   r   Ú<module>   s    


`