import multiprocessing
import functools


def in_separate_process(func):
    """Decorator that runs a function in a separate process, to force garbage collection
    collection upon termination of that process, limiting long-term memory usage.
    
    Parameters
    ----------
    func : function
        Function to run in a separate process. Per multiprocessing spec,
        must be declared in global scope.
    
    Returns
    -------
    function
        wrapped function
    
    See Also
    --------
    multiprocessing
        Python multiprocessing module, for writing parallel programs
    """

    @functools.wraps(func)
    def new_func(*args, **kwargs):
        recv_pipe, send_pipe = multiprocessing.Pipe(False)

        def temp_func(conn, args, kwargs):
            result = func(*args, **kwargs)
            conn.send(result)
            conn.close()

        proc = multiprocessing.Process(target=temp_func, args=(send_pipe, args, kwargs))
        proc.start()
        proc.join()
        result = recv_pipe.recv()
        recv_pipe.close()

        return result

    return new_func