diff --git a/docs/source/pages/pool.rst b/docs/source/pages/pool.rst index cd5a353..2dce091 100644 --- a/docs/source/pages/pool.rst +++ b/docs/source/pages/pool.rst @@ -228,8 +228,6 @@ The only method of a pool that one should **always** assume to be blocking is :p One method to be aware of is :py:meth:`.flush() `. Since it will await only those tasks that the pool considers **ended** or **cancelled**, the blocking can only come from any callbacks that were provided for either of those situations. -In general, the act of adding tasks to a pool is non-blocking, no matter which particular methods are used. The only notable exception is when a limit on the pool size has been set and there is "not enough room" to add a task. In this case, both :py:meth:`SimpleTaskPool.start() ` and :py:meth:`TaskPool.apply() ` will block until the desired number of new tasks found room in the pool (either because other tasks have ended or because the pool size was increased). - -:py:meth:`TaskPool.map() ` (and its variants) will **never** block. Since it makes use of a "meta-task" under the hood, it will always return immediately. However, if the pool was full when it was called, there is **no guarantee** that even a single task has started, when the method returns. -:py:meth:`TaskPool.map() ` (and its variants) will **never** block. Since it makes use of a "meta-task" under the hood, it will always return immediately. However, if the pool was full when it was called, there is **no guarantee** that even a single task has started, when the method returns. +In general, the act of adding tasks to a pool is non-blocking, no matter which particular methods are used. The only notable exception is when a limit on the pool size has been set and there is "not enough room" to add a task. In this case, :py:meth:`SimpleTaskPool.start() ` will block until the desired number of new tasks found room in the pool (either because other tasks have ended or because the pool size was increased). +:py:meth:`TaskPool.apply() ` and :py:meth:`TaskPool.map() ` (and its variants) will **never** block. Since they make use of "meta-tasks" under the hood, they will always return immediately. However, if the pool was full when one of them was called, there is **no guarantee** that even a single task has started, when the method returns. diff --git a/src/asyncio_taskpool/pool.py b/src/asyncio_taskpool/pool.py index 6a56c57..2267c9f 100644 --- a/src/asyncio_taskpool/pool.py +++ b/src/asyncio_taskpool/pool.py @@ -668,7 +668,9 @@ class TaskPool(BaseTaskPool): All the new tasks are added to the same task group. - This method blocks, **only if** the pool has not enough room to accommodate `num` new tasks. + Because this method delegates the spawning of the tasks to a meta task, it **never blocks**. However, just + because this method returns immediately, this does not mean that any task was started or that any number of + tasks will start soon, as this is solely determined by the :attr:`BaseTaskPool.pool_size` and `num`. Args: func: @@ -701,8 +703,9 @@ class TaskPool(BaseTaskPool): group_name = self._generate_group_name('apply', func) group_reg = self._task_groups.setdefault(group_name, TaskGroupRegister()) async with group_reg: - task = create_task(self._apply_num(group_name, func, args, kwargs, num, end_callback, cancel_callback)) - await task + meta_tasks = self._group_meta_tasks_running.setdefault(group_name, set()) + meta_tasks.add(create_task(self._apply_num(group_name, func, args, kwargs, num, + end_callback=end_callback, cancel_callback=cancel_callback))) return group_name @staticmethod