You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

60 lines
2.0 KiB

4 years ago
  1. class PriorityQueue(object):
  2. """A priority queue implemented using multiple internal queues (typically,
  3. FIFO queues). The internal queue must implement the following methods:
  4. * push(obj)
  5. * pop()
  6. * close()
  7. * __len__()
  8. The constructor receives a qfactory argument, which is a callable used to
  9. instantiate a new (internal) queue when a new priority is allocated. The
  10. qfactory function is called with the priority number as first and only
  11. argument.
  12. Only integer priorities should be used. Lower numbers are higher
  13. priorities.
  14. startprios is a sequence of priorities to start with. If the queue was
  15. previously closed leaving some priority buckets non-empty, those priorities
  16. should be passed in startprios.
  17. """
  18. def __init__(self, qfactory, startprios=()):
  19. self.queues = {}
  20. self.qfactory = qfactory
  21. for p in startprios:
  22. self.queues[p] = self.qfactory(p)
  23. self.curprio = min(startprios) if startprios else None
  24. def push(self, obj, priority=0):
  25. if priority not in self.queues:
  26. self.queues[priority] = self.qfactory(priority)
  27. q = self.queues[priority]
  28. q.push(obj) # this may fail (eg. serialization error)
  29. if self.curprio is None or priority < self.curprio:
  30. self.curprio = priority
  31. def pop(self):
  32. if self.curprio is None:
  33. return
  34. q = self.queues[self.curprio]
  35. m = q.pop()
  36. if len(q) == 0:
  37. del self.queues[self.curprio]
  38. q.close()
  39. prios = [p for p, q in self.queues.items() if len(q) > 0]
  40. self.curprio = min(prios) if prios else None
  41. return m
  42. def close(self):
  43. active = []
  44. for p, q in self.queues.items():
  45. if len(q):
  46. active.append(p)
  47. q.close()
  48. return active
  49. def __len__(self):
  50. return sum(len(x) for x in self.queues.values()) if self.queues else 0