from otp.ai.AIBase import * from direct.task import Task from direct.showbase import DirectObject import random class Barrier(DirectObject.DirectObject): notify = directNotify.newCategory('Barrier') def __init__(self, name, uniqueName, avIdList, timeout, clearedFunc = None, timeoutFunc = None, doneFunc = None): self.name = name self.uniqueName = uniqueName + '-Barrier' self.avIdList = avIdList[:] self.pendingAvatars = self.avIdList[:] self.timeout = timeout self.clearedFunc = clearedFunc self.timeoutFunc = timeoutFunc self.doneFunc = doneFunc if len(self.pendingAvatars) == 0: self.notify.debug('%s: barrier with empty list' % self.uniqueName) self.active = 0 if self.clearedFunc: self.clearedFunc() if self.doneFunc: self.doneFunc(self.avIdList) return self.taskName = self.uniqueName + '-Timeout' origTaskName = self.taskName while taskMgr.hasTaskNamed(self.taskName): self.taskName = origTaskName + '-' + str(random.randint(0, 10000)) taskMgr.doMethodLater(self.timeout, self.__timerExpired, self.taskName) for avId in self.avIdList: event = simbase.air.getAvatarExitEvent(avId) self.acceptOnce(event, self.__handleUnexpectedExit, extraArgs=[avId]) self.notify.debug('%s: expecting responses from %s within %s seconds' % (self.uniqueName, self.avIdList, self.timeout)) self.active = 1 def cleanup(self): if self.active: taskMgr.remove(self.taskName) self.active = 0 self.ignoreAll() def clear(self, avId): if avId not in self.pendingAvatars: self.notify.warning('%s: tried to clear %s, who was not listed.' % (self.uniqueName, avId)) return self.notify.debug('%s: clearing avatar %s' % (self.uniqueName, avId)) self.pendingAvatars.remove(avId) if len(self.pendingAvatars) == 0: self.notify.debug('%s: barrier cleared by %s' % (self.uniqueName, self.avIdList)) self.cleanup() if self.clearedFunc: self.clearedFunc() if self.doneFunc: self.doneFunc(self.avIdList) def isActive(self): return self.active def getPendingAvatars(self): return self.pendingAvatars[:] def __timerExpired(self, task): self.notify.warning('%s: timeout expired; responses not received from %s' % (self.uniqueName, self.pendingAvatars)) self.cleanup() if self.timeoutFunc: self.timeoutFunc(self.pendingAvatars[:]) if self.doneFunc: clearedAvIds = self.avIdList[:] for avId in self.pendingAvatars: clearedAvIds.remove(avId) self.doneFunc(clearedAvIds) return Task.done def __handleUnexpectedExit(self, avId): if avId not in self.avIdList: return self.avIdList.remove(avId) if avId in self.pendingAvatars: self.clear(avId)