zmc
2023-12-22 9fdbf60165db0400c2e8e6be2dc6e88138ac719a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
U
Z±d—ã@s\ddlmZmZddlZddlmZdZeƒZGdd„dƒZGdd„dƒZ    e    ƒZ
d    d
„Z dS) é)ÚThreadÚLockN)Úcounté
c@s$eZdZdd„Zdd„Zdd„ZdS)Ú WorkerThreadcCsHd|_||_tƒ|_|j ¡t|jdd}dttƒ›|_    | 
¡dS)NT)ÚtargetÚdaemonzTrio worker thread ) Ú_jobÚ _thread_cacherÚ _worker_lockÚacquirerÚ_workÚnextÚ name_counterÚnameÚstart)ÚselfZ thread_cacheÚthread©rúOd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\trio/_core/_thread_cache.pyÚ__init__,s
zWorkerThread.__init__cCs2|j\}}d|_t |¡}d|jj|<||ƒdS©N)r    ÚoutcomeÚcapturer
Ú _idle_workers)rÚfnÚdeliverÚresultrrrÚ _handle_job;s
 
 
 zWorkerThread._handle_jobcCsJ|jjtdr| ¡qz|jj|=Wntk
r>YqYqXdSqdS)N)Útimeout)r r Ú IDLE_TIMEOUTrr
rÚKeyError©rrrrr Hs
 
zWorkerThread._workN)Ú__name__Ú
__module__Ú __qualname__rrr rrrrr+s rc@seZdZdd„Zdd„ZdS)Ú ThreadCachecCs
i|_dSr)rr"rrrr`szThreadCache.__init__cCsHz|j ¡\}}Wntk
r.t|ƒ}YnX||f|_|j ¡dSr)rÚpopitemr!rr    r Úrelease)rrrZworkerÚ_rrrÚstart_thread_sooncs 
zThreadCache.start_thread_soonN)r#r$r%rr*rrrrr&_sr&cCst ||¡dS)uÈ    Runs ``deliver(outcome.capture(fn))`` in a worker thread.
 
    Generally ``fn`` does some blocking work, and ``deliver`` delivers the
    result back to whoever is interested.
 
    This is a low-level, no-frills interface, very similar to using
    `threading.Thread` to spawn a thread directly. The main difference is
    that this function tries to re-use threads when possible, so it can be
    a bit faster than `threading.Thread`.
 
    Worker threads have the `~threading.Thread.daemon` flag set, which means
    that if your main thread exits, worker threads will automatically be
    killed. If you want to make sure that your ``fn`` runs to completion, then
    you should make sure that the main thread remains alive until ``deliver``
    is called.
 
    It is safe to call this function simultaneously from multiple threads.
 
    Args:
 
        fn (sync function): Performs arbitrary blocking work.
 
        deliver (sync function): Takes the `outcome.Outcome` of ``fn``, and
          delivers it. *Must not block.*
 
    Because worker threads are cached and reused for multiple calls, neither
    function should mutate thread-level state, like `threading.local` objects
    â€“ or if they do, they should be careful to revert their changes before
    returning.
 
    Note:
 
        The split between ``fn`` and ``deliver`` serves two purposes. First,
        it's convenient, since most callers need something like this anyway.
 
        Second, it avoids a small race condition that could cause too many
        threads to be spawned. Consider a program that wants to run several
        jobs sequentially on a thread, so the main thread submits a job, waits
        for it to finish, submits another job, etc. In theory, this program
        should only need one worker thread. But what could happen is:
 
        1. Worker thread: First job finishes, and calls ``deliver``.
 
        2. Main thread: receives notification that the job finished, and calls
           ``start_thread_soon``.
 
        3. Main thread: sees that no worker threads are marked idle, so spawns
           a second worker thread.
 
        4. Original worker thread: marks itself as idle.
 
        To avoid this, threads mark themselves as idle *before* calling
        ``deliver``.
 
        Is this potential extra thread a major problem? Maybe not, but it's
        easy enough to avoid, and we figure that if the user is trying to
        limit how many threads they're using then it's polite to respect that.
 
    N)Ú THREAD_CACHEr*)rrrrrr*os<r*) Ú    threadingrrrÚ    itertoolsrr rrr&r+r*rrrrÚ<module>s #4