You made my day!
Thanks to both of you.
Fiddling around with mutexes on my own had not obtained the desired
result, but using condition variables did.
> This highlights the fact that using the optional variable argument in [thread::send] is only fit for the simplest cases.
> To work around this, don't use the variable argument, but arrange for both of your async threads to [thread::send] back to the main thread something that will append its result to a common variable:
>
> thread::send -async $handle_thread1 {set res [heavy_work];thread::send $main [list lappend ::result TH1 $res]}
>
> thread::send -async $handle_thread2 {set res [less_heavy_work];thread::send $main [list lappend ::result TH2 $res]}
After some trials processing the lines in parallel in batches of fixed
numbers I realized that I wasted time waiting for completion of batches.
So I finally followed Alex' suggestion in some kind: I created an
additional output thread that gets sent the processed lines directly as
they become available.
Amazingly the resulting pipeline (reader-filter-writer) outperforms the
single threaded serial solution (reading, processing and writing back
line by line) hands down, even if only one filter thread is running;
with two or three filters in parallel it finally saves about 40% of
original time. The batch oriented version in contrast needs at least two
parallel filters to gain speed at all, as it otherwise just introduces
additional overhead that results in an actual slowdown of processing.
Josef