disable Toontown's cheesy lock for normal, threaded Panda

This commit is contained in:
David Rose 2012-01-06 00:51:54 +00:00
parent 211df4b90f
commit ea05496d09

View File

@ -7,69 +7,78 @@ from PythonUtil import *
from direct.directnotify import DirectNotifyGlobal from direct.directnotify import DirectNotifyGlobal
import types import types
# This one line will replace the cheesy hack below, when we remove the from libpandaexpress import ConfigVariableBool
# hack.
#from direct.stdpy.threading import Lock
class Lock: # If using the Toontown ActiveX launcher, this must be set true.
""" This is a cheesy delayed implementation of Lock, designed to # Also, Panda must be compiled with SIMPLE_THREADS or no HAVE_THREADS
support the Toontown ActiveX launch, which must import Messenger # at all. In the normal Panda case, this should be set false.
before it has downloaded the rest of Panda. This is a TEMPORARY if ConfigVariableBool('delay-messenger-lock', False).getValue():
HACK, to be removed when the ActiveX launch is retired. """ class Lock:
""" This is a cheesy delayed implementation of Lock, designed to
support the Toontown ActiveX launch, which must import Messenger
before it has downloaded the rest of Panda. Note that this
cheesy lock isn't thread-safe if the application starts any
threads before acquiring the Messenger lock the first time.
(However, it's mostly thread-safe if Panda is compiled with
SIMPLE_THREADS.) """
notify = DirectNotifyGlobal.directNotify.newCategory("Messenger.Lock") notify = DirectNotifyGlobal.directNotify.newCategory("Messenger.Lock")
def __init__(self): def __init__(self):
self.locked = 0 self.locked = 0
def acquire(self): def acquire(self):
# Before we download Panda, we can't use any threading # Before we download Panda, we can't use any threading
# interfaces. So don't, until we observe that we have some # interfaces. So don't, until we observe that we have some
# actual contention on the lock. # actual contention on the lock.
if self.locked: if self.locked:
# We have contention. # We have contention.
return self.__getLock() return self.__getLock()
# This relies on the fact that any individual Python statement
# is atomic.
self.locked += 1
if self.locked > 1:
# Whoops, we have contention.
self.locked -= 1
return self.__getLock()
def release(self): # This relies on the fact that any individual Python statement
if self.locked: # is atomic.
# Still using the old, cheesy lock. self.locked += 1
self.locked -= 1 if self.locked > 1:
return # Whoops, we have contention.
self.locked -= 1
return self.__getLock()
# The new lock must have been put in place. def release(self):
self.release = self.lock.release if self.locked:
return self.lock.release() # Still using the old, cheesy lock.
self.locked -= 1
return
def __getLock(self): # The new lock must have been put in place.
# Now that we've started Panda, it's safe to import the Mutex self.release = self.lock.release
# class, which becomes our actual lock. return self.lock.release()
# From now on, this lock will be used.
self.notify.info("Acquiring Panda lock for the first time.") def __getLock(self):
# Now that we've started Panda, it's safe to import the Mutex
# class, which becomes our actual lock.
# From now on, this lock will be used.
from pandac.PandaModules import Thread, Mutex self.notify.info("Acquiring Panda lock for the first time.")
self.__dict__.setdefault('lock', Mutex('Messenger'))
self.lock.acquire()
self.acquire = self.lock.acquire
# Wait for the cheesy lock to be released before we return. from pandac.PandaModules import Thread, Mutex
self.notify.info("Waiting for cheesy lock to be released.") self.__dict__.setdefault('lock', Mutex('Messenger'))
while self.locked: self.lock.acquire()
Thread.forceYield()
self.notify.info("Got cheesy lock.")
# We return with the lock acquired. self.acquire = self.lock.acquire
# Wait for the cheesy lock to be released before we return.
self.notify.info("Waiting for cheesy lock to be released.")
while self.locked:
Thread.forceYield()
self.notify.info("Got cheesy lock.")
# We return with the lock acquired.
else:
# In the normal case, there's no reason not to import all of
# libpanda right away, and so we can just use Lock directly. This
# is perfectly thread-safe.
from direct.stdpy.threading import Lock
class Messenger: class Messenger: