mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
Dramatically reduce size of frozen/compiled code by pruning/masking unnecessary imports/code
This commit is contained in:
parent
591ce04ab1
commit
0d03207d1b
@ -41,7 +41,9 @@ only when debugging (i.e. when it won't be checked-in) or where it helps
|
||||
you resist using assert for error handling.
|
||||
"""
|
||||
|
||||
wantVerifyPdb = 0 # Set to true to load pdb on failure.
|
||||
from panda3d.core import ConfigVariableBool
|
||||
|
||||
wantVerifyPdb = ConfigVariableBool('want-verify-pdb', False) # Set to true to load pdb on failure.
|
||||
|
||||
|
||||
def verify(assertion):
|
||||
|
@ -12,7 +12,6 @@ from OnscreenImage import *
|
||||
from direct.directtools.DirectUtil import ROUND_TO
|
||||
from direct.showbase import DirectObject
|
||||
from direct.task import Task
|
||||
from direct.showbase.PythonUtil import recordCreationStackStr
|
||||
import types
|
||||
|
||||
guiObjectCollector = PStatCollector("Client::GuiObjects")
|
||||
@ -651,13 +650,6 @@ def toggleGuiGridSnap():
|
||||
def setGuiGridSpacing(spacing):
|
||||
DirectGuiWidget.gridSpacing = spacing
|
||||
|
||||
# this should trigger off of __dev__, but it's not available at this point.
|
||||
# __debug__ works because the production client is not __debug__ and the
|
||||
# production AI doesn't create any GUI.
|
||||
if get_config_showbase().GetBool('record-gui-creation-stack', __debug__):
|
||||
# this will help track down the code that created DirectGui objects
|
||||
# call obj.printCreationStackTrace() to figure out what code created it
|
||||
DirectGuiBase = recordCreationStackStr(DirectGuiBase)
|
||||
|
||||
class DirectGuiWidget(DirectGuiBase, NodePath):
|
||||
# Toggle if you wish widget's to snap to grid when draggin
|
||||
|
@ -72,13 +72,6 @@ class ProjectileInterval(Interval):
|
||||
self.projectileIntervalNum)
|
||||
ProjectileInterval.projectileIntervalNum += 1
|
||||
|
||||
"""
|
||||
# attempt to add info about the caller
|
||||
file, line, func = PythonUtil.callerInfo()
|
||||
if file is not None:
|
||||
name += '-%s:%s:%s' % (file, line, func)
|
||||
"""
|
||||
|
||||
args = (startPos, endPos, duration, startVel, endZ,
|
||||
wayPoint, timeToWayPoint, gravityMult)
|
||||
self.implicitStartPos = 0
|
||||
|
@ -1,4 +1,5 @@
|
||||
from panda3d.direct import get_config_showbase
|
||||
__all__ = ["install"]
|
||||
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.PythonUtil import fastRepr
|
||||
import sys
|
||||
@ -6,7 +7,6 @@ import types
|
||||
import traceback
|
||||
|
||||
notify = directNotify.newCategory("ExceptionVarDump")
|
||||
config = get_config_showbase()
|
||||
|
||||
reentry = 0
|
||||
|
||||
@ -187,7 +187,7 @@ def install(log, upload):
|
||||
wantStackDumpLog = log
|
||||
wantStackDumpUpload = upload
|
||||
|
||||
dumpOnExceptionInit = config.GetBool('variable-dump-on-exception-init', 0)
|
||||
dumpOnExceptionInit = ConfigVariableBool('variable-dump-on-exception-init', False)
|
||||
if dumpOnExceptionInit:
|
||||
# this mode doesn't completely work because exception objects
|
||||
# thrown by the interpreter don't get created until the
|
||||
|
@ -281,7 +281,7 @@ class GarbageReport(Job):
|
||||
if self._args.findCycles:
|
||||
s = ['===== GarbageReport: \'%s\' (%s %s) =====' % (
|
||||
self._args.name, self.numCycles,
|
||||
choice(self.numCycles == 1, 'cycle', 'cycles'))]
|
||||
('cycle' if self.numCycles == 1 else 'cycles'))]
|
||||
else:
|
||||
s = ['===== GarbageReport: \'%s\' =====' % (
|
||||
self._args.name)]
|
||||
@ -499,7 +499,7 @@ class GarbageReport(Job):
|
||||
rootId = index
|
||||
# check if the root object is one of the garbage instances (has __del__)
|
||||
objId = id(self.garbage[rootId])
|
||||
numDelInstances = choice(objId in self.garbageInstanceIds, 1, 0)
|
||||
numDelInstances = int(objId in self.garbageInstanceIds)
|
||||
stateStack.push(([rootId], rootId, numDelInstances, 0))
|
||||
while True:
|
||||
yield None
|
||||
@ -535,7 +535,7 @@ class GarbageReport(Job):
|
||||
elif refId is not None:
|
||||
# check if this object is one of the garbage instances (has __del__)
|
||||
objId = id(self.garbage[refId])
|
||||
numDelInstances += choice(objId in self.garbageInstanceIds, 1, 0)
|
||||
numDelInstances += int(objId in self.garbageInstanceIds)
|
||||
# this refId does not complete a cycle. Mark down
|
||||
# where we are in this list of referents, then
|
||||
# start looking through the referents of the new refId
|
||||
|
@ -5,7 +5,6 @@ __all__ = ['Diff', 'ObjectPool']
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.PythonUtil import invertDictLossless, makeList, safeRepr
|
||||
from direct.showbase.PythonUtil import getNumberedTypedString, getNumberedTypedSortedString
|
||||
from direct.showbase.PythonUtil import getNumberedTypedSortedStringWithReferrersGen
|
||||
import gc
|
||||
|
||||
class Diff:
|
||||
@ -97,7 +96,7 @@ class ObjectPool:
|
||||
s += '\n%s\t%s' % (count, typ)
|
||||
return s
|
||||
|
||||
def printObjsByType(self, printReferrers=False):
|
||||
def printObjsByType(self):
|
||||
print 'Object Pool: Objects By Type'
|
||||
print '\n============================'
|
||||
counts = list(set(self._count2types.keys()))
|
||||
@ -109,11 +108,7 @@ class ObjectPool:
|
||||
types = makeList(self._count2types[count])
|
||||
for typ in types:
|
||||
print 'TYPE: %s, %s objects' % (repr(typ), len(self._type2objs[typ]))
|
||||
if printReferrers:
|
||||
for line in getNumberedTypedSortedStringWithReferrersGen(self._type2objs[typ]):
|
||||
print line
|
||||
else:
|
||||
print getNumberedTypedSortedString(self._type2objs[typ])
|
||||
print getNumberedTypedSortedString(self._type2objs[typ])
|
||||
|
||||
def containerLenStr(self):
|
||||
s = 'Object Pool: Container Lengths'
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,24 +26,22 @@ from BulletinBoardGlobal import bulletinBoard
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from JobManagerGlobal import jobMgr
|
||||
from EventManagerGlobal import eventMgr
|
||||
from PythonUtil import *
|
||||
from direct.showbase import PythonUtil
|
||||
#from direct.interval.IntervalManager import ivalMgr
|
||||
#from PythonUtil import *
|
||||
from direct.interval import IntervalManager
|
||||
from direct.showbase.BufferViewer import BufferViewer
|
||||
from direct.task import Task
|
||||
from direct.directutil import Verify
|
||||
from direct.showbase import GarbageReport
|
||||
import sys
|
||||
import Loader
|
||||
import time
|
||||
import atexit
|
||||
import importlib
|
||||
from direct.showbase import ExceptionVarDump
|
||||
import DirectObject
|
||||
import SfxPlayer
|
||||
if __debug__:
|
||||
from direct.showbase import GarbageReport
|
||||
from direct.directutil import DeltaProfiler
|
||||
import OnScreenDebug
|
||||
import OnScreenDebug
|
||||
import AppRunnerGlobal
|
||||
|
||||
def legacyRun():
|
||||
@ -73,7 +71,8 @@ class ShowBase(DirectObject.DirectObject):
|
||||
if logStackDump or uploadStackDump:
|
||||
ExceptionVarDump.install(logStackDump, uploadStackDump)
|
||||
|
||||
self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False)
|
||||
if __debug__:
|
||||
self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False)
|
||||
|
||||
## The directory containing the main Python file of this application.
|
||||
self.mainDir = ExecutionEnvironment.getEnvironmentVariable("MAIN_DIR")
|
||||
@ -88,9 +87,6 @@ class ShowBase(DirectObject.DirectObject):
|
||||
#debug running multiplier
|
||||
self.debugRunningMultiplier = 4
|
||||
|
||||
# Setup wantVerifyPdb as soon as reasonable:
|
||||
Verify.wantVerifyPdb = self.config.GetBool('want-verify-pdb', 0)
|
||||
|
||||
# [gjeon] to disable sticky keys
|
||||
if self.config.GetBool('disable-sticky-keys', 0):
|
||||
storeAccessibilityShortcutKeys()
|
||||
@ -373,8 +369,8 @@ class ShowBase(DirectObject.DirectObject):
|
||||
builtins.wantUberdog = self.config.GetBool('want-uberdog', 1)
|
||||
if __debug__:
|
||||
builtins.deltaProfiler = DeltaProfiler.DeltaProfiler("ShowBase")
|
||||
self.onScreenDebug = OnScreenDebug.OnScreenDebug()
|
||||
builtins.onScreenDebug = self.onScreenDebug
|
||||
self.onScreenDebug = OnScreenDebug.OnScreenDebug()
|
||||
builtins.onScreenDebug = self.onScreenDebug
|
||||
|
||||
if self.wantRender2dp:
|
||||
builtins.render2dp = self.render2dp
|
||||
@ -388,10 +384,6 @@ class ShowBase(DirectObject.DirectObject):
|
||||
|
||||
self.createBaseAudioManagers()
|
||||
|
||||
# set up recording of Functor creation stacks in __dev__
|
||||
if self.__dev__ and self.config.GetBool('record-functor-creation-stacks', False):
|
||||
PythonUtil.recordFunctorCreationStacks()
|
||||
|
||||
if self.__dev__ or self.config.GetBool('want-e3-hacks', False):
|
||||
if self.config.GetBool('track-gui-items', True):
|
||||
# dict of guiId to gui item, for tracking down leaks
|
||||
@ -465,7 +457,8 @@ class ShowBase(DirectObject.DirectObject):
|
||||
some Panda config settings. """
|
||||
|
||||
try:
|
||||
import profile, pstats
|
||||
profile = importlib.import_module('profile')
|
||||
pstats = importlib.import_module('pstats')
|
||||
except ImportError:
|
||||
return
|
||||
|
||||
@ -1647,23 +1640,26 @@ class ShowBase(DirectObject.DirectObject):
|
||||
|
||||
def addAngularIntegrator(self):
|
||||
if not self.physicsMgrAngular:
|
||||
from panda3d.physics import AngularEulerIntegrator
|
||||
physics = importlib.import_module('panda3d.physics')
|
||||
self.physicsMgrAngular = 1
|
||||
integrator = AngularEulerIntegrator()
|
||||
integrator = physics.AngularEulerIntegrator()
|
||||
self.physicsMgr.attachAngularIntegrator(integrator)
|
||||
|
||||
def enableParticles(self):
|
||||
if not self.particleMgrEnabled:
|
||||
# Use importlib to prevent this import from being picked up
|
||||
# by modulefinder when packaging an application.
|
||||
|
||||
if not self.particleMgr:
|
||||
from direct.particles.ParticleManagerGlobal import particleMgr
|
||||
self.particleMgr = particleMgr
|
||||
PMG = importlib.import_module('direct.particles.ParticleManagerGlobal')
|
||||
self.particleMgr = PMG.particleMgr
|
||||
self.particleMgr.setFrameStepping(1)
|
||||
|
||||
if not self.physicsMgr:
|
||||
from PhysicsManagerGlobal import physicsMgr
|
||||
from panda3d.physics import LinearEulerIntegrator
|
||||
self.physicsMgr = physicsMgr
|
||||
integrator = LinearEulerIntegrator()
|
||||
PMG = importlib.import_module('direct.showbase.PhysicsManagerGlobal')
|
||||
physics = importlib.import_module('panda3d.physics')
|
||||
self.physicsMgr = PMG.physicsMgr
|
||||
integrator = physics.LinearEulerIntegrator()
|
||||
self.physicsMgr.attachLinearIntegrator(integrator)
|
||||
|
||||
self.particleMgrEnabled = 1
|
||||
@ -1886,9 +1882,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
return Task.cont
|
||||
|
||||
def __igLoop(self, state):
|
||||
# We render the watch variables for the onScreenDebug as soon
|
||||
# as we reasonably can before the renderFrame().
|
||||
self.onScreenDebug.render()
|
||||
if __debug__:
|
||||
# We render the watch variables for the onScreenDebug as soon
|
||||
# as we reasonably can before the renderFrame().
|
||||
self.onScreenDebug.render()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.recordFrame()
|
||||
@ -1900,9 +1897,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
if self.multiClientSleep:
|
||||
time.sleep(0)
|
||||
|
||||
# We clear the text buffer for the onScreenDebug as soon
|
||||
# as we reasonably can after the renderFrame().
|
||||
self.onScreenDebug.clear()
|
||||
if __debug__:
|
||||
# We clear the text buffer for the onScreenDebug as soon
|
||||
# as we reasonably can after the renderFrame().
|
||||
self.onScreenDebug.clear()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.playFrame()
|
||||
@ -1925,9 +1923,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
|
||||
|
||||
def __igLoopSync(self, state):
|
||||
# We render the watch variables for the onScreenDebug as soon
|
||||
# as we reasonably can before the renderFrame().
|
||||
self.onScreenDebug.render()
|
||||
if __debug__:
|
||||
# We render the watch variables for the onScreenDebug as soon
|
||||
# as we reasonably can before the renderFrame().
|
||||
self.onScreenDebug.render()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.recordFrame()
|
||||
@ -1941,9 +1940,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
if self.multiClientSleep:
|
||||
time.sleep(0)
|
||||
|
||||
# We clear the text buffer for the onScreenDebug as soon
|
||||
# as we reasonably can after the renderFrame().
|
||||
self.onScreenDebug.clear()
|
||||
if __debug__:
|
||||
# We clear the text buffer for the onScreenDebug as soon
|
||||
# as we reasonably can after the renderFrame().
|
||||
self.onScreenDebug.clear()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.playFrame()
|
||||
@ -2178,8 +2178,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
self.texmem = None
|
||||
return
|
||||
|
||||
from direct.showutil.TexMemWatcher import TexMemWatcher
|
||||
self.texmem = TexMemWatcher()
|
||||
# Use importlib to prevent this import from being picked up
|
||||
# by modulefinder when packaging an application.
|
||||
TMW = importlib.import_module('direct.showutil.TexMemWatcher')
|
||||
self.texmem = TMW.TexMemWatcher()
|
||||
|
||||
def toggleShowVertices(self):
|
||||
""" Toggles a mode that visualizes vertex density per screen
|
||||
@ -2675,16 +2677,18 @@ class ShowBase(DirectObject.DirectObject):
|
||||
if not properties.getOpen():
|
||||
# If the user closes the main window, we should exit.
|
||||
self.notify.info("User closed main window.")
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
if __debug__:
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
self.userExit()
|
||||
|
||||
if properties.getForeground() and not self.mainWinForeground:
|
||||
self.mainWinForeground = 1
|
||||
elif not properties.getForeground() and self.mainWinForeground:
|
||||
self.mainWinForeground = 0
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
if __debug__:
|
||||
if self.__autoGarbageLogging:
|
||||
GarbageReport.b_checkForGarbageLeaks()
|
||||
|
||||
if properties.getMinimized() and not self.mainWinMinimized:
|
||||
# If the main window is minimized, throw an event to
|
||||
@ -2814,7 +2818,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
|
||||
init_app_for_gui()
|
||||
|
||||
import wx
|
||||
# Use importlib to prevent this import from being picked up
|
||||
# by modulefinder when packaging an application.
|
||||
wx = importlib.import_module('wx')
|
||||
|
||||
# Create a new base.wxApp.
|
||||
self.wxApp = wx.PySimpleApp(redirect = False)
|
||||
|
||||
@ -2889,8 +2896,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
# Don't do this twice.
|
||||
return
|
||||
|
||||
from Tkinter import tkinter
|
||||
import Pmw
|
||||
# Use importlib to prevent this import from being picked up
|
||||
# by modulefinder when packaging an application.
|
||||
tkinter = importlib.import_module('Tkinter').tkinter
|
||||
Pmw = importlib.import_module('Pmw')
|
||||
|
||||
# Create a new Tk root.
|
||||
self.tkRoot = Pmw.initialise()
|
||||
@ -2953,8 +2962,10 @@ class ShowBase(DirectObject.DirectObject):
|
||||
self.startWx(fWantWx)
|
||||
self.wantDirect = fWantDirect
|
||||
if self.wantDirect:
|
||||
from direct.directtools.DirectSession import DirectSession
|
||||
self.direct = DirectSession()
|
||||
# Use importlib to prevent this import from being picked up
|
||||
# by modulefinder when packaging an application.
|
||||
DirectSession = importlib.import_module('direct.directtools.DirectSession')
|
||||
self.direct = DirectSession.DirectSession()
|
||||
self.direct.enable()
|
||||
builtins.direct = self.direct
|
||||
else:
|
||||
|
@ -3,7 +3,7 @@
|
||||
__all__ = ['Transitions']
|
||||
|
||||
from panda3d.core import *
|
||||
from direct.gui.DirectGui import *
|
||||
from direct.gui.DirectGui import DirectFrame
|
||||
from direct.gui import DirectGuiGlobals as DGG
|
||||
from direct.interval.LerpInterval import LerpColorScaleInterval, LerpColorInterval, LerpScaleInterval, LerpPosInterval
|
||||
from direct.interval.MetaInterval import Sequence, Parallel
|
||||
|
@ -30,8 +30,8 @@ isDebugBuild = (python.lower().endswith('_d'))
|
||||
# These are modules that Python always tries to import up-front. They
|
||||
# must be frozen in any main.exe.
|
||||
startupModules = [
|
||||
'site', 'sitecustomize', 'os', 'encodings.cp1252',
|
||||
'encodings.latin_1', 'encodings.utf_8', 'io', 'org',
|
||||
'os', 'encodings.cp1252',
|
||||
'encodings.latin_1', 'encodings.utf_8', 'io',
|
||||
]
|
||||
|
||||
# These are missing modules that we've reported already this session.
|
||||
|
@ -70,6 +70,13 @@ class LockType:
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
# Helper to generate new thread names
|
||||
_counter = 0
|
||||
def _newname(template="Thread-%d"):
|
||||
global _counter
|
||||
_counter = _counter + 1
|
||||
return template % _counter
|
||||
|
||||
_threads = {}
|
||||
_nextThreadId = 0
|
||||
_threadsLock = core.Mutex('thread._threadsLock')
|
||||
|
@ -42,6 +42,7 @@ __all__ = [
|
||||
]
|
||||
|
||||
local = _thread._local
|
||||
_newname = _thread._newname
|
||||
|
||||
class ThreadBase:
|
||||
""" A base class for both Thread and ExternalThread in this
|
||||
@ -98,8 +99,7 @@ class Thread(ThreadBase):
|
||||
self.__kwargs = kwargs
|
||||
|
||||
if not name:
|
||||
import threading2
|
||||
name = threading2._newname()
|
||||
name = _newname()
|
||||
|
||||
current = current_thread()
|
||||
self.__dict__['daemon'] = current.daemon
|
||||
@ -404,106 +404,107 @@ def setprofile(func):
|
||||
def stack_size(size = None):
|
||||
raise ThreadError
|
||||
|
||||
def _test():
|
||||
if __debug__:
|
||||
def _test():
|
||||
from collections import deque
|
||||
|
||||
from collections import deque
|
||||
_sleep = core.Thread.sleep
|
||||
_sleep = core.Thread.sleep
|
||||
|
||||
_VERBOSE = False
|
||||
_VERBOSE = False
|
||||
|
||||
class _Verbose(object):
|
||||
class _Verbose(object):
|
||||
|
||||
def __init__(self, verbose=None):
|
||||
if verbose is None:
|
||||
verbose = _VERBOSE
|
||||
self.__verbose = verbose
|
||||
def __init__(self, verbose=None):
|
||||
if verbose is None:
|
||||
verbose = _VERBOSE
|
||||
self.__verbose = verbose
|
||||
|
||||
def _note(self, format, *args):
|
||||
if self.__verbose:
|
||||
format = format % args
|
||||
format = "%s: %s\n" % (
|
||||
currentThread().getName(), format)
|
||||
_sys.stderr.write(format)
|
||||
def _note(self, format, *args):
|
||||
if self.__verbose:
|
||||
format = format % args
|
||||
format = "%s: %s\n" % (
|
||||
currentThread().getName(), format)
|
||||
_sys.stderr.write(format)
|
||||
|
||||
class BoundedQueue(_Verbose):
|
||||
class BoundedQueue(_Verbose):
|
||||
|
||||
def __init__(self, limit):
|
||||
_Verbose.__init__(self)
|
||||
self.mon = Lock(name = "BoundedQueue.mon")
|
||||
self.rc = Condition(self.mon)
|
||||
self.wc = Condition(self.mon)
|
||||
self.limit = limit
|
||||
self.queue = deque()
|
||||
def __init__(self, limit):
|
||||
_Verbose.__init__(self)
|
||||
self.mon = Lock(name = "BoundedQueue.mon")
|
||||
self.rc = Condition(self.mon)
|
||||
self.wc = Condition(self.mon)
|
||||
self.limit = limit
|
||||
self.queue = deque()
|
||||
|
||||
def put(self, item):
|
||||
self.mon.acquire()
|
||||
while len(self.queue) >= self.limit:
|
||||
self._note("put(%s): queue full", item)
|
||||
self.wc.wait()
|
||||
self.queue.append(item)
|
||||
self._note("put(%s): appended, length now %d",
|
||||
item, len(self.queue))
|
||||
self.rc.notify()
|
||||
self.mon.release()
|
||||
def put(self, item):
|
||||
self.mon.acquire()
|
||||
while len(self.queue) >= self.limit:
|
||||
self._note("put(%s): queue full", item)
|
||||
self.wc.wait()
|
||||
self.queue.append(item)
|
||||
self._note("put(%s): appended, length now %d",
|
||||
item, len(self.queue))
|
||||
self.rc.notify()
|
||||
self.mon.release()
|
||||
|
||||
def get(self):
|
||||
self.mon.acquire()
|
||||
while not self.queue:
|
||||
self._note("get(): queue empty")
|
||||
self.rc.wait()
|
||||
item = self.queue.popleft()
|
||||
self._note("get(): got %s, %d left", item, len(self.queue))
|
||||
self.wc.notify()
|
||||
self.mon.release()
|
||||
return item
|
||||
def get(self):
|
||||
self.mon.acquire()
|
||||
while not self.queue:
|
||||
self._note("get(): queue empty")
|
||||
self.rc.wait()
|
||||
item = self.queue.popleft()
|
||||
self._note("get(): got %s, %d left", item, len(self.queue))
|
||||
self.wc.notify()
|
||||
self.mon.release()
|
||||
return item
|
||||
|
||||
class ProducerThread(Thread):
|
||||
class ProducerThread(Thread):
|
||||
|
||||
def __init__(self, queue, quota):
|
||||
Thread.__init__(self, name="Producer")
|
||||
self.queue = queue
|
||||
self.quota = quota
|
||||
def __init__(self, queue, quota):
|
||||
Thread.__init__(self, name="Producer")
|
||||
self.queue = queue
|
||||
self.quota = quota
|
||||
|
||||
def run(self):
|
||||
from random import random
|
||||
counter = 0
|
||||
while counter < self.quota:
|
||||
counter = counter + 1
|
||||
self.queue.put("%s.%d" % (self.getName(), counter))
|
||||
_sleep(random() * 0.00001)
|
||||
def run(self):
|
||||
from random import random
|
||||
counter = 0
|
||||
while counter < self.quota:
|
||||
counter = counter + 1
|
||||
self.queue.put("%s.%d" % (self.getName(), counter))
|
||||
_sleep(random() * 0.00001)
|
||||
|
||||
|
||||
class ConsumerThread(Thread):
|
||||
class ConsumerThread(Thread):
|
||||
|
||||
def __init__(self, queue, count):
|
||||
Thread.__init__(self, name="Consumer")
|
||||
self.queue = queue
|
||||
self.count = count
|
||||
def __init__(self, queue, count):
|
||||
Thread.__init__(self, name="Consumer")
|
||||
self.queue = queue
|
||||
self.count = count
|
||||
|
||||
def run(self):
|
||||
while self.count > 0:
|
||||
item = self.queue.get()
|
||||
print item
|
||||
self.count = self.count - 1
|
||||
def run(self):
|
||||
while self.count > 0:
|
||||
item = self.queue.get()
|
||||
print item
|
||||
self.count = self.count - 1
|
||||
|
||||
NP = 3
|
||||
QL = 4
|
||||
NI = 5
|
||||
NP = 3
|
||||
QL = 4
|
||||
NI = 5
|
||||
|
||||
Q = BoundedQueue(QL)
|
||||
P = []
|
||||
for i in range(NP):
|
||||
t = ProducerThread(Q, NI)
|
||||
t.setName("Producer-%d" % (i+1))
|
||||
P.append(t)
|
||||
C = ConsumerThread(Q, NI*NP)
|
||||
for t in P:
|
||||
t.start()
|
||||
_sleep(0.000001)
|
||||
C.start()
|
||||
for t in P:
|
||||
t.join()
|
||||
C.join()
|
||||
Q = BoundedQueue(QL)
|
||||
P = []
|
||||
for i in range(NP):
|
||||
t = ProducerThread(Q, NI)
|
||||
t.setName("Producer-%d" % (i+1))
|
||||
P.append(t)
|
||||
C = ConsumerThread(Q, NI*NP)
|
||||
for t in P:
|
||||
t.start()
|
||||
_sleep(0.000001)
|
||||
C.start()
|
||||
for t in P:
|
||||
t.join()
|
||||
C.join()
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
|
@ -16,13 +16,12 @@ implementation. """
|
||||
import sys as _sys
|
||||
|
||||
from direct.stdpy import thread
|
||||
from direct.stdpy.thread import stack_size, _local as local
|
||||
from direct.stdpy.thread import stack_size, _newname, _local as local
|
||||
from panda3d import core
|
||||
_sleep = core.Thread.sleep
|
||||
|
||||
from time import time as _time
|
||||
from traceback import format_exc as _format_exc
|
||||
from collections import deque
|
||||
|
||||
# Rename some stuff so "from threading import *" is safe
|
||||
__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
|
||||
@ -377,13 +376,6 @@ class _Event(_Verbose):
|
||||
finally:
|
||||
self.__cond.release()
|
||||
|
||||
# Helper to generate new thread names
|
||||
_counter = 0
|
||||
def _newname(template="Thread-%d"):
|
||||
global _counter
|
||||
_counter = _counter + 1
|
||||
return template % _counter
|
||||
|
||||
# Active thread administration
|
||||
_active_limbo_lock = _allocate_lock()
|
||||
_active = {} # maps thread id to Thread object
|
||||
@ -741,88 +733,89 @@ _shutdown = _MainThread()._exitfunc
|
||||
|
||||
|
||||
# Self-test code
|
||||
if __debug__:
|
||||
def _test():
|
||||
from collections import deque
|
||||
|
||||
def _test():
|
||||
class BoundedQueue(_Verbose):
|
||||
|
||||
class BoundedQueue(_Verbose):
|
||||
def __init__(self, limit):
|
||||
_Verbose.__init__(self)
|
||||
self.mon = RLock()
|
||||
self.rc = Condition(self.mon)
|
||||
self.wc = Condition(self.mon)
|
||||
self.limit = limit
|
||||
self.queue = deque()
|
||||
|
||||
def __init__(self, limit):
|
||||
_Verbose.__init__(self)
|
||||
self.mon = RLock()
|
||||
self.rc = Condition(self.mon)
|
||||
self.wc = Condition(self.mon)
|
||||
self.limit = limit
|
||||
self.queue = deque()
|
||||
def put(self, item):
|
||||
self.mon.acquire()
|
||||
while len(self.queue) >= self.limit:
|
||||
self._note("put(%s): queue full", item)
|
||||
self.wc.wait()
|
||||
self.queue.append(item)
|
||||
self._note("put(%s): appended, length now %d",
|
||||
item, len(self.queue))
|
||||
self.rc.notify()
|
||||
self.mon.release()
|
||||
|
||||
def put(self, item):
|
||||
self.mon.acquire()
|
||||
while len(self.queue) >= self.limit:
|
||||
self._note("put(%s): queue full", item)
|
||||
self.wc.wait()
|
||||
self.queue.append(item)
|
||||
self._note("put(%s): appended, length now %d",
|
||||
item, len(self.queue))
|
||||
self.rc.notify()
|
||||
self.mon.release()
|
||||
def get(self):
|
||||
self.mon.acquire()
|
||||
while not self.queue:
|
||||
self._note("get(): queue empty")
|
||||
self.rc.wait()
|
||||
item = self.queue.popleft()
|
||||
self._note("get(): got %s, %d left", item, len(self.queue))
|
||||
self.wc.notify()
|
||||
self.mon.release()
|
||||
return item
|
||||
|
||||
def get(self):
|
||||
self.mon.acquire()
|
||||
while not self.queue:
|
||||
self._note("get(): queue empty")
|
||||
self.rc.wait()
|
||||
item = self.queue.popleft()
|
||||
self._note("get(): got %s, %d left", item, len(self.queue))
|
||||
self.wc.notify()
|
||||
self.mon.release()
|
||||
return item
|
||||
class ProducerThread(Thread):
|
||||
|
||||
class ProducerThread(Thread):
|
||||
def __init__(self, queue, quota):
|
||||
Thread.__init__(self, name="Producer")
|
||||
self.queue = queue
|
||||
self.quota = quota
|
||||
|
||||
def __init__(self, queue, quota):
|
||||
Thread.__init__(self, name="Producer")
|
||||
self.queue = queue
|
||||
self.quota = quota
|
||||
|
||||
def run(self):
|
||||
from random import random
|
||||
counter = 0
|
||||
while counter < self.quota:
|
||||
counter = counter + 1
|
||||
self.queue.put("%s.%d" % (self.getName(), counter))
|
||||
_sleep(random() * 0.00001)
|
||||
def run(self):
|
||||
from random import random
|
||||
counter = 0
|
||||
while counter < self.quota:
|
||||
counter = counter + 1
|
||||
self.queue.put("%s.%d" % (self.getName(), counter))
|
||||
_sleep(random() * 0.00001)
|
||||
|
||||
|
||||
class ConsumerThread(Thread):
|
||||
class ConsumerThread(Thread):
|
||||
|
||||
def __init__(self, queue, count):
|
||||
Thread.__init__(self, name="Consumer")
|
||||
self.queue = queue
|
||||
self.count = count
|
||||
def __init__(self, queue, count):
|
||||
Thread.__init__(self, name="Consumer")
|
||||
self.queue = queue
|
||||
self.count = count
|
||||
|
||||
def run(self):
|
||||
while self.count > 0:
|
||||
item = self.queue.get()
|
||||
print item
|
||||
self.count = self.count - 1
|
||||
def run(self):
|
||||
while self.count > 0:
|
||||
item = self.queue.get()
|
||||
print item
|
||||
self.count = self.count - 1
|
||||
|
||||
NP = 3
|
||||
QL = 4
|
||||
NI = 5
|
||||
NP = 3
|
||||
QL = 4
|
||||
NI = 5
|
||||
|
||||
Q = BoundedQueue(QL)
|
||||
P = []
|
||||
for i in range(NP):
|
||||
t = ProducerThread(Q, NI)
|
||||
t.setName("Producer-%d" % (i+1))
|
||||
P.append(t)
|
||||
C = ConsumerThread(Q, NI*NP)
|
||||
for t in P:
|
||||
t.start()
|
||||
_sleep(0.000001)
|
||||
C.start()
|
||||
for t in P:
|
||||
t.join()
|
||||
C.join()
|
||||
Q = BoundedQueue(QL)
|
||||
P = []
|
||||
for i in range(NP):
|
||||
t = ProducerThread(Q, NI)
|
||||
t.setName("Producer-%d" % (i+1))
|
||||
P.append(t)
|
||||
C = ConsumerThread(Q, NI*NP)
|
||||
for t in P:
|
||||
t.start()
|
||||
_sleep(0.000001)
|
||||
C.start()
|
||||
for t in P:
|
||||
t.join()
|
||||
C.join()
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
|
@ -12,6 +12,7 @@ from direct.showbase.PythonUtil import *
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
import types
|
||||
import random
|
||||
import importlib
|
||||
|
||||
try:
|
||||
import signal
|
||||
@ -591,7 +592,6 @@ class TaskManager:
|
||||
def popupControls(self):
|
||||
# Don't use a regular import, to prevent ModuleFinder from picking
|
||||
# it up as a dependency when building a .p3d package.
|
||||
import importlib
|
||||
TaskManagerPanel = importlib.import_module('direct.tkpanels.TaskManagerPanel')
|
||||
return TaskManagerPanel.TaskManagerPanel(self)
|
||||
|
||||
@ -602,8 +602,8 @@ class TaskManager:
|
||||
|
||||
# Defer this import until we need it: some Python
|
||||
# distributions don't provide the profile and pstats modules.
|
||||
from direct.showbase.ProfileSession import ProfileSession
|
||||
return ProfileSession(name)
|
||||
PS = importlib.import_module('direct.showbase.ProfileSession')
|
||||
return PS.ProfileSession(name)
|
||||
|
||||
def profileFrames(self, num=None, session=None, callback=None):
|
||||
if num is None:
|
||||
@ -629,8 +629,8 @@ class TaskManager:
|
||||
self._profileFrames.set(profileFrames)
|
||||
if (not self._frameProfiler) and profileFrames:
|
||||
# import here due to import dependencies
|
||||
from direct.task.FrameProfiler import FrameProfiler
|
||||
self._frameProfiler = FrameProfiler()
|
||||
FP = importlib.import_module('direct.task.FrameProfiler')
|
||||
self._frameProfiler = FP.FrameProfiler()
|
||||
|
||||
def getProfileTasks(self):
|
||||
return self._profileTasks.get()
|
||||
@ -642,8 +642,8 @@ class TaskManager:
|
||||
self._profileTasks.set(profileTasks)
|
||||
if (not self._taskProfiler) and profileTasks:
|
||||
# import here due to import dependencies
|
||||
from direct.task.TaskProfiler import TaskProfiler
|
||||
self._taskProfiler = TaskProfiler()
|
||||
TP = importlib.import_module('direct.task.TaskProfiler')
|
||||
self._taskProfiler = TP.TaskProfiler()
|
||||
|
||||
def logTaskProfiles(self, name=None):
|
||||
if self._taskProfiler:
|
||||
@ -689,9 +689,9 @@ class TaskManager:
|
||||
|
||||
# Defer this import until we need it: some Python
|
||||
# distributions don't provide the profile and pstats modules.
|
||||
from direct.showbase.ProfileSession import ProfileSession
|
||||
profileSession = ProfileSession('profiled-task-%s' % task.getName(),
|
||||
Functor(profileInfo.taskFunc, *profileInfo.taskArgs))
|
||||
PS = importlib.import_module('direct.showbase.ProfileSession')
|
||||
profileSession = PS.ProfileSession('profiled-task-%s' % task.getName(),
|
||||
Functor(profileInfo.taskFunc, *profileInfo.taskArgs))
|
||||
ret = profileSession.run()
|
||||
|
||||
# set these values *after* profiling in case we're profiling the TaskProfiler
|
||||
|
Loading…
x
Reference in New Issue
Block a user