gyn

Win32下的Perl,无用的select,停滞的Tk,结束吧....

也谈Tcl的代码热替换

热替换的好处就不提了,至少是有用处的。如果没有 Erlang ,我想迟早也会去关注这个话题。尤其是在 Tk 中绑定事件处理函数时或者在调试的时候,根据不同的需要,可以动态的改变代码功能,这显然非常方便。但是如果实现的过程本身可能破坏原来代码的结构,我想这就有点得不偿失了。最起码的,应该有一套方便并且可遵循的规则。下面就两种办法进行分析。

先来设定一个最基本的实验环境:一个用来显示结果的文本框和一个用来激发事件的按钮,足矣。需要达到的目的是,在运行过程中,动态改变按钮的绑定处理函数。

第一种做法 -- 嵌入 source

Tcl 的代码集成,包括 package 等,多是建立在 source load 的基础上的,说白了 package require 不过也是在 pkgIndex.tcl 中找到相应的文件并 source 之。所以第一种思路是在按钮的绑定函数中 source 文件,主要的代码片段如下:

text .t

button .bt -text test -command {

    source b.tcl

}

pack .t .bt

我不得不将 source 放在函数中的原因在于,必须在每次运行时检测文件,以确保运行了最新修改过的代码。其中, b.tcl 的代码为

.t insetr end “1\n”

用来在文本框中新插入一行,内容为 1 。如果将 1 改为 2 ,程序将自动变换为插入内容为 2 的一行。但是这里有两个问题存在,首先这种检测很多时候是多余的,我们并不需要修改代码;第二, source 本身是对文件的读入操作,这不可避免地引入了 IO ,也就是说影像了性能。这种热替换方式,不大适合与巨大的事件处理函数,或者可能遭遇频繁调用的情况。

第二种做法 –- socket 指令 :

在修改完 b.tcl 之后,需要有人告诉运行程序一声,“喂,你的按钮该换代码了!”,接着主程序兴冲冲地去找按钮处理函数的源代码。这里讲的其实是一个进程间通信的问题,于是选择了 socket 。我把这个过程写了两个文件,一个是名为 hot.tm 的包,提供了两个主要函数: init ,用来指定可以被替换的函数及其相对应的文件; update ,用来具体实施热替换。其实替换的过程也是一个 source ,不同之处在于 source 的内容是一个函数,而非第一种情况里函数中的一段代码,这样新的函数将覆盖之前的版本。这是 a.tcl 的代码需要有所修改:

lappend auto_path [file dirname [info script]]

package require hot

 

hot::init b b.tcl

 

text .t

button .bt -text test –command b

 

pack .t .bt

hot namespace 中,维护着一个函数名到源文件的 array ,在初始化时需要指明哪些函数是可以被热替换的。我可不想随便哪个函数都可以被替换,这就乱套了。

另一个文件时 hotc.tcl ,用来在修改完代码之后通知运行程序来进行热替换,当然这个过程只能依靠人工来完成了。比如在这里需要替换 b 函数,那么就执行一下 hotc.tcl b

最后我想,这应该是一个比较可以被接受的方法了。其实即使是标榜着热替换的 erlang ,也需要在修改代码之后 compile 的,这就好比执行了 hotc.tcl ,只不过 erlang 的做法是语言级的。

代码下载

posted on 2009-05-17 17:08 gyn_tadao 阅读(740) 评论(0)  编辑 收藏 引用 所属分类: TclTk

只有注册用户登录后才能发表评论。
<2009年5月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

常用链接

留言簿(15)

随笔分类(126)

随笔档案(108)

相册

搜索

最新评论

阅读排行榜

评论排行榜