[Tutor] Changing instance attributes in different threads
Michael Lange
klappnase at freenet.de
Wed Feb 8 12:17:33 CET 2006
On Tue, 7 Feb 2006 23:31:06 +0100
Michael Lange <klappnase at freenet.de> wrote:
>
> So I think I need two Condition objects here; it is most important here that thread 1 does not
> block to minimize the risk of recording buffer overruns, but from reading the docs I am
> not sure about the correct procedure. So if I change self.rec_locked and self.vu_locked from the
> code above to be Condition objects is it correct to do:
>
<snip>
Ok, some testing gave me the answer, with the code I posted I got an AssertionError, so obviously
the release() call has to be inside the "if self.rec_lock.acquire(blocking=0):" block.
So now my functions look like:
gui thread (periodically called by Tkinter):
def get_peaks(self):
if not self.vu_lock.acquire(blocking=0):
return None
data = [x for x in self.vubuffer]
self.vubuffer = []
self.vu_lock.release()
if not data:
return None
left, right = 0, 0
for d in data:
left = max(audioop.max(audioop.tomono(d, 2, 1, 0), 2), left)
right = max(audioop.max(audioop.tomono(d, 2, 0, 1), 2), right)
return left, right
child thread 1:
vubuffer = []
recbuffer = []
while self.running:
data = self._audioobj.read(self._fragsize)# read data from soundcard
vubuffer.append(data)
if self.vu_lock.acquire(blocking=0):
self.vubuffer += vubuffer
vubuffer = []
self.vu_lock.release()
if self.recording:
recbuffer.append(data)
if self.rec_lock.acquire(blocking=0):
self.recbuffer += recbuffer
recbuffer = []
self.rec_lock.release()
child thread 2:
while self.recording:
# wait a moment until there is something in the buffer to be written
data = []
time.sleep(0.1)
if self.rec_lock.acquire(blocking=0):
data = [x for x in self.recbuffer]
self.recbuffer = []
self.rec_lock.release()
for d in data:
self._waveobj.writeframesraw(d)# write data to file
This *seems* to work, however it looks like this code does not separate properly the gui from the child
threads which everyone says should be avoided in any case.
On the other hand, with the technique I used before, with a boolean as "lock", like:
if not self.vu_locked:
self.vu_locked = 1
self.vubuffer += vubuffer
vubuffer = []
self.vu_locked = 0
it seems like the worst case is that both the gui and the child thread pass the test "if not self.vu_locked" at
the same time which might cause some data to be lost from the vubuffer list; probably that is something
I could live with.
So now my question:
Does anyone know how a threading.Condition() object is handled internally, so maybe its methods actually
can be called safely from the gui thread?
Thanks
Michael
More information about the Tutor
mailing list