Jim Dukarm wrote: > On Monday 23 August 2004 11:52, Graham Fawcett wrote: > >>I need to implement a lock in a certain block of code, so that only one >>process at a time is will be able to execute the restricted block. (Note >>this is an inter-process lock, not an inter-thread lock, or I would just >>use the standard threading library.) >> > > Would it be practical to run the restricted code in its own process as a > server (maybe using Medusa or sockets) which responds to only one request > from your application(s) at a time? That would be a very portable solution. Why didn't I think of that? Actually, moving the code into Medusa would be a pain. But I could write a server to manage semaphores, upon which I could build the locks. In fact, it could even be multithreaded... ....... Okay, this ought to do the trick. Thanks for the inspiration, Jim! -- Graham # ===================================================== """ ipc_lock.py: lightweight interprocess locks. Usage: from ipc_lock import Lock lock = Lock('lock_name') lock.acquire() try: do_something() finally: lock.release() You must run a lock server as well: ls = LockServer() ls.serve_forever() will do the trick. It's a basic socket server, multi-threaded, with a basic line protocol. Commands are of the form := '\n' := '+' | '-' | '*' := [^\n]* where is a single character command in '+-*'. The message '+fred' would acquire the lock named 'fred', blocking until it's available. '-fred' will release the lock. The dangerous '*' command will release all locks and is for debugging. """ from threading import Lock as _Lock import socket import SocketServer class LockServer(SocketServer.ThreadingTCPServer): PORT = 5555 locks = {} def __init__(self): SocketServer.ThreadingTCPServer.__init__( self, ('', self.PORT), LockHandler) print 'serving %s on port %d' % (self, self.PORT) def get_lock(self, lockname): if not self.locks.has_key(lockname): self.locks[lockname] = _Lock() return self.locks[lockname] class LockHandler(SocketServer.BaseRequestHandler): def handle(self): data = '' while not '\n' in data: data += self.request.recv(128) data = data.rstrip() cmd = data[0] if cmd == '*': self.server.locks.clear() self.request.send('*\r\n') else: key = data[1:] lock = self.server.get_lock(key) if cmd == '+': lock.acquire() self.request.send('+%s\r\n' % key) elif cmd == '-': lock.release() self.request.send('-%s\r\n' % key) else: self.request.send('?%s' % data) class Lock: def __init__(self, name): self.name = name def acquire(self): s = socket.socket() s.connect(('localhost', 5555)) s.send('+%s\n' % self.name) return s.recv(1024) # okay, I copy-pasted. Sue me... def release(self): s = socket.socket() s.connect(('localhost', 5555)) s.send('-%s\n' % self.name) return s.recv(1024) def clear_all(): s = socket.socket() s.connect(('localhost', 5555)) s.send('*\n') return s.recv(1024) if __name__ == '__main__': s = LockServer() s.serve_forever()