有没有办法从fileevent处理程序中操作非全局变量?考虑以下最小服务器:
proc initState {stateName} {
upvar $stateName state
set state(foo) bar
set state(baz) bla
# ...
return
}
proc handleConnection {stateName newsock clientAddress clientPort} {
upvar $stateName state
fconfigure $newsock -blocking 0
fconfigure $newsock -buffering line
fileevent $newsock readable [list handleData $newsock]
return
}
proc handleData {f} {
if {[eof $f]} {
fileevent $f readable {}
close $f
return
}
gets $f line
puts $f ok
# need to modify state here...
return
}
proc runServer {port} {
array set state {}
initState state
socket -server {handleConnection state} $port
vwait forever
}
runServer 1234
是否有可能操纵state
范围内创建的runServer
数组,或者是唯一可以使state
成为全局变量的方法?
我对Tcl很新,如果我使用C,我只需将一个指向state
的指针传递给事件处理程序,但遗憾的是Tcl不允许这样做。我在做什么奇怪的事情,是否有更多的Tcl-ish方式?
答案 0 :(得分:4)
这根本不起作用。问题是Tcl的堆栈帧不会以您想要的方式持续存在。
解决此问题的标准选项是:
将状态保存在由“连接令牌”(例如,频道名称)索引的全局数组中。请记住,数组是按字符串索引的;像“sock42,hostname
”这样的复合键非常合法。
将状态保存在以连接令牌命名的命名空间中。如果您使用的是Tcl 8.5,namespace upvar
命令可以使更多更容易。
将状态保存在TclOO 对象(需要Tcl 8.6 或单独的TclOO软件包8.5)或使用不同的对象系统(例如,[incr] Tcl],XOTcl;这些适用于许多Tcl版本。)
将状态保持在 coroutine (需要Tcl 8.6)。这有效地为您提供了一个命名堆栈(并允许您编写代码,因此它显然是“直线”而不是由回调驱动)但其版本要求是 strict 。