Posted to tcl by aspect at Thu Apr 27 02:44:29 GMT 2017view raw
- package require Thread
- set unfinished_work {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
- set finished_work {}
- set workers {}
- set retirees {}
- set n_workers 7
- set is_done false
- set USE_PRESERVE 0 ;# MUST MATCH
- set worker_script {
- set USE_PRESERVE 0 ;# MUST MATCH
- proc work {main} {
- set result 0
- while 1 {
- puts "[thread::id] asking for work"
- set work [thread::send $main get_work]
- if {$work eq ""} break
- puts "[thread::id] doing $work"
- after 1
- thread::send -async $main [list give_result [thread::id] $work]
- }
- puts "[thread::id] done!"
- thread::send -async $main [list remove_worker [thread::id]]
- if {$::USE_PRESERVE} {
- thread::release
- } else {
- thread::exit
- }
- }
- thread::wait
- }
- proc get_work {} {
- puts "Main distributing work from {$::unfinished_work}"
- set ::unfinished_work [lassign $::unfinished_work work]
- return $work
- }
- proc give_result {wid result} {
- puts "Main receiving finished work: $result"
- lappend ::finished_work $result
- }
- proc remove_worker {wid} {
- puts "Main removing $wid"
- set status [thread::join $wid]
- puts "Main removed $wid: $status"
- if {[dict unset ::workers $wid] eq ""} {
- puts "Main done!"
- set ::is_done true
- }
- }
- proc start_worker {} {
- if {$::USE_PRESERVE} {
- set id [thread::create -preserved -joinable $::worker_script]
- } else {
- set id [thread::create -joinable $::worker_script]
- }
- dict set ::workers $id working
- thread::send -async $id [list work [thread::id]]
- return $id
- }
- for {set i 0} {$i < $::n_workers} {incr i} {
- set wid [start_worker]
- puts "Started worker: $wid"
- }
- vwait is_done
- puts "Results: $::finished_work"
- puts "Remaining threads: [thread::names]"