def spawn(self, __groups, __coro_fun, *args, **kwargs):
        """
        Start a new coroutine and add it to the pool atomically.

        :param groups: The groups the coroutine belongs to.
        :type groups: :class:`set` of group keys
        :param coro_fun: Coroutine function to run
        :param args: Positional arguments to pass to `coro_fun`
        :param kwargs: Keyword arguments to pass to `coro_fun`
        :raise RuntimeError: if the limit on any of the groups or the total
                             limit is exhausted
        :rtype: :class:`asyncio.Task`
        :return: The task in which the coroutine runs.

        Every group must have at least one free slot available for `coro` to be
        spawned; if any groups capacity (or the total limit) is exhausted, the
        coroutine is not accepted into the pool and :class:`RuntimeError` is
        raised.

        If the coroutine cannot be added due to limiting, it is not started at
        all.

        The coroutine is started by calling `coro_fun` with `args` and
        `kwargs`.

        .. note::

           The first two arguments can only be passed positionally, not as
           keywords. This is to prevent conflicts with keyword arguments to
           `coro_fun`.

        """
        # ensure the implicit group is included
        __groups = set(__groups) | {()}

        return asyncio.ensure_future(__coro_fun(*args, **kwargs))