[Zope-Checkins] CVS: Zope/lib/python/ZServer/PubCore - ZRendezvous.py:1.11

Chris McDonough chrism at plope.com
Wed Mar 24 01:05:21 EST 2004


Update of /cvs-repository/Zope/lib/python/ZServer/PubCore
In directory cvs.zope.org:/tmp/cvs-serv6301

Modified Files:
	ZRendezvous.py 
Log Message:
Jim commented this code at the PyCon DC 2004 sprint.


=== Zope/lib/python/ZServer/PubCore/ZRendezvous.py 1.10 => 1.11 ===
--- Zope/lib/python/ZServer/PubCore/ZRendezvous.py:1.10	Tue Mar 18 16:15:16 2003
+++ Zope/lib/python/ZServer/PubCore/ZRendezvous.py	Wed Mar 24 01:05:19 2004
@@ -15,49 +15,87 @@
 from ZServerPublisher import ZServerPublisher
 
 class ZRendevous:
+    """Worker thread pool
+
+    For better or worse, we hide locking sementics from the worker
+    threads.  The worker threads do no locking.
+    """ 
 
     def __init__(self, n=1):
-        sync=thread.allocate_lock()
-        self._a=sync.acquire
-        self._r=sync.release
-        pool=[]
-        self._lists=pool, [], []
-        self._a()
+        sync = thread.allocate_lock()
+        self._acquire = sync.acquire
+        self._release = sync.release
+        pool = []
+        self._lists = (
+            pool, # Collection of locks representing threads are not
+                  # waiting for work to do
+            [],   # Request queue
+            [],   # Pool of locks representing threads that are
+                  # waiting (ready) for work to do.
+            )
+        
+        self._acquire() # callers will block
         try:
             while n > 0:
-                l=thread.allocate_lock()
+                l = thread.allocate_lock()
                 l.acquire()
                 pool.append(l)
                 thread.start_new_thread(ZServerPublisher,
                                         (self.accept,))
-                n=n-1
-        finally: self._r()
+                n = n-1
+        finally:
+            self._release() # let callers through now
 
     def accept(self):
-        self._a()
+        """Return a request from the request queue
+
+        If no requests are in the request queue, then block until
+        there is nonw.
+        """
+        self._acquire() # prevent other calls to protect data structures
         try:
             pool, requests, ready = self._lists
             while not requests:
-                l=pool[-1]
-                del pool[-1]
+                # There are no requests in the queue. Wait until there are.
+
+                # This thread is waiting, to remove a lock from the collection
+                # of locks corresponding to threads not waiting for work
+                l = pool.pop()
+
+                # And add it to the collection of locks representing threads
+                # ready and waiting for work.
                 ready.append(l)
-                self._r()
+                self._release() # allow other calls
+
+                # Now try to acquire the lock. We will block until
+                # someone calls handle to queue a request and releases the lock
+                # which handle finds in the ready queue
                 l.acquire()
-                self._a()
+
+                self._acquire() # prevent calls so we can update
+                                # not waiting pool
                 pool.append(l)
 
-            r=requests[0]
-            del requests[0]
-            return r
-        finally: self._r()
+            # return the *first* request
+            return requests.pop(0)
+
+        finally:
+            self._release() # allow calls
 
     def handle(self, name, request, response):
-        self._a()
+        """Queue a request for processing
+        """
+        self._acquire() # prevent other calls to protect data structs
         try:
             pool, requests, ready = self._lists
+            # queue request
             requests.append((name, request, response))
             if ready:
-                l=ready[-1]
-                del ready[-1]
-                l.release()
-        finally: self._r()
+                # If any threads are ready and waiting for work
+                # then remove one of the locks from the ready pool
+                # and release it, letting the waiting thread go forward
+                # and consume the request
+                ready.pop().release()
+
+        finally:
+            self._release()




More information about the Zope-Checkins mailing list