def fbRemoveCallback(oSelf, sEventName, fCallback, bFireOnce=False, bIgnoreMissingEventNames=False): mDebugOutput_HideInCallStack = True # Errors are often easier to read if this function is left out of the stack. # Use "bIgnoreMissingEventNames" with caution: misspelled names may go unnoticed! if not oSelf.__fbCheckIsKnownEventName( sEventName, bIgnoreMissingEventNames=bIgnoreMissingEventNames): return False dafCallbacks_by_sEventName = oSelf.__dafCallbacks_by_sEventName if bFireOnce else oSelf.__dafFireOnceCallbacks_by_sEventName atfCallbacks = dafCallbacks_by_sEventName[sEventName] try: atfCallbacks.remove(fCallback) except ValueError: fShowDebugOutput( oSelf, "%sallback for %s not found: %s" % ("Fire-once c" if bFireOnce else "C", sEventName, repr(fCallback))) return False else: fShowDebugOutput( oSelf, "%sallback for %s removed: %s" % ("Fire-once c" if bFireOnce else "C", sEventName, repr(fCallback))) return True
def fAddEvents(oSelf, *asEventNames): mDebugOutput_HideInCallStack = True # Errors are often easier to read if this function is left out of the stack. # Might be called multiple times by sub-classes. if not hasattr(oSelf, "_cWithCallbacks__dafCallbacks_by_sEventName"): oSelf.__dafCallbacks_by_sEventName = {} oSelf.__dafFireOnceCallbacks_by_sEventName = {} for sEventName in asEventNames: assert sEventName not in oSelf.__dafCallbacks_by_sEventName, \ "The event %s appears to be defined twice" % repr(sEventName) oSelf.__dafCallbacks_by_sEventName[sEventName] = [] oSelf.__dafFireOnceCallbacks_by_sEventName[sEventName] = [] fShowDebugOutput(oSelf, "new events: %s" % ", ".join(asEventNames))
def fbFireCallbacks(oSelf, sEventName, *txArguments, **dxArguments): mDebugOutput_HideInCallStack = True # Errors are often easier to read if this function is left out of the stack. oSelf.__fbCheckIsKnownEventName(sEventName) atfFireOnceCallbacks = oSelf.__dafFireOnceCallbacks_by_sEventName[ sEventName] atfCallbacks = oSelf.__dafCallbacks_by_sEventName[ sEventName] + atfFireOnceCallbacks if not atfCallbacks: fShowDebugOutput( oSelf, "Event %s fired without callbacks for %s." % (sEventName, repr(oSelf))) return False fShowDebugOutput( oSelf, "Firing %s event with %d callbacks for %s." % (sEventName, len(atfCallbacks), repr(oSelf))) if txArguments or dxArguments: asArguments = ([repr(xArgument) for xArgument in txArguments] + [ "%s:%s" % (repr(xKey), repr(xValue)) for (xKey, xValue) in dxArguments.items() ]) fShowDebugOutput(oSelf, " Arguments: %s." % ", ".join(asArguments)) for fCallback in atfCallbacks: bFireOnce = fCallback in atfFireOnceCallbacks fShowDebugOutput( oSelf, " -> %s%s" % (repr(fCallback), " (fire once)" if bFireOnce else "")) fCallback(oSelf, *txArguments, **dxArguments) if bFireOnce: atfFireOnceCallbacks.remove(fCallback) return True
def fAddCallback(oSelf, sEventName, fCallback, bFireOnce=False, bIgnoreMissingEventNames=False): mDebugOutput_HideInCallStack = True # Errors are often easier to read if this function is left out of the stack. # Use "bIgnoreMissingEventNames" with caution: misspelled names may go unnoticed! if oSelf.__fbCheckIsKnownEventName( sEventName, bIgnoreMissingEventNames=bIgnoreMissingEventNames): dafCallbacks_by_sEventName = oSelf.__dafFireOnceCallbacks_by_sEventName if bFireOnce else oSelf.__dafCallbacks_by_sEventName dafCallbacks_by_sEventName[sEventName].append(fCallback) fShowDebugOutput( oSelf, "New callback for %s: %s%s" % (sEventName, repr(fCallback), " (fire once)" if bFireOnce else ""))
def fbWait(oSelf, nTimeoutInSeconds): assert isinstance(nTimeoutInSeconds, (int, float)) and nTimeoutInSeconds >= 0, \ "Invalid timeout value %s" % repr(nTimeoutInSeconds) # Wait for the lock to be unlocked by trying to lock it with a timeout. If we locked it, unlock it again. # Returns True of the lock was unlocked during the call. fShowDebugOutput("Waiting for %s up to %d seconds..." % (oSelf, nTimeoutInSeconds)) nEndTime = time.time() + nTimeoutInSeconds try: oSelf.__oQueuePutLock.put(0, True, nTimeoutInSeconds) try: nRemainingTimeoutInSeconds = nEndTime - time.time() if nRemainingTimeoutInSeconds < 0: fShowDebugOutput("Timeout") return False oSelf.__oQueue.put(0, True, float(nRemainingTimeoutInSeconds)) oSelf.__oQueue.get(False, 0) finally: oSelf.__oQueuePutLock.get(False, 0) except queue.Full: return False return True
def __fbAcquire(oSelf, xCallStackOrThreadId, nTimeoutInSeconds): mDebugOutput_HideInCallStack = True # Errors are often easier to read if this function is left out of the stack. if nTimeoutInSeconds is not None: assert isinstance(nTimeoutInSeconds, (int, float)) and nTimeoutInSeconds >=0, \ "Invalid timeout value %s" % repr(nTimeoutInSeconds) fShowDebugOutput("Attempting to lock %s for up to %f seconds..." % (oSelf, nTimeoutInSeconds)) else: fShowDebugOutput("Attempting to lock %s..." % oSelf) nEndTime = time.time() + nTimeoutInSeconds try: oSelf.__oQueuePutLock.put(0, nTimeoutInSeconds > 0, nTimeoutInSeconds) try: nRemainingTimeoutInSeconds = max(0, nEndTime - time.time()) try: oSelf.__oQueue.put(oSelf.__xLastAcquireCallStackOrThreadId, nRemainingTimeoutInSeconds > 0, nRemainingTimeoutInSeconds) except queue.Full: if nTimeoutInSeconds > 0: fShowDebugOutput( "Not acquired becuase waiting for locked to become unlocked timed out." ) else: fShowDebugOutput( "Not acquired because already locked.") return False oSelf.__xFinalReleaseCallStackOrThreadId = None oSelf.__xLastAcquireCallStackOrThreadId = xCallStackOrThreadId fShowDebugOutput("Acquired.") oSelf.fFireCallbacks("locked") return True finally: oSelf.__oQueuePutLock.get(False, 0) except queue.Full: fShowDebugOutput("Not acquired because busy.") return False