473,657 Members | 2,366 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

A lock that times out but doesn't poll

The queue and condition class allow threads to wait only a limited
time. However this currently is implemented by a polling loop.

Now for those who like to avoid polling I have here a Tlock
class that allows for a timeout but doesn't use polling.

All comments are welcome.
----------------------- Tlock.py -------------------------------

import threading

class TimeOut(Excepti on):
pass

class Tlock:

def __init__(self):

self.mutex = threading.Lock( )
self.lktab = [threading.Lock( )]
def acquire(self, timeout=None):

class SC:
pass
def break_lock(sc, mutex, tab):

mutex.acquire()
try:
try:
i = tab.index(sc.pl , 1)
del tab[i]
sc.broken = True
sc.pl.release()
sc.pl.release()
except ValueError:
pass
finally:
mutex.release()
self.mutex.acqu ire()
sc=SC()
sc.ll = threading.Lock( )
sc.ll.acquire()
self.lktab.appe nd(sc.ll)
sc.pl = self.lktab[-2]
sc.broken = False
if len(self.lktab) > 2 and timeout is not None:
tm = threading.Timer (timeout, break_lock,
args=[sc, self.mutex, self.lktab])
tm.start()
else:
tm = None
self.mutex.rele ase()
sc.pl.acquire()
if sc.broken:
raise TimeOut, "lock timed out"
else:
if tm is not None:
tm.cancel()
def release(self):

self.mutex.acqu ire()
self.lktab[0].release()
del self.lktab[0]
self.lktab[0].release()
self.mutex.rele ase()
if __name__ == "__main__":

from time import sleep
from random import randint

T = Tlock()

def thrd(Id):

for _ in xrange(100):
try:
print "Trying %d" % Id
T.acquire(randi nt(0,6))
print "Entering %d" % Id
sleep(randint(0 ,6))
print "Leaving %d" % Id
T.release()
except TimeOut, ErrId:
print "Failed %d" % Id
sleep(randint(0 ,6))
for i in xrange(5):
th = threading.Threa d(target=thrd, args=(i,))
th.start()
Jul 18 '05 #1
14 2790
Ironic, isn't it? The whole idea of a condition variable is to avoid
sleeping and polling. The polling soaks up CPU cycles, and the sleeping
introduces latency that might not be acceptable for a given application.

I presented two versions of sleepless timed condition variables in this NG a
year or two ago. They hooted me down like an English kuneegut.

One version used an alarm clock thread. From a very quick glance at your
code, I presume that's what you've done. The other used a C coded timed
lock, something that's not in standard Python. Why, I wonder? I can't
imagine there are many platforms where you can't implement such a thing. I
showed a C extension for MS Windows.

I made my Python module a drop-in replacement for the current threading
module, BTW. I am uncomfortable with the existing package not only because
it uses polling, ("the evil from which we flee"), but also because it's so
convoluted. Reading it, I have a hard time proving to myself that it's
correct. If the package I posted is still on the net somewhere, take a look
at it and see just how simple it can be.

Now they will taunt me a second time.
Jul 18 '05 #2
Okay, I've got a comment: How about some comments? Maybe it's just me, but
I find the code a little hard to comprehend.

What's up with this?

Exception in thread Thread-456:
Traceback (most recent call last):
File "C:\Python23\li b\threading.py" , line 436, in __bootstrap
self.run()
File "C:\Python23\li b\threading.py" , line 544, in run
self.function(* self.args, **self.kwargs)
File "C:\Python23\Sc ripts\foo.py", line 29, in break_lock
sc.pl.release()
error: release unlocked lock

That crops up occasionally.

It's been a while, but as I recall, the tricky bit in implementing timed
locks with an alarm clock thread is seeing to it that threads that don't
time out waiting on a timed lock do not leave zombie alarm clock threads
running. If you are not careful, they could proliferate and eat up system
resources.
"Antoon Pardon" <ap*****@forel. vub.ac.be> wrote in message
news:sl******** ************@rc pc42.vub.ac.be. ..
The queue and condition class allow threads to wait only a limited
time. However this currently is implemented by a polling loop.

Now for those who like to avoid polling I have here a Tlock
class that allows for a timeout but doesn't use polling.

All comments are welcome.
----------------------- Tlock.py -------------------------------

import threading

class TimeOut(Excepti on):
pass

class Tlock:

def __init__(self):

self.mutex = threading.Lock( )
self.lktab = [threading.Lock( )]
def acquire(self, timeout=None):

class SC:
pass
def break_lock(sc, mutex, tab):

mutex.acquire()
try:
try:
i = tab.index(sc.pl , 1)
del tab[i]
sc.broken = True
sc.pl.release()
sc.pl.release()
except ValueError:
pass
finally:
mutex.release()
self.mutex.acqu ire()
sc=SC()
sc.ll = threading.Lock( )
sc.ll.acquire()
self.lktab.appe nd(sc.ll)
sc.pl = self.lktab[-2]
sc.broken = False
if len(self.lktab) > 2 and timeout is not None:
tm = threading.Timer (timeout, break_lock,
args=[sc, self.mutex, self.lktab])
tm.start()
else:
tm = None
self.mutex.rele ase()
sc.pl.acquire()
if sc.broken:
raise TimeOut, "lock timed out"
else:
if tm is not None:
tm.cancel()
def release(self):

self.mutex.acqu ire()
self.lktab[0].release()
del self.lktab[0]
self.lktab[0].release()
self.mutex.rele ase()
if __name__ == "__main__":

from time import sleep
from random import randint

T = Tlock()

def thrd(Id):

for _ in xrange(100):
try:
print "Trying %d" % Id
T.acquire(randi nt(0,6))
print "Entering %d" % Id
sleep(randint(0 ,6))
print "Leaving %d" % Id
T.release()
except TimeOut, ErrId:
print "Failed %d" % Id
sleep(randint(0 ,6))
for i in xrange(5):
th = threading.Threa d(target=thrd, args=(i,))
th.start()

Jul 18 '05 #3
I just took a look at Timer in threading.py. Correct me if I'm wrong, but
it appears that the
timer always stays around for the programmed interval, even if cancel() is
called on it. If that's the
case, it's hard for me to see how it could be used to implement a useful
timed lock. The typical scenario
is for a thread to obtain a lock fairly quickly when things are functioning
properly, but to wait on it with
a long timeout in case some resource dries up -- like a socket connection
breaks. In that scenario,
a thread that repeatedly waits on a timed lock will generate new Timer
threads faster than they will die off.

How can you use cancel() for anything? In a time-sliced environment,
won't there
always be a race condition?

Once again, I have reservations about threading.py. I do realtime
programming in my day job, so
I see bush-whackers behind every rhododendron. Why, the stories I could
tell. They would
make a grown man sick Heck, they would make a sick man groan.

I looked for my pure Python version of timed locks, but I couldn't find it.
I'm wondering if I found
problems with *it* and deleted it.

I did find the MS-Windows timed lock extension though.
Jul 18 '05 #4
Op 2004-11-25, Jive schreef <so*****@micros oft.com>:
I just took a look at Timer in threading.py. Correct me if I'm wrong, but
it appears that the
timer always stays around for the programmed interval, even if cancel() is
called on it. If that's the
case, it's hard for me to see how it could be used to implement a useful
timed lock. The typical scenario
is for a thread to obtain a lock fairly quickly when things are functioning
properly, but to wait on it with
a long timeout in case some resource dries up -- like a socket connection
breaks. In that scenario,
a thread that repeatedly waits on a timed lock will generate new Timer
threads faster than they will die off.


Only at the beginning, after the mean timeout Timer threads should die
out as fast as new are created. But that may be too much.

But is is worst. I found out that in order to wait the specific time
the Timer class uses a polling loop until the specified time is expired.

--
Antoon Pardon
Jul 18 '05 #5
Op 2004-11-25, Jive schreef <so*****@micros oft.com>:
Okay, I've got a comment: How about some comments? Maybe it's just me, but
I find the code a little hard to comprehend.
The basic algorithm is that you have a list of simple locks that is
treated mostly like a queue. A tread that aquires the Tlock, first
allocates a new lock that is appened to the list and aquired, then
the next to last lock is aquired too.

A thread that releases the lock, releases the first lock and
deletes it from the table and then release the new first
lock.
A thread that specifies a timeout on the release, starts a timer
thread. This timer thread will look if the lock is in the table
and if so releases it and removes it from the table. It also
marks the lock is broken.

What's up with this?

Exception in thread Thread-456:
Traceback (most recent call last):
File "C:\Python23\li b\threading.py" , line 436, in __bootstrap
self.run()
File "C:\Python23\li b\threading.py" , line 544, in run
self.function(* self.args, **self.kwargs)
File "C:\Python23\Sc ripts\foo.py", line 29, in break_lock
sc.pl.release()
error: release unlocked lock

That crops up occasionally.
There are two solutions for that.

1) Just remove line 29, it is not needed but I entered it for
"estetical" concerns.

2) Use semaphores in the table. That means changing the Lock
to a Semaphore on lines 11 and 38.
It's been a while, but as I recall, the tricky bit in implementing timed
locks with an alarm clock thread is seeing to it that threads that don't
time out waiting on a timed lock do not leave zombie alarm clock threads
running. If you are not careful, they could proliferate and eat up system
resources.


What do you mean with a Zombie? The clock thread will remain for as long
as the timeout, which may be longer then needed but then they disappear,
so there won't be any real zombies.
But I expect some of the python comunity are laughing at me now, because
I have discoverd that the Timer class is implemented by a Condition
variable that is waited upon with a timeout. And this timeout is
implemented by a polling loop.
--
Antoon Pardon
Jul 18 '05 #6
"Jive" <so*****@micros oft.com> writes:
I did find the MS-Windows timed lock extension though.


That's pretty much what I use when I need them (at least under
Windows). For example, in a recent application I had a serious need
for low latency events and minimizing CPU while blocked. Switching
from the threading.Event to a Win32 event object was a big win on both
fronts, and are pretty drop-in in terms of functionality. I imagine
there is something similar in pthreads, but have not had the need
there yet.

Probably the best way to support this sort of thing in Python itself
is with OS-specific blocks for cases which are easy to do and fall
back to the current implementation in others. But as has been posted
here before, that needs someone to make, test and then propose the
changes.

-- David
Jul 18 '05 #7

"Antoon Pardon" <ap*****@forel. vub.ac.be> wrote in message
news:sl******** ************@rc pc42.vub.ac.be. ..

What do you mean with a Zombie? The clock thread will remain for as long
as the timeout, which may be longer then needed but then they disappear,
so there won't be any real zombies.


Whether you call them zombies or not, they can multiply like crazy and fll
up system memory.
Jul 18 '05 #8

"David Bolen" <db**@fitlinxx. com> wrote in message
news:ui******** ***@fitlinxx.co m...
"Jive" <so*****@micros oft.com> writes:
I did find the MS-Windows timed lock extension though.
That's pretty much what I use when I need them (at least under
Windows). For example, in a recent application I had a serious need
for low latency events and minimizing CPU while blocked. Switching
from the threading.Event to a Win32 event object was a big win on both
fronts, and are pretty drop-in in terms of functionality. I imagine
there is something similar in pthreads, but have not had the need
there yet.

Probably the best way to support this sort of thing in Python itself
is with OS-specific blocks for cases which are easy to do and fall
back to the current implementation in others. But as has been posted
here before, that needs someone to make, test and then propose the
changes.

-- David


Ah ha! You understand. I live and breath this stuff. You too?

Here is a common example from my line of work: You set a piece of machinery
into motion. If everything is operating normally, it will reach a certain
point and interrupt a light beam. You must react to that event instantly.
However, if it has not interrupted the beam after some longer time, you must
wake up because something is wrong.
Probably the best way to support this sort of thing in Python itself
is with OS-specific blocks for cases which are easy to do and fall
back to the current implementation in others. But as has been posted
here before, that needs someone to make, test and then propose the
changes.


I would ammend that to read, "fall back on an improvement of the current
implementation, " but otherwise I agree.

A year ago I volunteered (on this group) to do the general work, and the
specific module for Windoze. I was told, "Just post your cute little code
to some free software repository somewhere." At least that's the way I felt
at the time. Of course, no one here knows "Jive" from Adam. There is a
tendency on the net to assume anyone you don't recognise is a clueless
newbie, and everything they post is naive blather. I've been cruising and
using the newsgroups under one name or another since the mid 80's.

So where was I before I went off into old fart mode? Oh yeah. It really
should go into the main Python distribution.
Jul 18 '05 #9
Jive wrote:
Here is a common example from my line of work: You set a piece of machinery
into motion. If everything is operating normally, it will reach a certain
point and interrupt a light beam. You must react to that event instantly.
"Instantly" is of course impossible, even with a language
faster than Python. You probably have some specific maximum
latency in mind. And maybe this is a hard realtime system
and maybe it's not.

Python, of course, is unsuitable for many hard realtime systems,
and if you're using Windows you are probably on the wrong platform
in the first place. (Just on Friday we were doing a little bit
of latency measurement in a similar situation. 97 times out of
100 the Python code on a fast WinXP machine was taking less than
the required 0.35 seconds to respond and finish its processing.
Once it took 0.37 seconds, once it took 0.85 seconds, and once
it took just over 1.0 seconds. Windows....)
A year ago I volunteered (on this group) to do the general work, and the
specific module for Windoze. I was told, "Just post your cute little code
to some free software repository somewhere." At least that's the way I felt
at the time. Of course, no one here knows "Jive" from Adam. There is a
tendency on the net to assume anyone you don't recognise is a clueless
newbie, and everything they post is naive blather. I've been cruising and
using the newsgroups under one name or another since the mid 80's.

So where was I before I went off into old fart mode? Oh yeah. It really
should go into the main Python distribution.


The bar for putting things in the main distribution should be
very, very high. One of the conditions for doing that should
probably be that the code is fairly widely used and widely
required. It's not apparent that this is yet the case.

Why not post it to an appropriate "recipe" page in the fledgling
Agile Control Forum site instead? (http://www.engcorp.com/acf)
That way others who *do* work in the machine control field will
have an early chance to try out your code, experiment, maybe
even improve it, fix bugs, and basically do some of the work that
*should* be done before anything gets into the main Python distro...

-Peter
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
10594
by: DanGo | last post by:
Hi All, I'm trying to get my head around synchronization. Documentation seems to say that creating a volatile field gives a memorybarrier. Great! But when I do a little performance testing Thread.MemoryBarrier is 40 times slower than accessing a volatile int. Also I don't see any significant difference between the time to increment a volatile int and a
4
1382
by: Rick Strahl [MVP] | last post by:
Hi all, I have an ASP.Net application that's online that's 'locking up' from time to time. It doesn't completely lock up but all of a sudden it appears to be stuck for about 20-30 seconds, before it catches and fires back up... The app doesn't restart itself (I'm logging this stuff) - it just starts working again. If there are multiple requests at that time they all are slow. They all go through, just at a glacial speed. I've checked...
5
4058
by: Bob Bins | last post by:
Is there a way to create a shared lock using the Monitor class or any other synchronization class in .NET? So I have one resource that may have multiple threads using it at once but a second thread that when called must have exclusive access and cause the other threads to wait. I can't figure out how to do this with .Net. Thanks.
4
5363
by: Ben | last post by:
Hello everybody I got confused by this problem for which I don't have a logical explanation. There is a Thread (ThreadA) which receives Events from another system thread (ThreadS). ThreadA then adds a time stamp to the received event and adds it to a event queue. This works well (therfore not shown here). The queue fills up. Then I used a timer to check every millisecond for new events in the queue and send it to another thread...
17
1997
by: djc | last post by:
I got great info on related question previously. This link <http://www.yoda.arachsys.com/csharp/threads/volatility.shtml> from Brian Gideon was especially informative. 1) the lock statement does *not* make the processor finish all code in the code block before giving another thread from your process a slice of processor time, it only makes sure other threads cannot run the same code *if* they also adhere to the same lock object....
190
8044
by: blangela | last post by:
If you had asked me 5 years ago about the future of C++, I would have told you that its future was assured for many years to come. Recently, I have been starting to wonder. I have been teaching C++ at a local polytechnical school here in Vancouver, Canada for approximately 8 years. Six years ago, at the height (or should I say volume?) of the internet bubble, I had 80+ students per semester in my C++ course. Now I am fortunate to have...
5
3022
by: Peted | last post by:
i have an mdi application with two child forms Childform A and childform B in a nutshell Childform B has a timer with a routine that polls a ip socket for information every 30sec.
94
30271
by: Samuel R. Neff | last post by:
When is it appropriate to use "volatile" keyword? The docs simply state: " The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock Statement (C# Reference) statement to serialize access. " But when is it better to use "volatile" instead of "lock" ?
12
4478
by: Zytan | last post by:
I have a Timer class set to trigger every second. The Tick function that is called every second uses a lock to prevent multiple ticks from executing the same code at the same time. The code within calls a Visual Basic input message box, which is synchronous, it waits until you enter some input, and press enter. But, this message box pops up every second regardless if the old ones have finished. The timer's Tick function is called over...
0
8312
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8827
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8504
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8606
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6169
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4159
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4318
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2732
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1622
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.