When looking at the source code of nameko, I often see the usage of gt.link(self._handle_thread_exited)

 def spawn_managed_thread(self, run_method):
    """ Spawn a lifecycle-managed thread, which calls the ``run_method``
    once it has been started.

    Any errors raised inside the ``run_method`` cause the container to be
    killed.

    It is the entrypoint provider's responsibility to react to ``stop()``
    calls and terminate it's spawned threads.

    Threads are killed automatically by the container if they are
    still running after all their providers have been stopped.

    Entrypoints may only create separate threads using this method,
    to ensure they are life-cycle managed.
    """
    gt = eventlet.spawn(run_method)
    self._active_threads.add(gt)
    gt.link(self._handle_thread_exited)
    return gt

In the documentation of eventlet, there is no description of what this api does, so I took a look at the source code of eventlet, and there are comments about him:

 def link(self, func, *curried_args, **curried_kwargs):
    """ Set up a function to be called with the results of the GreenThread.

    The function must have the following signature::

        def func(gt, [curried args/kwargs]):

    When the GreenThread finishes its run, it calls *func* with itself
    and with the `curried arguments <http://en.wikipedia.org/wiki/Currying>`_ supplied
    at link-time.  If the function wants to retrieve the result of the GreenThread,
    it should call wait() on its first argument.

    Note that *func* is called within execution context of
    the GreenThread, so it is possible to interfere with other linked
    functions by doing things like switching explicitly to another
    greenthread.
    """
    if self._exit_funcs is None:
        self._exit_funcs = deque()
    self._exit_funcs.append((func, curried_args, curried_kwargs))
    if self._exit_event.ready():
        self._resolve_links()

English is not understandable, just use translation software to translate it:

图片.png

original:

 Set up a function to be called with the results of the GreenThread.

        The function must have the following signature::

            def func(gt, [curried args/kwargs]):

        When the GreenThread finishes its run, it calls *func* with itself and with the `curried arguments <http://en.wikipedia.org/wiki/Currying>`_ supplied at link-time.  If the function wants to retrieve the result of the GreenThread,it should call wait() on its first argument.

        Note that *func* is called within execution context of the GreenThread, so it is possible to interfere with other linked functions by doing things like switching explicitly to another greenthread.

Translation:

 设置一个函数,用GreenThread的结果来调用。

        该函数必须有以下签名:。

            def func(gt, [curried args/kwargs])。

        当GreenThread完成其运行时,它用自己和在链接时提供的`curried arguments <http://en.wikipedia.org/wiki/Currying>`_调用*func*。 如果该函数想获取GreenThread的结果,它应该在其第一个参数上调用wait()。

        请注意,*func*是在GreenThread的执行上下文中调用的,所以有可能会干扰到其他链接的函数,比如明确地切换到另一个Greenthread。

So, what is this link for? In fact, it is a callback function register.

Similar to add_done_callback in threading
For details, please refer to: Does the callback function of Python's thread pool run in the main thread or the worker thread?
 import eventlet
from loguru import logger


def func():
    logger.debug('执行 func')


def call_back_func(gt):
    logger.debug('执行 回调函数')


t1 = eventlet.spawn(func)
t2 = eventlet.spawn(func)
t3 = eventlet.spawn(func)

t1.link(call_back_func)
t2.link(call_back_func)
t3.link(call_back_func)

t1.wait()
t2.wait()
t3.wait()

Results of the

 2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数
2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数
2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数

universe_king
3.4k 声望680 粉丝