def expire(self):
        try:
            # Set expiring variable and forget old timer.
            with self.lock:
                self.expire_gen += 1
                self.expiring = True
                self.rtimer = None

            while True:
                with self.lock:
                    if not self.heap:
                        return

                    top = self.heap[0]
                    ctime = time.time()
                    if top.expire > ctime:
                        return

                    # remove the timer
                    expired = heapq.heappop(self.heap)
                    del self.timers[expired]

                    # Ok to run with lock as we use RLock
                    # Much safer for things like caches
                    expired.expire = None
                    expired.run()
        except Exception as ex:
            self.logger.error("Unexpected Exception: %s", str(ex))
        finally:
            # This is never set while expiring is True
            assert self.rtimer is None

            with self.lock:
                # Now grab the next timer and set our real-time timer and unset expiring
                if self.heap:
                    top = self.heap[0]
                    ival = top.expire - time.time()
                    if 0 < ival:
                        ival = 0
                    self.rtimer = threading.Timer(ival, self.expire)
                    self.rtimer.start()
                self.expiring = False
dataset/ETHPy150Open ejeschke/ginga/ginga/util/heaptimer.py/TimerHeap.expire/swapped operands of `<`