Browse Source

disable Toontown's cheesy lock for normal, threaded Panda

David Rose 14 years ago
parent
commit
ea05496d09
1 changed files with 67 additions and 58 deletions
  1. 67 58
      direct/src/showbase/Messenger.py

+ 67 - 58
direct/src/showbase/Messenger.py

@@ -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
-# hack.
-#from direct.stdpy.threading import Lock
+from libpandaexpress import ConfigVariableBool
+
+# If using the Toontown ActiveX launcher, this must be set true.
+# Also, Panda must be compiled with SIMPLE_THREADS or no HAVE_THREADS
+# at all.  In the normal Panda case, this should be set false.
+if ConfigVariableBool('delay-messenger-lock', False).getValue():
+    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")
+
+        def __init__(self):
+            self.locked = 0
+
+        def acquire(self):
+            # Before we download Panda, we can't use any threading
+            # interfaces.  So don't, until we observe that we have some
+            # actual contention on the lock.
+
+            if self.locked:
+                # We have contention.
+                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):
+            if self.locked:
+                # Still using the old, cheesy lock.
+                self.locked -= 1
+                return
 
 
-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.  This is a TEMPORARY
-    HACK, to be removed when the ActiveX launch is retired. """
+            # The new lock must have been put in place.
+            self.release = self.lock.release
+            return self.lock.release()
 
 
-    notify = DirectNotifyGlobal.directNotify.newCategory("Messenger.Lock")
+        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.
 
 
-    def __init__(self):
-        self.locked = 0
-
-    def acquire(self):
-        # Before we download Panda, we can't use any threading
-        # interfaces.  So don't, until we observe that we have some
-        # actual contention on the lock.
-
-        if self.locked:
-            # We have contention.
-            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):
-        if self.locked:
-            # Still using the old, cheesy lock.
-            self.locked -= 1
-            return
-
-        # The new lock must have been put in place.
-        self.release = self.lock.release
-        return self.lock.release()
-
-    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.
-
-        self.notify.info("Acquiring Panda lock for the first time.")
-
-        from pandac.PandaModules import Thread, Mutex
-        self.__dict__.setdefault('lock', Mutex('Messenger'))
-        self.lock.acquire()
-        
-        self.acquire = self.lock.acquire
+            self.notify.info("Acquiring Panda lock for the first time.")
+
+            from pandac.PandaModules import Thread, Mutex
+            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.
-        self.notify.info("Waiting for cheesy lock to be released.")
-        while self.locked:
-            Thread.forceYield()
-        self.notify.info("Got cheesy lock.")
+            # 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.
-            
+            # 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: