1# encoding: utf-8 2 3__all__ = ['Pipe', 'pipe'] 4 5 6class Pipe(object): 7 """An OS independent asynchronous pipe.""" 8 9 def __init__(self): 10 # Based on Zope async.py: http://svn.zope.org/zc.ngi/trunk/src/zc/ngi/async.py 11 12 self.writer = socket.socket() 13 self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 14 15 count = 0 16 while 1: 17 count += 1 18 a = socket.socket() 19 a.bind(("127.0.0.1", 0)) 20 connect_address = a.getsockname() 21 a.listen(1) 22 23 try: 24 self.writer.connect(connect_address) 25 break 26 27 except socket.error: 28 detail = exception().exception 29 30 if detail[0] != errno.WSAEADDRINUSE: 31 raise 32 33 if count >= 10: 34 a.close() 35 self.writer.close() 36 raise socket.error("Cannot bind trigger!") 37 38 a.close() 39 40 self.reader, addr = a.accept() 41 self.reader.setblocking(0) 42 self.writer.setblocking(0) 43 a.close() 44 45 self.writer_fd = self.writer.fileno() 46 self.reader_fd = self.reader.fileno() 47 48 def read(self): 49 """Emulate a file descriptors read method""" 50 try: 51 return self.reader.recv(1) 52 except socket.error: 53 ex = exception().exception 54 if ex.args[0] == errno.EWOULDBLOCK: 55 raise IOError 56 raise 57 58 def write(self, data): 59 """Emulate a file descriptors write method""" 60 return self.writer.send(data) 61 62 63def pipe(): 64 """Return the optimum pipe implementation for the capabilities of the active system.""" 65 66 try: 67 from os import pipe 68 return pipe() 69 70 except: 71 pipe = Pipe() 72 return pipe.reader_fd, pipe.writer_fd 73