processing.py 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # coding: utf-8
  2. import typing
  3. from multiprocessing import Process
  4. from multiprocessing.connection import Connection
  5. from multiprocessing.connection import Pipe
  6. from synergine2.base import BaseObject
  7. from synergine2.config import Config
  8. from synergine2.share import SharedDataManager
  9. STOP = '__STOP__'
  10. # global shared manager
  11. shared_data = SharedDataManager()
  12. # TODO: se jobs
  13. class Job(object):
  14. pass
  15. class Worker(object):
  16. def __init__(
  17. self,
  18. config: Config,
  19. real_job: typing.Callable[..., typing.Any],
  20. ) -> None:
  21. self.config = config
  22. local_read_pipe, local_write_pipe = Pipe(duplex=False)
  23. process_read_pipe, process_write_pipe = Pipe(duplex=False)
  24. self.local_read_pipe = local_read_pipe # type: Connection
  25. self.local_write_pipe = local_write_pipe # type: Connection
  26. self.process_read_pipe = process_read_pipe # type: Connection
  27. self.process_write_pipe = process_write_pipe # type: Connection
  28. self.real_job = real_job
  29. self.process = Process(
  30. target=self.work,
  31. args=(
  32. self.local_write_pipe,
  33. self.process_read_pipe,
  34. )
  35. )
  36. self.db = None # type: RedisDatabase
  37. self.process.start()
  38. def work(self, *args, **kwargs):
  39. while True:
  40. args = self.process_read_pipe.recv()
  41. if args == STOP:
  42. return
  43. result = self.real_job(*args)
  44. self.local_write_pipe.send(result)
  45. class ProcessManager(BaseObject):
  46. def __init__(
  47. self,
  48. config: Config,
  49. process_count: int,
  50. job: typing.Callable[..., typing.Any],
  51. ) -> None:
  52. self.config = config
  53. self._process_count = process_count
  54. self.workers = []
  55. self.start_workers(process_count, job)
  56. def start_workers(self, worker_count: int, job: typing.Callable[..., typing.Any]) -> None:
  57. assert not self.workers
  58. for i in range(worker_count):
  59. self.workers.append(Worker(self.config, job))
  60. def make_them_work(self, message: typing.Any) -> 'TODO':
  61. responses = []
  62. for worker_id, worker in enumerate(self.workers):
  63. worker.process_write_pipe.send((worker_id, self._process_count, message))
  64. for worker in self.workers:
  65. responses.append(worker.local_read_pipe.recv())
  66. return responses
  67. def terminate(self) -> None:
  68. for worker in self.workers:
  69. worker.process_write_pipe.send(STOP)
  70. for worker in self.workers:
  71. worker.process.join()