""" 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 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, funcs): self.funcs = funcs self.pids = [] self.fds = {} self.buffers = {} self.results = {} def is_done(self): return len(self.fds) == 0 def cleanup(self): # close pipes and kill child processes for pid,(i,fd) in self.fds.iteritems(): 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 self.fds.iteritems(): os.waitpid( pid, 0 ) self.results[pid] = None self.fds = {} self.buffers = {} def child( self, fdw, f): # call function res = f() # 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: if os.getpid() != parentpid: os._exit(rc) def fork_all(self): for i,f in enumerate(self.funcs): pid, fd = self.fork_one(f) self.pids.append(pid) self.fds[pid] = (i,fd) self.buffers[fd] = cStringIO.StringIO() def communicate(self): rlist = [ fd for _, (_,fd) in self.fds.iteritems() ] rlist.append(pyabc.wait_fd) stop = False while not stop: rrdy = _retry_select( rlist ) for fd in rrdy: if fd == pyabc.wait_fd: stop = True continue self.buffers[fd].write( os
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)

// Google Mock - a framework for writing C++ mock classes.
//
// This file is for verifying that various Google Mock constructs do not
// produce linker errors when instantiated in different translation units.
// Please see gmock_link_test.h for details.

#define LinkTest LinkTest1

#include  "test/gmock_link_test.h"