Example #1
0
    def __init__(cls, name, bases, nmspc):
        super().__init__(name, bases, nmspc)
        p_list = [(lambda x: False, lambda x: None)]
        cls._call_match = Match(p_list)
        cls._cast_match = Match(p_list)
        cls._info_match = Match(p_list)
        patterns = {
            'call': [],
            'cast': [],
            'info': [],
        }
        for attr in nmspc.values():
            cls._maybe_add_pattern(attr, patterns)

        for handler_type, type_patterns in patterns.items():
            cls._finalize_match(handler_type, type_patterns)
Example #2
0
    def _finalize_match(cls, handler_type, type_patterns):
        if not type_patterns:
            return

        attr_name = "_{}_match".format(handler_type)
        type_patterns.sort(key=lambda tp: tp[0])
        type_patterns = [tp[1] for tp in type_patterns]
        m = Match(type_patterns)
        setattr(cls, attr_name, m)
Example #3
0
    def __init__(self):
        self.state = 'init'
        super().__init__()

        self.__timeout_coro = None

        call_match = _atom_match_factory(Atom('$gen_call'))
        cast_match = _atom_match_factory(Atom('$gen_cast'))
        self._match = Match([(call_match, self._pre_handle_call),
                             (cast_match, self._pre_handle_cast),
                             (lambda x: True, self._pre_handle_info)])
Example #4
0
    async def _do_call(self, label, request, timeout=5):
        calling_pid = self._calling_process.pid_
        m_ref = self._node.monitor_process(calling_pid, self._destination_pid)
        msg = (label, (calling_pid, m_ref), request)
        await self._node.send(calling_pid, self._destination_pid, msg)

        def pattern(in_msg):
            if type(in_msg) != tuple:
                return False
            if len(in_msg) != 2:
                return False
            if in_msg[0] != m_ref:
                return False
            return True

        match = Match([(pattern, lambda x: x[1])])
        res = await self._calling_process.receive(match, timeout)
        self._node.demonitor_process(calling_pid, self._destination_pid, m_ref)
        return res
Example #5
0
    def __init__(self, passive: bool = False) -> None:
        """ Create a process and register itself. Pid is generated by the node
            object.
            :arg passive: Passive process has to handle their ``self.inbox_``
                from the user code. Active process will run the poll loop on the
                inbox and call ``self.handle_one_inbox_message`` for every
                incoming message.
        """
        self.state = 'init'
        self.passive_ = passive  # type: bool
        """ Having ``passive=True`` will only wake up this
            ``Process`` when a message arrives, to handle it, otherwise it will
            not get any CPU time for any empty polling loops. Having
            ``passive=False`` will run
            :py:func:`~Pyrlang.process.Process.process_loop``
            polling inbox.
        """

        node_obj = self.node_db.get()

        self.node_name_ = node_obj.node_name_  # type: str
        """ Convenience field to see the Node  """

        self.inbox_ = asyncio.Queue()
        """ Message queue. Messages are detected by the ``_run``
            loop and handled one by one in ``handle_one_inbox_message()``. 
        """
        self.__tmp_inbox = asyncio.Queue()  # used for selective receives

        self.pid_ = node_obj.register_new_process(self)
        """ Process identifier for this object. Remember that when creating a 
            process, it registers itself in the node, and this creates a
            reference. 
            References prevent an object from being garbage collected.
            To destroy a process, get rid of this extra reference by calling
            ``exit()`` and telling it the cause of its death.
        """

        self.is_exiting_ = False

        self._monitored_by = dict()  # type: Dict[Reference, Pid]
        """ Who monitors us. Either local or remote processes. """

        self._monitors = dict()  # type: Dict[Reference, Pid]
        """ Who we monitor. NOTE: For simplicity multiple monitors of same 
            target are not implemented. """

        self._links = set()  # type: Set[Pid]
        """ Bi-directional linked process pids. Each linked pid pair is unique
            hence using a set to store them. """

        self._signals = asyncio.Queue()
        """ Exit (and maybe later other) signals are placed here and handled
            at safe moments of time between handling messages. """

        if not self._match:
            self._match = Match()
        LOG.debug("Spawned process %s", self.pid_)
        if not self.passive_:
            event_loop = asyncio.get_event_loop()
            event_loop.create_task(self.process_loop())
            event_loop.create_task(self.handle_signals())