""" module pyabc_split Executes python functions and their arguements as separate processes and returns their return values through pickling. This modules offers a single function: Function: split_all(funcs) The function returns a generator objects that allowes iteration over the results, Arguments: funcs: a list of tuples (f, args) where f is a python function and args is a collection of arguments for f. Caveats: 1. Global variables in the parent process are not affected by the child processes. 2. The functions can only return simple types, see the pickle module for details Usage: Assume you would like to run the function f_1(1), f_2(1,2), f_3(1,2,3) in different processes. def f_1(i): return i+1 def f_2(i,j): return i*10+j+1 def f_3(i,j,k): return i*100+j*10+k+1 Construct a tuple of the function and arguments for each function t_1 = (f_1, [1]) t_2 = (f_2, [1,2]) t_3 = (f_3, [1,2,3]) Create a list containing these tuples: funcs = [t_1, t_2, t_3] Use the function split_all() to run these functions in separate processes: for res in split_all(funcs): print res The output will be: 2 13 124 (The order may be different, except that in this case the processes are so fast that they terminate before the next one is created) Alternatively, you may quite in the middle, say after the first process returns: for res in split_all(funcs): print res break This will kill all processes not yet finished. To run ABC operations, that required saving the child process state and restoring it at the parent, use abc_split_all(). import pyabc def abc_f(truth): import os print "pid=%d, abc_f(%s)"%(os.getpid(), truth) pyabc.run_command('read_truth %s'%truth) pyabc.run_command('strash') funcs = [ defer(abc_f)("1000"), defer(abc_f)("0001") ] for _ in abc_split_all(funcs): pyabc.run_command('write_verilog /dev/stdout') Author: Baruch Sterin """ import os import select import fcntl import errno import sys import cPickle as pickle import signal import cStringIO import traceback from contextlib import contextmanager import pyabc def _retry_select(rlist): while True: try: rrdy,_,_ = select.select(rlist,[],[]) if rrdy: return rrdy except select.error as e: if e[0] == errno.EINTR: continue raise class _splitter(object): def __init__(self): self.pids = [] self.fds = {} self.buffers = {} self.results = {} def is_done(self): return len(self.fds) == 0 def _kill(self, pids): # close pipes and kill child processes for pid in pids: if pid == -1: continue i, fd = self.fds[pid] del self.buffers[fd] del self.fds[pid] self.pids[i] = -1 self.results[pid] = None os.close(fd) try: os.kill( pid, signal.SIGINT) except Exception as e: print >>sys.stderr, 'exception while trying to kill pid=%d: '%pid, e raise # wait for termination and update result for pid in pids: os.waitpid( pid, 0 ) def kill(self, ids): self._kill( [ self.pids[i] for i in ids ] ) def cleanup(self): self._kill( self.fds.keys() ) def child( self, fdw, f): # call function try: res = f() except: traceback.print_exc() raise # write return value into pipe with os.fdopen( fdw, "w" ) as fout: pickle.dump(res, fout) return 0 def _fork_one(self, f): # create a pipe to communicate with the child process pr,pw = os.pipe() # set pr to be non-blocking fcntl.fcntl(pr, fcntl.F_SETFL, os.O_NONBLOCK) parentpid = os.getpid() rc = 1 try: # create child process pid = os.fork() if pid == 0: # child process: os.close(pr) pyabc.close_on_fork(pw) rc = self.child( pw, f) os._exit(rc) else: # parent process: os.close(pw) return (pid, pr) finally
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

from __future__ import absolute_import, division, print_function

INCLUDES = """
#include <openssl/objects.h>
"""

TYPES = """
"""

FUNCTIONS = """
ASN1_OBJECT *OBJ_nid2obj(int);
const char *OBJ_nid2ln(int);
const char *OBJ_nid2sn(int);
int OBJ_obj2nid(const ASN1_OBJECT *);
int OBJ_ln2nid(const char *);
int OBJ_sn2nid(const char *);
int OBJ_txt2nid(const char *);
ASN1_OBJECT *OBJ_txt2obj(const char *, int);
int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int);
int OBJ_cmp(const ASN1_OBJECT *, const ASN1_OBJECT *);
ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *);
int OBJ_create(const char *, const char *, const char *);
"""

MACROS = """
/* OBJ_cleanup became a macro in 1.1.0 */
void OBJ_cleanup(void);
"""

CUSTOMIZATIONS = """
"""