# Twisted stackless example # See the `blocking' echo server at the end # # agl@imperialviolet.org from stackless import channel, tasklet import stackless from twisted.internet import reactor, protocol import twisted.python import twisted.python.rebuild def twisted_tasklet (): reactor.run () tasklet (twisted_tasklet) () class StacklessProtocol (protocol.Protocol): def __init__ (self, in_buf_size = 32768, out_buf_size = 32768): self.__chan = channel () self.__task = tasklet (self.process)() self.__out_buf = "" self.__in_buf = "" self.__n = 0 self.__waiting_on_read = False self.__waiting_on_write = False self.__waiting_for_write = True self.__in_buf_size = in_buf_size self.__out_buf_size = out_buf_size self.__task.run () def reada (self, n): while len (self.__in_buf) < n: self.__waiting_on_read = 1 self.__chan.receive () a = self.__in_buf[:n] self.__in_buf = self.__in_buf[n:] return a def read (self): while len (self.__in_buf) == 0: self.__waiting_on_read = 1 self.__chan.receive () a = self.__in_buf self.__in_buf = "" return a def write (self, s): while len (self.__out_buf) > self.__out_buf_size: self.__waiting_on_write = 1 self.__chan.receive () self.__out_buf += s if self.__waiting_for_write: reactor.callLater (0, self.__write_ready) self__waiting_for_write = False def resumeProducing (self): if len (self.__out_buf) == 0: self.transport.unregisterProducer () self.__waiting_for_write = True else: self.transport.write (self.__out_buf) self.__out_buf = "" if self.__waiting_on_write: self.__waiting_on_write = False self.__chan.send (1) def __write_ready (self): self.transport.registerProducer (self, 0) def dataReceived(self, data): self.__in_buf += data if len (self.__in_buf) > self.__in_buf_size: self.transport.pauseProducing () if self.__waiting_on_read: self.__waiting_on_read = False self.__chan.send (1) class LineReader (object): def line_read (self): while True: line = self.__line_get () if line != None: return line try: self.__linebuf += self.read () except AttributeError: self.__linebuf = "" self.__linebuf += self.read () def __line_get (self): try: index = self.__linebuf.find ('\n') except AttributeError: self.__linebuf = "" return None if index == -1: return None a = self.__linebuf[:index] self.__linebuf = self.__linebuf[index+1:] if len (a) > 0 and a[-1] == '\r': a = a[:-1] return a class MyServer(StacklessProtocol, LineReader): def process (self): while True: self.write (self.line_read () + '\n') factory = protocol.Factory () factory.protocol = MyServer reactor.listenTCP (8007, factory) stackless.run ()