1 import multiprocessing as mp
2 from multiprocessing.connection import wait
14 class ForkException(Exception): pass
17 def fork_joy(send, stack, expr, dictionary):
19 stack, dictionary = joy(stack, expr, dictionary)
20 result, _ = get_n_items(1, stack)
21 except Exception as err:
22 send.send((True, repr(err)))
24 send.send((False, result))
28 def fork(stack, expr, dictionary):
30 Take two quoted programs from the stack and
36 q, p, stack = get_n_items(2, stack)
39 q_pipe_recv, q_pipe_send = mp.Pipe(False)
40 p_pipe_recv, p_pipe_send = mp.Pipe(False)
44 args=(p_pipe_send, stack, p, dictionary),
48 args=(q_pipe_send, stack, q, dictionary),
53 # Ensure "wait() will promptly report the readable end as being ready."
54 # See docs for multiprocessing.connection.wait().
58 readers = [q_pipe_recv, p_pipe_recv]
60 # We have one or two results or errors
63 order = read_me is q_pipe_recv
64 wait_me = readers[order]
65 wait_proc = (Q, P)[order]
66 stack = one_result(stack, order, read_me, wait_me, wait_proc)
67 else: # both results/errors
68 p_err, p_result = p_pipe_recv.recv()
69 q_err, q_result = q_pipe_recv.recv()
71 raise ForkException(p_result)
73 raise ForkException(q_result)
74 stack = (q_result, (p_result, stack))
76 return stack, expr, dictionary
79 def one_result(stack, order, read_me, wait_me, wait_proc):
80 err, result = read_me.recv()
85 raise ForkException(result)
87 err, second_result = wait_me.recv()
90 raise ForkException(second_result)
92 stack = (result, (second_result, stack))
94 stack = (second_result, (result, stack))
98 if __name__ == '__main__':
99 mp.set_start_method('fork')
101 dictionary = initialize()
102 default_defs(dictionary)
104 stack = repl(dictionary=dictionary)