changeset 13:65482f4e2555

Added a really simple channel communication system, somewhat similar to that of Stackless.
author Atul Varma <varmaa@toolness.com>
date Sun, 19 Apr 2009 12:55:38 -0700
parents 1ffa6554ff3a
children 545927beb490
files channels.py cosocket.py example.py
diffstat 3 files changed, 48 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/channels.py	Sun Apr 19 12:55:38 2009 -0700
@@ -0,0 +1,22 @@
+_channels = {}
+
+class until_message_sent(object):
+    def __init__(self, channel_name, message):
+        self.channel_name = channel_name
+        self.message = message
+
+    def execute(self, dispatcher):
+        if self.channel_name in _channels:
+            for receiver in _channels[self.channel_name]:
+                receiver.return_from_yield(self.message)
+            _channels[self.channel_name] = []
+        dispatcher.return_from_yield()
+
+class until_message_received(object):
+    def __init__(self, channel_name):
+        self.channel_name = channel_name
+
+    def execute(self, dispatcher):
+        if self.channel_name not in _channels:
+            _channels[self.channel_name] = []
+        _channels[self.channel_name].append(dispatcher)
--- a/cosocket.py	Sat Apr 18 12:45:10 2009 -0700
+++ b/cosocket.py	Sun Apr 19 12:55:38 2009 -0700
@@ -11,34 +11,34 @@
         self.__data = []
         self.__coroutine_stack = []
         if conn:
-            self.__process_next_instruction()
+            self.return_from_yield()
 
-    def __process_next_instruction(self, feedback = None):
+    def return_from_yield(self, message = None):
         try:
-            instruction = self.__coroutine.send(feedback)
+            instruction = self.__coroutine.send(message)
         except StopIteration:
             if self.__coroutine_stack:
                 self.__coroutine = self.__coroutine_stack.pop()
-                self.__process_next_instruction()
+                self.return_from_yield()
             else:
                 self.close()
         else:
             if type(instruction) == types.GeneratorType:
                 self.__coroutine_stack.append(self.__coroutine)
                 self.__coroutine = instruction
-                self.__process_next_instruction()
+                self.return_from_yield()
             else:
                 instruction.execute(self)
 
     def handle_connect(self):
-        self.__process_next_instruction()
+        self.return_from_yield()
 
     def initiate_send(self):
         asynchat.async_chat.initiate_send(self)
         if ((not self.ac_out_buffer) and
             (len(self.producer_fifo) == 0) and
             self.connected):
-            self.__process_next_instruction()
+            self.return_from_yield()
 
     def collect_incoming_data(self, data):
         # TODO: Enforce some maximum data length.
@@ -48,7 +48,7 @@
         self.set_terminator(None)
         data = ''.join(self.__data)
         self.__data = []
-        self.__process_next_instruction(data)
+        self.return_from_yield(data)
 
 class CoroutineSocketServer(asyncore.dispatcher):
     def __init__(self, addr, coroutineFactory):
--- a/example.py	Sat Apr 18 12:45:10 2009 -0700
+++ b/example.py	Sun Apr 19 12:55:38 2009 -0700
@@ -1,12 +1,24 @@
 from cosocket import *
+import channels
+
+def _make_http_response(msg):
+    return ('HTTP/1.1 200 OK\r\n' +
+            'Content-Length: %d\r\n' % len(msg) +
+            'Content-Type: text/plain\r\n\r\n' +
+            msg)
 
 def example_http_server_coroutine(addr):
-    request = yield until_received(terminator = '\r\n\r\n')
-    msg = 'hello %s.' % addr[0]
-    yield until_sent('HTTP/1.1 200 OK\r\n' +
-                     'Content-Length: %d\r\n' % len(msg) +
-                     'Content-Type: text/plain\r\n\r\n' +
-                     msg)
+    request_line = yield until_received(terminator = '\r\n')
+    request_headers = yield until_received(terminator = '\r\n\r\n')
+    req_parts = request_line.split()
+    if req_parts[1] == '/listen':
+        ip = yield channels.until_message_received('global')
+        yield until_sent(_make_http_response('send from %s.' % ip))
+    elif req_parts[1] == '/send':
+        yield channels.until_message_sent('global', addr[0])
+        yield until_sent(_make_http_response('sent.'))
+    else:
+        yield until_sent(_make_http_response('hello %s.' % addr[0]))
 
 def _example_nested_coroutine():
     chunk = yield until_received(bytes = 20)