def __init__(self, action=None): self.g = (self, action) # Id similar to channel name, to correctly select the chosen guard among the guard set. self.id = uuid.uuid1().hex # Necessary to allow for correct locking self.dispatch = SocketDispatcher().getThread() self.dispatch.registerGuard(self.id) self.LM = LockMessenger(self.id)
class Guard(object): """ The empty interface of a guard. """ def __init__(self, action=None): self.g = (self, action) # Id similar to channel name, to correctly select the chosen guard among the guard set. self.id = uuid.uuid1().hex self.id = self.id.encode() # Necessary to allow for correct locking self.dispatch = SocketDispatcher().getThread() self.dispatch.registerGuard(self.id) self.LM = LockMessenger(self.id) def _offer(self, req): try: # Acquire lock conn, state, seq = self.LM.remote_acquire_and_get_state( req.process) # Check sequence number if seq != req.seq_check: state = FAIL # Success? if (state == READY): self.LM.remote_notify(conn, req.process, req.ch_id, None) # Release lock self.LM.remote_release(conn, req.process) except AddrUnavailableException: # Unable to reach process during offer # The primary reason is probably because a request were part of an alting and the process have exited. if conf.get(SOCKETS_STRICT_MODE): raise FatalException( "PyCSP unable to reach process during Guard.offer(%s)" % str(self.process)) else: sys.stderr.write( "PyCSP unable to reach process during Guard.offer(%s)\n" % str(self.process)) def _close(self): # Invoked from Alternation self.dispatch.deregisterGuard(self.id)
class Guard: """ The empty interface of a guard. """ def __init__(self, action=None): self.g = (self, action) # Id similar to channel name, to correctly select the chosen guard among the guard set. self.id = uuid.uuid1().hex # Necessary to allow for correct locking self.dispatch = SocketDispatcher().getThread() self.dispatch.registerGuard(self.id) self.LM = LockMessenger(self.id) def _offer(self, req): try: # Acquire lock conn, state, seq = self.LM.remote_acquire_and_get_state(req.process) # Check sequence number if seq != req.seq_check: state = FAIL # Success? if (state == READY): self.LM.remote_notify(conn, req.process, req.ch_id, None) # Release lock self.LM.remote_release(conn, req.process) except AddrUnavailableException: # Unable to reach process during offer # The primary reason is probably because a request were part of an alting and the process have exited. if conf.get(SOCKETS_STRICT_MODE): raise FatalException("PyCSP unable to reach process during Guard.offer(%s)" % str(self.process)) else: sys.stderr.write("PyCSP unable to reach process during Guard.offer(%s)\n" % str(self.process)) def _close(self): # Invoked from Alternation self.dispatch.deregisterGuard(self.id)
def run(self): # Create remote lock self.cond = threading.Condition() dispatch = SocketDispatcher().getThread() self.addr = dispatch.server_addr dispatch.registerProcess(self.id, RemoteLock(self)) try: self.return_value = self.fn(*self.args, **self.kwargs) except ChannelPoisonException as e: # look for channels and channel ends self.__check_poison(self.args) self.__check_poison(self.kwargs.values()) except ChannelRetireException as e: # look for channel ends self.__check_retire(self.args) self.__check_retire(self.kwargs.values()) # Join spawned processes for p in self.spawned: p.join_report() # Initiate clean up and waiting for channels to finish outstanding operations. for channel in self.activeChanList: channel._CM.leave(channel, self) # Wait for channels self.cond.acquire() X = len(self.activeChanList) while len(self.closedChanList) < X: self.cond.wait() self.cond.release() dispatch.deregisterProcess(self.id) # Deregister channel references for chan in self.registeredChanConnectList: chan._deregister() for chan in self.registeredChanHomeList: chan._deregister() for chan in self.registeredChanHomeList: chan._threadjoin()
def run(self): # Multiprocessing inherits global objects like singletons. Thus we must reset! # Reset SocketDispatcher Singleton object to force the creation of a new # SocketDispatcher # Host and Port address will be set for the SocketDispatcher (one per interpreter/multiprocess) if "pycsp_host" in self.kwargs: self.host = self.kwargs.pop("pycsp_host") else: self.host = '' if "pycsp_port" in self.kwargs: self.port = self.kwargs.pop("pycsp_port") else: self.port = None if self.host != '': conf.set(PYCSP_HOST, self.host) if self.port != None: conf.set(PYCSP_PORT, self.port) try: SocketDispatcher(reset=True) except SocketBindException as e: self._error.value = 1001 self.return_pipe[1].send(None) return # Create remote lock self.cond = threading.Condition() dispatch = SocketDispatcher().getThread() self.addr = dispatch.server_addr dispatch.registerProcess(self.id, RemoteLock(self)) return_value = None try: return_value = self.fn(*self.args, **self.kwargs) except ChannelPoisonException as e: # look for channels and channel ends self.__check_poison(self.args) self.__check_poison(list(self.kwargs.values())) except ChannelRetireException as e: # look for channel ends self.__check_retire(self.args) self.__check_retire(list(self.kwargs.values())) finally: self.return_pipe[1].send(return_value) # Join spawned processes for p in self.spawned: p.join_report() # Initiate clean up and waiting for channels to finish outstanding operations. for channel in self.activeChanList: channel._CM.leave(channel, self) # Wait for channels self.cond.acquire() X = len(self.activeChanList) while len(self.closedChanList) < X: self.cond.wait() self.cond.release() dispatch.deregisterProcess(self.id) # Deregister namespace references for chan in self.registeredChanConnectList: chan._deregister() for chan in self.registeredChanHomeList: chan._deregister() for chan in self.registeredChanHomeList: chan._threadjoin() # Wait for sub-processes as these may not yet have quit. for processchild in multiprocessing.active_children(): processchild.join() # Wait for sub-threads as these may not yet have quit. When threads are run in multiprocesses (daemon setting is ignored) skip = threading.currentThread() for threadchild in threading.enumerate(): if not threadchild == skip: threadchild.join()
def run(self): # Multiprocessing inherits global objects like singletons. Thus we must reset! # Reset SocketDispatcher Singleton object to force the creation of a new # SocketDispatcher # Host and Port address will be set for the SocketDispatcher (one per interpreter/multiprocess) if self.kwargs.has_key("pycsp_host"): self.host = self.kwargs.pop("pycsp_host") else: self.host = '' if self.kwargs.has_key("pycsp_port"): self.port = self.kwargs.pop("pycsp_port") else: self.port = None if self.host != '': conf.set(PYCSP_HOST, self.host) if self.port != None: conf.set(PYCSP_PORT, self.port) try: SocketDispatcher(reset=True) except SocketBindException as e: self._error.value = 1001 self.return_pipe[1].send(None) return # Create remote lock self.cond = threading.Condition() dispatch = SocketDispatcher().getThread() self.addr = dispatch.server_addr dispatch.registerProcess(self.id, RemoteLock(self)) return_value = None try: return_value = self.fn(*self.args, **self.kwargs) except ChannelPoisonException as e: # look for channels and channel ends self.__check_poison(self.args) self.__check_poison(self.kwargs.values()) except ChannelRetireException as e: # look for channel ends self.__check_retire(self.args) self.__check_retire(self.kwargs.values()) finally: self.return_pipe[1].send(return_value) # Join spawned processes for p in self.spawned: p.join_report() # Initiate clean up and waiting for channels to finish outstanding operations. for channel in self.activeChanList: channel._CM.leave(channel, self) # Wait for channels self.cond.acquire() X = len(self.activeChanList) while len(self.closedChanList) < X: self.cond.wait() self.cond.release() dispatch.deregisterProcess(self.id) # Deregister namespace references for chan in self.registeredChanConnectList: chan._deregister() for chan in self.registeredChanHomeList: chan._deregister() for chan in self.registeredChanHomeList: chan._threadjoin() # Wait for sub-processes as these may not yet have quit. for processchild in multiprocessing.active_children(): processchild.join() # Wait for sub-threads as these may not yet have quit. When threads are run in multiprocesses (daemon setting is ignored) skip = threading.currentThread() for threadchild in threading.enumerate(): if not threadchild == skip: threadchild.join()
def shutdown(): """ Closing the PYCSP instance Every PyCSP application will create a server thread, to serve incoming communications on channels. For this reason, it is required to always end the PyCSP application with a call to shutdown() Usage: >>> shutdown() Performs a stable shutdown of hosted channels, waiting for local and remote processes to disconnect from the hosted channels. """ global init_procs try: # compatible with Python 2.6+ current_proc = threading.current_thread() except AttributeError: # compatible with Python 2.5- current_proc = threading.currentThread() try: if current_proc.maintained: raise InfoException("pycsp.shutdown must not be called in PyCSP processes wrapped in a PyCSP.Process structure. PyCSP.Process processes have their own shutdown mechanism.") except AttributeError: pass try: dispatch = SocketDispatcher().getThread() for p in current_proc.spawned: p.join_report() # Initiate clean up and waiting for channels to finish outstanding operations. for channel in current_proc.activeChanList: channel._CM.leave(channel, current_proc) # Wait for channels current_proc.cond.acquire() X = len(current_proc.activeChanList) while len(current_proc.closedChanList) < X: current_proc.cond.wait() current_proc.cond.release() dispatch.deregisterProcess(current_proc.id) # Deregister channel references for chan in current_proc.registeredChanConnectList: chan._deregister() for chan in current_proc.registeredChanHomeList: chan._deregister() # Wait for channelhomethreads to terminate for chan in current_proc.registeredChanHomeList: chan._threadjoin() # Cleaning structures current_proc.spawned = [] current_proc.registeredChanHomeList = [] current_proc.registeredChanConnectList = [] current_proc.activeChanList = [] current_proc.closedChanList = [] # Reset current_proc id, to force a new init(), if required del current_proc.id except AttributeError: pass
def init(): """ Initialising state variables for channel communication made from an uninitialized thread/process (__main__). This function is invoked from const.getThreadAndName to initialise the current NON-CSP! process when necessary. """ global init_procs try: # compatible with Python 2.6+ current_proc = threading.current_thread() except AttributeError: # compatible with Python 2.5- current_proc = threading.currentThread() run = True try: if current_proc.id != None: run = False except AttributeError: pass if run: if not current_proc in init_procs: init_procs.append(current_proc) current_proc.id = uuid.uuid1().hex + ".__INIT__" current_proc.fn = None current_proc.state = FAIL current_proc.result_ch_idx = None current_proc.result_msg = None current_proc.ack = False current_proc.sequence_number = 1 # Protect against early termination of mother-processes leaving childs in an invalid state current_proc.spawned = [] # Protect against early termination of channelhomes leaving channel references in an invalid state current_proc.registeredChanHomeList = [] current_proc.registeredChanConnectList = [] # Protect against early termination of processes leaving channelhomes in an invalid state current_proc.activeChanList = [] current_proc.closedChanList = [] current_proc.cond = threading.Condition() dispatch = SocketDispatcher().getThread() current_proc.addr = dispatch.server_addr dispatch.registerProcess(current_proc.id, RemoteLock(current_proc)) def wait_ack(): current_proc.cond.acquire() while not current_proc.ack: current_proc.cond.wait() # Got ack, resetting current_proc.ack= False current_proc.cond.release() def wait(): current_proc.cond.acquire() while current_proc.state == READY: current_proc.cond.wait() current_proc.cond.release() current_proc.wait = wait current_proc.wait_ack = wait_ack