#! /usr/local/bin/python -- """ usage: %(progname)s [args] """ import bisect import os import select import socket import string import sys import time import whrandom import coro import fcntl, FCNTL class coroutine_device: "socket that automatically suspends/resumes instead of blocking." def __init__ (self, _fileno=None): self._fileno = _fileno self._closed = 0 if self._fileno: flags = fcntl.fcntl(self._fileno, FCNTL.F_GETFL, 0) fcntl.fcntl(self._fileno, FCNTL.F_SETFL, flags | FCNTL.O_NONBLOCK) def fileno (self): return self._fileno TimeoutError = coro.TimeoutError def wait_for_read (self, timeout=None): me = coro.current_thread() if timeout is not None: triple = coro.the_event_list.insert_event (me, time.time()+timeout, TIMEOUT_VALUE) if me is None: raise coro.CoroutineSocketError, "coroutine sockets cannot run in 'main'" else: coro.read_set[self._fileno] = me try: result = me.yield_() except: raise coro.CoroutineSocketError, "coroutine socket could not yield_" if result == coro.TIMEOUT_VALUE: # i.e, we timed out del coro.read_set[self._fileno] raise TimeoutError elif timeout is not None: try: # remove event coro.the_event_list.remove_event (triple) except: print "Error removing: result=%s" % result if result == coro.BADF_ERROR: # ie, bad socket for select raise coro.CoroutineSocketError, "bad file descriptor" def wait_for_write (self, timeout=None): me = coro.current_thread() if timeout is not None: triple = coro.the_event_list.insert_event (me, time.time()+timeout, TIMEOUT_VALUE) if me is None: raise coro.CoroutineSocketError, "coroutine sockets cannot run in 'main'" else: coro.write_set[self._fileno] = me try: result = me.yield_() except: raise coro.CoroutineSocketError, "coroutine socket could not yield_" if result == coro.TIMEOUT_VALUE: # i.e, we timed out del coro.write_set[self._fileno] raise TimeoutError elif timeout is not None: # remove event coro.the_event_list.remove_event (triple) if result == coro.BADF_ERROR: # ie, bad socket for select raise coro.CoroutineSocketError, "bad file descriptor" def read(self, buffer_size): self.wait_for_read() return os.read(self._fileno, buffer_size) def write(self, data): self.wait_for_write() return os.write(self._fileno, data) def close (self): if not self._closed: self._closed = 1 if self._fileno: return os.close(self._fileno) else: return None def __del__ (self): self.close()