move to a thread event to fix race condition

The old conditional objects had a problem where the calling code was
notifyAll()ing before the helper threads had started waiting.
This commit is contained in:
Damien Elmes 2011-01-04 12:32:33 +09:00
parent 3a7f8fdc7a
commit d717be8849

View file

@ -122,7 +122,7 @@ else:
mplayerQueue = [] mplayerQueue = []
mplayerManager = None mplayerManager = None
mplayerReader = None mplayerReader = None
mplayerCond = threading.Condition() mplayerEvt = threading.Event()
mplayerClear = False mplayerClear = False
class MplayerReader(threading.Thread): class MplayerReader(threading.Thread):
@ -130,9 +130,7 @@ class MplayerReader(threading.Thread):
def run(self): def run(self):
while 1: while 1:
mplayerCond.acquire() mplayerEvt.wait()
mplayerCond.wait()
mplayerCond.release()
try: try:
mplayerManager.mplayer.stdout.read() mplayerManager.mplayer.stdout.read()
except: except:
@ -145,8 +143,7 @@ class MplayerMonitor(threading.Thread):
self.mplayer = None self.mplayer = None
self.deadPlayers = [] self.deadPlayers = []
while 1: while 1:
mplayerCond.acquire() mplayerEvt.wait()
mplayerCond.wait()
if mplayerQueue: if mplayerQueue:
# ensure started # ensure started
if not self.mplayer: if not self.mplayer:
@ -170,7 +167,7 @@ class MplayerMonitor(threading.Thread):
else: else:
return True return True
self.deadPlayers = [pl for pl in self.deadPlayers if clean(pl)] self.deadPlayers = [pl for pl in self.deadPlayers if clean(pl)]
mplayerCond.release() mplayerEvt.clear()
def kill(self): def kill(self):
if not self.mplayer: if not self.mplayer:
@ -189,24 +186,22 @@ class MplayerMonitor(threading.Thread):
cmd, startupinfo=si, stdin=subprocess.PIPE, cmd, startupinfo=si, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError: except OSError:
mplayerCond.release() mplayerEvt.clear()
raise Exception("Audio player not found") raise Exception("Audio player not found")
def queueMplayer(path): def queueMplayer(path):
ensureMplayerThreads() ensureMplayerThreads()
while mplayerEvt.isSet():
time.sleep(0.1)
path = path.encode(sys.getfilesystemencoding()) path = path.encode(sys.getfilesystemencoding())
mplayerCond.acquire()
mplayerQueue.append(path) mplayerQueue.append(path)
mplayerCond.notifyAll() mplayerEvt.set()
mplayerCond.release()
runHook("soundQueued") runHook("soundQueued")
def clearMplayerQueue(): def clearMplayerQueue():
global mplayerClear global mplayerClear
mplayerCond.acquire()
mplayerClear = True mplayerClear = True
mplayerCond.notifyAll() mplayerEvt.set()
mplayerCond.release()
def ensureMplayerThreads(): def ensureMplayerThreads():
global mplayerManager, mplayerReader global mplayerManager, mplayerReader