From: Andreas Otto on 4 Feb 2010 03:11 Hi, I'm using a workaround to address the following problem in my project called "libmsgque" with a tcl extension support "tclmsgque" The question is: Is an "official" solution available for the missing "Main" problem ? mfg Andreas Otto http://nhi1.berlios.de/theLink/tclmsgque/group__tclmsgqueref.htm =================================================================== Tcl has a special requirement, for every new server-thread a new interpreter is created and this interpreter source the toplevel file for initialization. This file is set on library startup and can be changed with "Init". The problem is the server startup code from the toplevel. For internal purpose this code should only be executed on "application-startup" (like the C \b main function)and not for every thread again, use "tclmsgque Main" to achieve this. \verbatim package require TclMsgque .... proc ServerSetup {ctx} ... proc ServerCleanup {ctx} ... .... tclmsgque Main { set srv [tclmsgque MqS] $srv ConfigSetServerSetup ServerSetup $srv ConfigSetServerCleanup ServerCleanup $srv ConfigSetFactory if {[catch { $srv LinkCreate {*}$argv $srv ProcessEvent -wait FOREVER }]} { $srv ErrorSet } $srv Exit } \endverbatim
From: Alexandre Ferrieux on 4 Feb 2010 03:24 On Feb 4, 9:11 am, Andreas Otto <aotto1...(a)users.sourceforge.net> wrote: > Hi, > > I'm using a workaround to address the following problem in my > project called "libmsgque" with a tcl extension support "tclmsgque" > > The question is: > > Is an "official" solution available for the missing "Main" problem ? > > mfg > > Andreas Otto > > http://nhi1.berlios.de/theLink/tclmsgque/group__tclmsgqueref.htm > =================================================================== > Tcl has a special requirement, for every new server-thread a new > interpreter is created and this interpreter source the toplevel file for > initialization. This file is set on library startup and > can be changed with "Init". The problem is the server startup code from > the toplevel. For internal purpose this code should only be executed on > "application-startup" (like the C \b main function)and not for every > thread again, use "tclmsgque Main" to achieve this. > \verbatim > package require TclMsgque > ... > proc ServerSetup {ctx} ... > proc ServerCleanup {ctx} ... > ... > tclmsgque Main { > set srv [tclmsgque MqS] > $srv ConfigSetServerSetup ServerSetup > $srv ConfigSetServerCleanup ServerCleanup > $srv ConfigSetFactory > if {[catch { > $srv LinkCreate {*}$argv > $srv ProcessEvent -wait FOREVER > }]} { > $srv ErrorSet > } > $srv Exit} > > \endverbatim Do you realize that _nothing_ forces the newly created thread-interps to source the same "toplevel" file ? Or are you talking about your loadable extension's Init function, which indeed must be called in each thread-interp (because Tcl_Create*Command is per-interp) ? In that case, just use a singleton: MyExt_Init(...) { ... static int first=1; if (first) { first=0; DoSomethingOnce(); } CreateTheTclCommands(); } Notice that the static var access doesn't need a mutex because the first [load] of the extension can trivially be done way ahead of the first thread creation. So the subsequent per-thread code can safely do a [load] again, "first" will be 0. -Alex
From: Andreas Otto on 4 Feb 2010 03:58 Thanks for your help, Am 04.02.2010 09:24, schrieb Alexandre Ferrieux: > On Feb 4, 9:11 am, Andreas Otto <aotto1...(a)users.sourceforge.net> > wrote: > > > Do you realize that _nothing_ forces the newly created thread-interps > to source the same "toplevel" file ? For my problem a "server" in tcl is defined as a toplevel file and this file is sourced (even in a thread) to define the server behavior. Splitting this file into two independent files is possible but difficult to maintain and in fact a "single-file" solution is always best like one "server.exe" is C# or one "server.jar" in JAVA. > > Or are you talking about your loadable extension's Init function, > which indeed must be called in each thread-interp (because > Tcl_Create*Command is per-interp) ? > In that case, just use a singleton: > > MyExt_Init(...) > { > ... > static int first=1; > if (first) { > first=0; > DoSomethingOnce(); > } > CreateTheTclCommands(); > } > > Notice that the static var access doesn't need a mutex because the > first [load] of the extension can trivially be done way ahead of the > first thread creation. So the subsequent per-thread code can safely do > a [load] again, "first" will be 0. as my internal coding-convention I never use "static-variables" to achieve some behaviour, but this only belongs to me. I found an solution close to yours, and set a "flag" variable in the interpreter to identify a "thread" startup ... -> the question was more interesting for "other" tcl projects as well, because near all languages have a "Main" like behavior ... C,C++,C#,JAVA,VB.NET - have main (or Main) perl - has a interpreter "perl_clone" command (this is close to main) python - has a "main" (if __name__ == "__main__": ...) but this is not needed because python has no mature thread support at all tcl - has mature thread support but no "main" -> extra code needed to simulate "main" my solution .................... static int NS(Main) ( Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] ) { if (3 != objc) { Tcl_WrongNumArgs(interp, 2, objv, "code"); return TCL_ERROR; } if (Tcl_UnsetVar (interp, "MQ_STARTUP_IS_THREAD", TCL_GLOBAL_ONLY) == TCL_ERROR) { TclErrorCheck (Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_GLOBAL)); } return TCL_OK; } mfg Andreas Otto
From: Alexandre Ferrieux on 4 Feb 2010 04:42 On Feb 4, 9:58 am, Andreas Otto <aotto1...(a)users.sourceforge.net> wrote: > Thanks for your help, > > Am 04.02.2010 09:24, schrieb Alexandre Ferrieux: > > > On Feb 4, 9:11 am, Andreas Otto <aotto1...(a)users.sourceforge.net> > > wrote: > > > Do you realize that _nothing_ forces the newly created thread-interps > > to source the same "toplevel" file ? > > For my problem a "server" in tcl is defined as a toplevel file > and this file is sourced (even in a thread) to define the server > behavior. Splitting this file into two independent files is possible > but difficult to maintain and in fact a "single-file" solution is > always best like one "server.exe" is C# or one "server.jar" in JAVA. Are you kidding ? thread::send $id "set i_am_a_thread 1;source toplevel.tcl" > > as my internal coding-convention I never use "static-variables" to > achieve some behaviour, but this only belongs to me. I found an > solution close to yours, and set a "flag" variable in the interpreter > to identify a "thread" startup ... Very contorted. If you have religious reservations about static variables, and prefer complicated workarounds, that's your problem. The static method (1) works without mutex for arbitrary uncooperating threads as soon as the main thread has first done a [load] before spawning, and (2) can be refined with a self-initialized mutex if you want to support the even more general case of N symmetric threads doing [load] concurrently. -Alex
|
Pages: 1 Prev: Hello world and expectk Next: How to let an "entry" show its last characters? |