Queue.Queue-like class without the busy-wait

Antoon Pardon apardon at forel.vub.ac.be
Tue Mar 29 07:28:21 EST 2005


Op 2005-03-29, Antoon Pardon schreef <apardon at forel.vub.ac.be>:
> Op 2005-03-29, Paul Rubin schreef <http>:
>> Antoon Pardon <apardon at forel.vub.ac.be> writes:
>>> Well have a look at what I have written over the weekend. It uses
>>> a seperate thread with one pipe for a wakeup mechanisme.
>>
>> Thanks, I'll look at it.  Why don't you use usleep instead of a pipe?
>
> Because with the pipe the "sleep" can be indeterminate.
>
> The select make the thread sleep until either of the folowing
> happens.
>
>   1) A timeout, which means one of the locks has to be broken
>
>   2) A byte was received. This means a lock was tried to be
>      acquired and inserted in the heap, so the timeout may
>      need to be recalculated. (acquiring a lock, sends a
>      byte over the pipe)
>
>> I decided over the weekend that using a separate thread with usleep is
>> the simplest thing to do in pure Python.
>
> I'm not going to call my solution simple, but it wastes very few
> cycles. if no thread is blocked on a lock, the select will just
> block until that changes. No need for some kind of polling loop.
>

And here is a small patch for it. It corrects the acquiring and
releasing of the heapmutex.

--- tlock.py    2005-03-29 14:25:09.000000000 +0200
+++ src/python/tlock.py 2005-03-29 14:25:43.000000000 +0200
@@ -67,6 +67,7 @@
     heapmutex.acquire()
     waketime, pl, mutex, table = heap[0]
     timeout = waketime - time.time()
+    heapmutex.release()
     while timeout <= 0.0:
       lck = pl()
       if lck is not None:
@@ -82,10 +83,11 @@
             pass
         finally:
           mutex.release()
+      heapmutex.acquire()
       heappop(heap)
       waketime, pl, mutex, table = heap[0]
       timeout = waketime - time.time()
-    heapmutex.release()
+      heapmutex.release()
     rdlst, wrlst, erlst = select([heapfd],[],[],timeout)
     if rdlst:
       os.read(rdlst[0],1)
@@ -107,17 +109,17 @@
 
     for Nr in xrange(20):
       try:
-        print "Trying   %d (loop %d)" % (Id, Nr)
+        print "Trying   %2d (loop %2d)" % (Id, Nr)
         T.acquire(randint(0,rg))
-        print "Entering %d (loop %d)" % (Id, Nr)
+        print "Entering %2d (loop %2d)" % (Id, Nr)
         sleep(randint(0,rg))
-        print "Leaving  %d (loop %d)" % (Id, Nr)
+        print "Leaving  %2d (loop %2d)" % (Id, Nr)
         T.release()
       except TimeOut, ErrId:
-        print "Failed   %d (loop %d)" % (Id, Nr)
+        print "Failed   %2d (loop %2d)" % (Id, Nr)
       sleep(randint(0,rg))
 
 
-  for i in xrange(rg):
+  for i in xrange(5 * rg):
     th = threading.Thread(target=thrd, args=(i,))
     th.start()



More information about the Python-list mailing list