## programowanie zdarzeniowe, coroutine
# + rozszerzenie ebp02.tcl...
# + dodałem możliwość wielu msg typu A (z niedokon handlerem)
# + jak zrobic to samo z vwait ?!
#
lassign [chan pipe] wy we
# ^ łącze nienazwane do wysylania msg
fileevent $wy readable {
set msg [gets $wy]; if {[eof $wy]} {close $wy; return}
set typ [lindex $msg 0]
if {![info exists event($typ)]} {_puts "brak obslugi $typ"; return}
eval $event($typ)
# ^ to się wykonuje na poziomie globalnym
}
proc czekaj_na typ {
dolacz ::coro$typ [info coro]
set ::event($typ) "\[pobierz ::coro$typ\]"
yield
if {[llength [set ::coro$typ]]==0} {unset ::event($typ)}
return $::msg
}
proc dolacz {li_ w} { # dołącz jeśli nie ma (!)
upvar $li_ li; if {![info exists li]} {set li {}}
if {[lsearch -exact $li $w]==-1} {lappend li $w}
}
proc pobierz {li_} {
upvar $li_ li; set r [lindex $li 0]; set li [lrange $li 1 end]
return $r
}
set new_coro_licz 0
proc new_coro args { # auto nazwy coroutin
set nc coro#$::new_coro_licz#
coroutine $nc {*}$args; incr ::new_coro_licz
}
array unset event
set event(A) {new_coro handlerA $msg}
set event(B) {coroutine coroB handlerB $msg}
# ^ początkowa obsluga zdarzeń
# ^ typ A i B inaczej obslugiwany !!
proc handlerA {m} {
_puts "A/111 [info coro] '$m'"
set m2 [czekaj_na A1]
_puts "A/222 [info coro] '$m2'"
}
proc handlerB {m} {
_puts "B/111 [info coro] '$m'"
set m2 [czekaj_na B1]
_puts "B/222 [info coro] '$m2'"
}
# ^^^ wykonaj ^^^
.output.t delete 1.0 end
array get event
puts $we "A 123"; flush $we
puts $we "B 321"; flush $we
array get event
puts $we "A1 1233"; flush $we
puts $we "B1 3211"; flush $we
exit