Sujet : Re: Thread with -async exits prematurely
De : et99 (at) *nospam* rocketship1.me (et99)
Groupes : comp.lang.tclDate : 19. Jun 2024, 23:37:08
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <v4vmik$26f15$1@dont-email.me>
References : 1
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1
On 6/19/2024 3:49 AM, Luis Mendes wrote:
Hi all!
My program is working fine when thread::send don't use the -async option.
When it does, all of those created threads exit prematurely.
The pseudo-code I have is this:
-snip-
What I want is really to have several threads launched in the same moment,
at each run of the while loop that checks if the number of active threads
is less than the nr_max_threads.
How can that be accomplished?
Thanks,
Luís
I can't tell your true intent from the pseudo code alone. As Rich said, non-working but real code is preferred here, then people can run the code and help you debug it.
Are you re-using threads or creating new ones and are you using threads as workers to process jobs? Is this going to eventually be a multi-server, single-queue implementation? Do all threads run the same code?
I have a way of doing those kinds of threads you might find interesting; it's sort of object oriented threads.
------------------------------
set script {
package require... ;# one time setups
source ....
global var1 var2 ...
proc init {args} ;# like a constructor, one time to init the thread's var's
lassign $args ::var1 ::var2 ....
}
proc work {arg1 arg2 ...} { ;# like a method
...
return result
}
... including any oo code ...
thread::wait ;# don't exit, re-use
}
# now to create a worker thread(s) and init it:
set tid(1) [thread::create $script] ;# 2,3, ...
thread::send $tid(1) [list init value1 value2 ...] ;# similar to an OO constructor
#Then sync or async job requests:
set result($N) [thead::send $tid($N) [list work ...arglist...]] ;# sync call to thread N
# async call
unset -nocomplain result(1)
set status [thread::send -async $tid(1) [list work ...arglist...] result(1)]
# .... other stuff before waiting including other work and update or vwait calls ....
if {![info exist result(1)]} {vwait result(1)} ;#conditional vwait
------------------------------
Some notes:
Each thread has it's own interpreter, so global data in a thread is not "global" to the program nor visible to other threads (or the main thread). So, unless you really need multiple namespaces in a thread, global variables might be simpler to use.
Re-use threads; you can just "call" it (like calling a method) for each new job you want done. No need to package require or "source" code more than once (per thread).
End the script with a thread::wait, with nothing after that (see manual's warning).
The unset/if not exist technique protects against any entering of the event loop before vwait-ing. Can wait for 1 or all or any combo. Can also set a write trace on a result variable in lieu of doing a vwait.
Each thread needs it's own result variable (which resides in the main thread) where it both signals a job is done, and also can return the job's value (scalars, array element, lists, dicts, etc).
You will need to keep track of the tid's and the result's by using your own thread index. You might also need to create a job queue.
This is essentially how my Tasks module works, except it hides all the above details. You can also use the tpool and ttrace packages, which has many of the same and lots more features.