terminals.py 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from multiprocessing import Queue
  2. from multiprocessing import Process
  3. from queue import Empty
  4. import time
  5. from synergine2.simulation import Simulation, Subject
  6. STOP_SIGNAL = '__STOP_SIGNAL__'
  7. class TerminalPackage(object):
  8. def __init__(
  9. self,
  10. subjects: [Subject]=None,
  11. actions: ['TODO']=None,
  12. ):
  13. self.subjects = subjects
  14. self.actions = actions or {}
  15. class Terminal(object):
  16. """Default behaviour is to do nothing.
  17. DEFAULT_SLEEP is sleep time between each queue read"""
  18. DEFAULT_SLEEP = 1
  19. def __init__(self):
  20. self._input_queue = None
  21. self._output_queue = None
  22. self._stop_required = False
  23. def start(self, input_queue: Queue, output_queue: Queue) -> None:
  24. self._input_queue = input_queue
  25. self._output_queue = output_queue
  26. self.run()
  27. def run(self):
  28. """
  29. Override this method to create your daemon terminal
  30. """
  31. try:
  32. while self.read():
  33. time.sleep(self.DEFAULT_SLEEP)
  34. except KeyboardInterrupt:
  35. pass
  36. def read(self):
  37. while True:
  38. try:
  39. package = self._input_queue.get(block=False, timeout=None)
  40. if package == STOP_SIGNAL:
  41. self._stop_required = True
  42. return False
  43. self.receive(package)
  44. except Empty:
  45. return True # Finished to read Queue
  46. def receive(self, value):
  47. raise NotImplementedError()
  48. def send(self, value):
  49. self._output_queue.put(value)
  50. class TerminalManager(object):
  51. def __init__(self, terminals: [Terminal]):
  52. self._terminals = terminals
  53. self._outputs_queues = []
  54. self._inputs_queues = []
  55. def start(self) -> None:
  56. for terminal in self._terminals:
  57. output_queue = Queue()
  58. self._outputs_queues.append(output_queue)
  59. input_queue = Queue()
  60. self._inputs_queues.append(input_queue)
  61. process = Process(target=terminal.start, kwargs=dict(
  62. input_queue=output_queue,
  63. output_queue=input_queue,
  64. ))
  65. process.start()
  66. def stop(self):
  67. for output_queue in self._outputs_queues:
  68. output_queue.put(STOP_SIGNAL)
  69. def send(self, value):
  70. for output_queue in self._outputs_queues:
  71. output_queue.put(value)
  72. def receive(self) -> []:
  73. values = []
  74. for input_queue in self._inputs_queues:
  75. try:
  76. while True:
  77. values.append(input_queue.get(block=False, timeout=None))
  78. except Empty:
  79. pass # Queue is empty
  80. return values