Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/vwait?V=53
QUERY_STRINGV=53
CONTENT_TYPE
DOCUMENT_URI/revision/vwait
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.100.156
REMOTE_PORT21904
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.16.75.37
HTTP_CF_RAY88649928ecb39129-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_REFERERhttp://wiki.tcl.tk/revision/vwait?V=53
HTTP_CF_CONNECTING_IP3.16.75.37
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit vwait '''`\[http://www.tcl.tk/man/tcl/TclCmd/vwait.htm%|%vwait\]`''',\ a\ \[Tcl\ Commands%|%built-in\]\ Tcl\ command,\ enters\ the\ \[Tcl\ event\ loop%|%event\ loop\]\ and\ only\ returns\ once\nthe\ indicated\ variable\ is\ modified.\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''vwait'''\ ''varName''\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/vwait.htm%|%official\ man\ page\]:\ \ \ \n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[event-oriented\ programming\]:\ \ \ \n\n\ \ \ \[Tcl\ event\ loop\]:\ \ \ \n\n\ \ \ `\[update\]`:\ \ \ \n\ \ \ \[update\]:\ \ \ \n\ \ \ \[Update\ considered\ harmful\]:\ \ \ \n\n\n\n**\ Description\ **\n\n'''`vwait`'''\ enters\ the\ Tcl\ \[event\ loop\],\ and\ as\ events\ are\ processed,\ monitors\ the\ variable\ named\ by\ ''varName''\ for\ changes,\ \[return%|%returning\]\ only\ once\ some\ event\ handler\ modifies\ ''varName''.\ \ Thus,\ `vwait`\ effectively\ blocks\ execution\ of\ the\ foreground\ script\ until\ a\ modification\ of\ ''varName''\ occurs.\nAs\ soon\ as\ the\ event\ handler\ that\ modifies\ ''varName''\ returns,\ `vwait`\ returns.\ ''VarName''\ is\ resolved\ relative\ to\ the\ \[global\]\ scope,\ so\ the\ following\ pattern\ is\ often\ useful:\n\n======\nvwait\ \[namespace\ which\ -variable\ foo\]\n======\n\nSince\ the\ event\ handler\ that\ stores\ a\ value\ to\ ''varName''\ continues\ to\ completion\ before\ `vwait`\ can\ return,\ some\ time\ can\ pass\ betweeen\ when\ a\ value\ is\ stored\ to\ ''varName''\ and\ when\ `vwait`\ returns.\ \nFor\ example,\ if\ an\ event\ handler\ sets\n''varName''\ and\ then\ itself\ calls\ '''vwait'''\ to\ wait\ for\ a\ different\ variable,\nthen\ the\ outer\ `vwait`\ depends\ on\ the\ inner\ `vwait`,\ and\ may\ not\ return\ for\ a\ long\ time.\ \ In\ general,\ nested\ calls\ to\ `vwait`\ should\ be\ avoided.\ \n\n\n\n**\ `vwait\ forever`\ **\n**\ Avoiding\ Conflicting\ \[vwait\]'s\ **\n''Wish''\ has\ a\ built-in\ event\ loop.\ Tclsh\ has\ one\ too\ but\ enters\ that\ only\ on\ demand,\ for\ which\ the\ \[idiom\]\ is\ to\ write\ at\ the\ end\ of\ code\nPackages\ such\ as\ \[Tk\]\ and\ \[tclsvc\]\ themselves\ call\ \[vwait\]\ \ To\ avoid\ conflicting\ \[vwait\]'s:\n======\nvwait\ forever\nif\ \{!\[info\ exists\ tk_version\]\ &&\ !\[info\ exists\ tcl_service\]\}\ \{\ ...\n======\n\n\[PS\]\ 2004-03-09:\ \ For\ example,\ this\ script,\ which\ implements\ a\ TCP\ server\ in\ntclsh\ and\ wish,\ will\ not\ exit\ properly\ when\ you\ close\ its\ main\ window:\n\n======\nproc\ accept\ \{\ channel\ peer\ port\ \}\ \{\n\ \ \ \ close\ \$channel\n\}\nsocket\ -server\ accept\ 5000\n======\n\n\[RS\]:\ \ ''forever''\ being\ the\ name\ of\ a\ variable\ that\ is\ presumably\ never\ used,\ but\ you\ can\ set\ ''forever''\ to\ any\ value\ to\ terminate\ such\ a\ Tcl\ script).\nAfter\ you\ close\ the\ window,\ the\ wish\ app\ does\ not\ exit,\ but\ remains\ fully\ active\ in\ memory.\n\n\[DGP\]:\ \ This\ discussion\ is\ essentially\ another\nvote\ in\ favor\ of\ \[http://sf.net/tracker/?func=detail&aid=456548&group_id=12997&atid=362997%|%Tk\ Feature\ Request\ 456548\].\n\nThe\ flaw\ here\ is\ in\ Tk's\ continued\ assumptions\ about\ being\ in\ wish,\ rather\ than\nbeing\ an\ independent\ package\ that\ might\ be\ loaded\ into\ any\ Tcl\ interp.\ \ There's\nnothing\ wrong\ with\ \[\[vwait\]\]\ (at\ least\ nothing\ revealed\ in\ this\ discussion.\ :)\n).\n\n----\n\n\[Chris\ Nelson\]\ said\ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/3ebbe18159a8efac?tvc=2&q=multiple+vwaits%|%these\ golden\ words%|%\]\ on\ \[comp.lang.tcl\]:\n\n''Multiple\ vwaits\ nest,\ they\ do\ not\ happen\ in\ parallel.\ \ The\ outermost\ vwait\ cannot\ complete\ until\ all\ others\ return.''\n\n----\n\n'''vwait\ forever''':\ ''Wish''\ has\ a\ built-in\ event\ loop.\ Tclsh\ has\ one\ too\ but\ enters\ that\ only\ on\ demand,\ for\ which\ the\ \[idiom\]\ is\ to\ write\ at\ the\ end\ of\ code\n\n======\nvwait\ forever\n======\n\n\nSee\ the\ note\ below\ about\ namespaces\ -\ missing\ this\ note\ results\ in\ problems\ that\ occur\ quite\ commonly!\n\n\n----\n\n'''Timeout\ for\ vwait''':\ Wai\ Shun\ Au\ wrote\ in\ \[comp.lang.tcl\]:\n**\ Timeout\ for\ `vwait`\ **\nafter\ 30000\ \{set\ a\ \$a\}\nvwait\ a\n======\n\nThis\ way\ it\ would\ wait\ for\ ''a''\ to\ be\ changed\ or\ until\ 30\ seconds\ is\ up.\n\n\[Jeffrey\ Hobbs\]\ commented:\ \ You\ found\ the\ standard\ way,\ but\ you\ have\ to\ go\ a\nbit\ further\ to\ avoid\ weird\ bugs.\ \ Cache\ the\ \[after\]\ id\ and\ make\ sure\ to\ cancel\nit\ following\ the\ ''vwait''\ (no\ \[catch\]\ needed\ -\ if\ the\ after\ id\ no\ longer\nexists,\ because\ it\ was\ triggered,\ ''after\ cancel''\ doesn't\ care).\ \ That\ way\ you\nwon't\ get\ ''a''\ being\ reset\ no\ matter\ what\ in\ 30\ secs.\n\n----\n\n\[DKF\]:\ \ You\ can\ '''`vwait`\ on\ several\ variables\ simultaneously'''\ as\ long\ as\nall\ those\ variables\ are\ in\ the\ same\ array,\ and\ you\ are\ happy\ for\ any\ set\ of\ the\narray\ to\ cause\ the\ `vwait`\ to\ terminate.\ \ Do\ this\ by\ making\ the\ `vwait`\ be\non\ the\ overall\ array,\ and\ not\ any\ element\ of\ it.\n\n----\n\n\[BBH\]:\ \ Actually,\ you\ can\ combine\ the\ multiple\ variable\ &\ timeout\ nicely\nwithout\ the\ variables\ having\ to\ be\ related,\ and\ the\ timer\ won't\ affect\ the\nactual\ variables,\ Demonstrated\ by\ this\ code\ taken\ from\ dissussion\ on\n\[comp.lang.tcl\]\ (most\ of\ the\ original\ work\ by\ \[Donald\ Porter\],\ that\ I\ntweaked\ a\ little\ to\ add\ timeout\ option).\n\nkenstir:\ \ I\ have\ further\ tweaked\ this\ version\ of\ waitForAny\ that\ returns\ the\nvar\ (or\ vars)\ that\ got\ set\ during\ the\ vwait.\ \ This\ allows\ you\ to\ build\ a\ robust\nasynchronous\ queue.\ \ I'm\ submitting\ it\ as\ a\ patch\ to\ tcllib.sourceforge.net\nalong\ with\ tests.\n\n======\nnamespace\ eval\ control\ \{\n\ \ \ \ namespace\ export\ waitForAny\n\ \ \ \ variable\ waitForAnyKey\ 0\n\n\ \ \ \ #\ new\ \"vwait\"\ that\ takes\ multiple\ variables\ and/or\ optional\ timeout\n\ \ \ \ #\ usage:\ \ waitForAny\ ?timeout?\ variable\ ?variable\ ...?\n\ \ \ \ proc\ waitForAny\ \{args\}\ \{\n\ \ \ \ \ \ \ \ variable\ waitForAnyArray\n\ \ \ \ \ \ \ \ variable\ waitForAnyKey\n\n\ \ \ \ \ \ \ \ #\ if\ first\ arg\ is\ a\ number,\ then\ that\ is\ max\ wait\ time\n\ \ \ \ \ \ \ \ if\ \{\[string\ is\ int\ \[lindex\ \$args\ 0\]\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ timeout\ \[lindex\ \$args\ 0\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ create\ trigger\ script\ that\ will\ cause\ vwait\ to\ fall\ thru\n\ \ \ \ \ \ \ \ #\ (trailing\ comment\ is\ to\ eat\ appended\ args\ in\ trace\ command)\n\ \ \ \ \ \ \ \ set\ index\ \"Key\[incr\ waitForAnyKey\]\"\n\ \ \ \ \ \ \ \ set\ trigger\ \"\[namespace\ code\ \[list\ set\ waitForAnyArray(\$index)\ 1\]\]\ \;#\"\n\n\ \ \ \ \ \ \ \ #\ create\ trace\ to\ trip\ trigger\n\ \ \ \ \ \ \ \ foreach\ var\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ uplevel\ \\#0\ \[list\ trace\ variable\ \$var\ w\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ set\ timer\ is\ user\ requested\ one\n\ \ \ \ \ \ \ \ if\ \{\[info\ exists\ timeout\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ timerId\ \[after\ \$timeout\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ vwait\ \[namespace\ which\ -variable\ waitForAnyArray\](\$index)\n\n\ \ \ \ \ \ \ \ #\ remove\ all\ traces\n\ \ \ \ \ \ \ \ foreach\ var\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ uplevel\ \\#0\ \[list\ trace\ vdelete\ \$var\ w\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ cancel\ timer\n\ \ \ \ \ \ \ \ if\ \[info\ exists\ timerId\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ after\ cancel\ \$timerId\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ cleanup\n\ \ \ \ \ \ \ \ unset\ waitForAnyArray(\$index)\n\ \ \ \ \}\n\}\n======\n\n\n----\n\n'''vwait\ in\ namespaces:'''\ The\ varName\ must\ be\ globally\ qualified\ as\ if\ in\ a\n\n======\nnamespace\ eval\ foo\ \{\n\ \ \ \ vwait\ bar\ \ \ \ \ \ \ \ \;#\ will\ never\ fire\n\ \ \ \ vwait\ ::foo::bar\ \;#\ does\ the\ job\n\n\ \ \ \ variable\ bar\ \ \ \ \ \;#\ These\ two\ lines\ also\ do\ the\ job\n\ \ \ \ vwait\ \[namespace\ which\ -variable\ bar\]\ \ \ \ \;#\ DGP\n\}\ \;#\ RS\n======\n\n**\ Avoiding\ Nested\ Calls\ to\ `vwait`\ **\n----\nA\ majority\ of\ the\ coding\ questions\ received\ in\ \[comp.lang.tcl\]\nabout\ `vwait`\ appear\ to\ result\ from\ deep\ misunderstandings\ of\ the\ command\ (as\nopposed\ to\ mere\ syntactic\ confusion,\ for\ example).\ \[Bruce\ Hartweg\]\ has\ rightly\nadvised\ that\ its\ proper\ use\ is\ restricted:\ \ \"IMHO\ vwaits\ shouldn't\ be\ used\ too\nmuch\ (the\ nesting\ issue\ creates\ unexpected\ results)\ because\ you\ are\ trying\ to\nforce\ a\ synchronous\ approach\n\nin\ an\ event\ world,\ it\ is\ much\ better\ to\ keep\ everything\ event\ driven.\nOccasionally\ for\ simple\ things\ (like\ dialogs)\ to\ use\ a\ vwait\ to\ avoid\ having\ to\nbreak\ something\ the\ has\ a\ couple\ of\ file\ picks\ and/or\ confirmations\ into\numpteen\ parts\ has\ its\ place.\"\ \ \[KBK\]\ agrees\ that\ the\ \[Tcl\ event\ loop\]\ is\ widely\nmisunderstood\ and\ discusses\ related\ issues\ in\ \[Update\ considered\ harmful\]\ and\nthe\ pages\ to\ which\ it\ links.\n\n----\n\nPackages\ such\ as\ \[Tk\]\ and\ \[tclsvc\]\ themselves\ call\ `vwait`.\ \ To\ avoid\ nested\ `vwait`\ calls:\nThis\ little\ program\ demonstrates\ what\ \[Chris\ Nelson\]\ stated\ above\ (vwaits\ nest):\n======\nset\ ::time\ 0\nset\ ::a\ 0\nset\ ::b\ 0\n\nproc\ a_vwait\ \{\}\ \{\n\ \ \ \ puts\ \"Waiting\ 15\ sec\ for\ ::a\"\n\ \ \ \ vwait\ ::a\n\ \ \ \ puts\ \"::a\ set\"\n\}\n\nproc\ b_vwait\ \{\}\ \{\n\ \ \ \ puts\ \"Waiting\ 30\ sec\ for\ ::b\"\n\ \ \ \ vwait\ ::b\n\ \ \ \ puts\ \"::b\ set\"\n\}\n\n\nproc\ timer\ \{\}\ \{\n\ \ \ \ incr\ ::time\ 1\n\ \ \ \ puts\ \"\$::time\ sec\"\n\ \ \ \ if\ \{\$::time\ ==\ 35\}\ \{\n\ \ \ \ \ \ \ \ exit\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ after\ 1000\ timer\n\ \ \ \ \}\n\}\n\nafter\ 1\ a_vwait\nafter\ 5\ b_vwait\nafter\ 10\ timer\n\nafter\ 15000\ \{set\ ::a\ 0\}\nafter\ 30000\ \{set\ ::b\ 0\}\n\nvwait\ forever\n======\n\nAlthough\ there\ are\ two\ events\ set\ to\ trigger\ in\ 15\ sec\ and\ 30\ sec\ respectively,\ the\ 30\ sec\ vwait\ blocks\ the\ 15\ sec\ vwait,\ opposite\ of\ the\ intuitive\ reaction\ to\ this\ program.\n\nWhen\ you\ understand\ this\ code\ snippit,\ you'll\ be\ free\ from\ the\ dangers\ of\ haphazardly\ using\ vwait.\n\n----\n\[Marty\ Backe\]\n2002-08-15\n\n\nChristian\ Klugesherz\ 2009-12-04:\ \ To\ understand\ what\ really\ happens,\ just\nreplace\ the\ above\ timer\ procedure,\ by\ adding\ \[after\ info\]\ which\ shows\ the\ existing\nreplace\ the\ above\ timer\ proc,\ by\ adding\ \[after\ info\]\ which\ shows\ the\ existing\n\n======\nproc\ timer\ \{\}\ \{\n\ \ \ \ incr\ ::time\ 1\n\ \ \ \ puts\ \"\$::time\ sec\"\n\ \ \ \ puts\ \[after\ info\]\n\ \ \ \ if\ \{\$::time\ ==\ 35\}\ \{\n\ \ \ \ \ \ \ \ exit\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ after\ 1000\ timer\n\ \ \ \ \ \ \ \ #puts\ \[after\ info\]\n\ \ \ \ \}\n\}\n======\n\n----\n\nPeter\ Newman\ 2004-03-09:\ '''Wish\ Is\ Buggy!'''\ It\ seems\ to\ me\ that\ all\ these\nproblems\ with\ `vwait`,\ `\[tkwait\]`,\ `\[update\]`\ and\ ''people\ not\ understanding\ the\nproblems\ with\ \[vwait\],\ \[tkwait\],\ \[update\]\ and\ ''people\ not\ understanding\ the\ndesign\ of\ wish\ -\ in\ that\ it\ automatically\ appends\ the\ event\ loop\ onto\ the\nscripts\ it\ runs.\n\nTake\ the\ following\ \"Hello\ World\"\ program:-\n\n======\npack\ \[button\ .mybutton\ -text\ \{Hello\ World!\}\ -command\ exit\]\ \;\n======\n\nIt's\ buggy!\ I\ forget\ to\ call\ the\ event\ loop.\ So\ it\ does\ nothing.\ But\ wish\ will\nrun\ it\ Ok.\ So\ wish's\ bug\ cancels\ out\ my\ bug\ -\ and\ the\ bug\ in\ my\ program\ gets\noverlooked.\ Almost\ all\ programs\ on\ this\ Wiki\ are\ like\ that.\ As\ written\ by\ the\nprogrammer,\ there's\ no\ call\ to\ the\ event\ loop.\n\nNow\ with\ \"Hello\ World\"\ programs\ it\ probably\ doesn't\ matter.\ But\ with\ncomplicated\ real\ world\ programs\ the\ event\ loop\ matters\ a\ lot.\ But\ wish\ permits\nand\ encourages\ Tcl\ programmers\ to\ ignore\ the\ event\ loop.\ We\ only\ worry\ about\ it\nwhen\ the\ roof\ caves\ in!\ Then\ we\ find\ out\ we\ haven't\ got\ a\ clue\ how\ it\ works.\ Or\nhow\ to\ write\ code\ that\ handles\ the\ event\ loop\ properly.\ (Then\ it's\ thank\ God\nfor\ pages\ like\ this\ on\ the\ Wiki,\ as\ you\ try\ and\ figure\ it\ out.)\n\nThe\ solution\ is\ to\ get\ rid\ of\ the\ auto-appending\ the\ event\ loop\ from\ wish.\ And\nforce\ Tcl\ programmers\ to\ learn\ and\ think\ about\ the\ event\ loop\ from\ the\ first,\nand\ with\ every\ subsequent,\ script\ they\ write.\n\n----\n\n\[schlenk\]:\ \ Not\ really,\ wish\ is\ ok,\ but\ there\ are\ tendencies\ to\ get\ rid\ of\ it\nin\ favor\ of\ tclsh\ and\ package\ require\ Tk.\ Tk\ starts\ the\ event\ loop\ by\ default,\nso\ there\ isn't\ any\ bug.\ If\ you\ use\ Tk,\ you\ have\ a\ running\ event\ loop.\ Why\ make\nthings\ more\ complex\ by\ forcing\ people\ to\ require\ the\ event\ loop\ explicitly\ if\nit\ is\ clear\ they\ need\ it?\n\n----\n\n\[PS\]\ 2004-03-09:\ \ I'd\ have\ to\ agree\ with\ schlenk\ that\ the\ current\ wish\nbehaviour\ is\ the\ right\ thing,\ but\ the\ whole\ reason\ I\ moved\ the\ 'check\ for\ tk'\nremark\ to\ the\ top\ of\ the\ page\ is\ that\ I\ was\ bitten\ by\ it\ *again*.\ Currently,\ if\nyou\ want\ the\ 'default'\ Tcl\ event\ loop,\ the\ recommended/standard\ way\ seems\ to\ be\nto\ call\ `\[vwait\ forever\]`.\ But\ there\ are\ more\ and\ more\ script\ out\ there\ that\nto\ call\ \[\[vwait\ forever\]\].\ But\ there\ are\ more\ and\ more\ script\ out\ there\ that\nemerge.\ Is\ checking\ for\ tk\ and\ tclsvr\ enough\ right\ now?\ Probably.\ Will\ it\ be\ in\nthe\ future?\ Probably\ not.\ What\ we\ really\ need\ is\ a\ function\ that\ I\ can\ call\ to\nstart\ the\ event\ loop,\ which\ -by\ default-\ will\ never\ return.\ Something\ like:\n\n======\ninterp\ eventloop\n\n#\ or\ just\neventloop\n\n#\ and\ for\ the\ special\ case\ which\ needs\ it:\n\n\{\ ...\ appInitCode\ \}\neventloop\ -pleaseReturnIfPossible\n\{\ ...\ appCleanupCode\ \}\n======\n\nOr\ bastardise\ `vwait`\ to\ do\ the\ same,\ when\ called\ with\ forever\ as\ its\ first\nargument\ (which\ would\ probably\ break\ things).\ And\ maybe\ \[\[interp\ eventloop\n\{script\}\]\]\ to\ provide\ the\ appropriate\ eventloop\ handler\ code.\n\n----\n\n\[NEM\]:\ \ It\ is\ worth\ pointing\ out\ here\ that\ \[tk_messageBox\]\ calls\ vwait\ninternally\ (at\ least\ on\ UNIX).\ This\ has\ been\ a\ cause\ of\ several\ bugs\ in\ event\ndriven\ code\ I\ have\ written.\ All\ the\ advice\ given\ on\ this\ page\ about\ not\ calling\nvwait\ should\ also\ apply\ to\ tk_messageBox.\ In\ particular,\ don't\ do\ something\nlike\ the\ following:\n\n======\nfileevent\ \$fd\ readable\ \[list\ readdata\ \$fd\]\nproc\ readdata\ fd\ \{\n\ \ \ \ global\ line\n\ \ \ \ set\ line\ \[gets\ \$fd\]\n\ \ \ \ #\ Some\ other\ stuff...\n\ \ \ \ tk_messageBox\ ...\n\ \ \ \ #\ Some\ more\ stuff...\n\}\n======\n\nThe\ problem\ is\ that\ the\ nested\ `vwait`\ means\ that\ `readdata`\ will\nlikely\ be\ re-entered,\ causing\ all\ kinds\ of\ mayhem\ to\ ensue.\ The\ way\ I\ coded\naround\ this\ was\ to\ implement\ my\ own\ dialog\ box\ code,\ which\ took\ a\ callback:\n\n======\nmessagebox\ ...\ -command\ \[list\ dosomething\ ...\]\n======\n\nBut\ then,\ you\ still\ have\ to\ deal\ with\ what\ to\ do\ with\ events\ that\ come\ in\ while\nthe\ dialog\ is\ still\ raised.\ (Do\ you\ process\ them,\ or\ should\ you\ wait\ until\ the\ndialog\ box\ is\ dismissed?)\ I\ never\ really\ decided\ what\ the\ ''correct''\ behaviour\nin\ this\ situation\ would\ be.\n\n----\n\n\[CMcC\]:\ \ In\ case\ it\ matters\ to\ you,\ this\ quickie\ will\ prevent\ recursive\ `vwait`\ while\ permitting\ iterative\ `vwait`:\n\n======\nrename\ ::vwait\ ::vwait_org\nproc\ ::vwait\ varname\ \{\n\ \ \ \ rename\ ::vwait\ ::no_vwait\n\ \ \ \ set\ result\ \[uplevel\ 1\ \[list\ vwait_org\ \$varname\]\]\n\ \ \ \ rename\ ::no_vwait\ ::vwait\n\ \ \ \ return\ \$result\n\}\n======\n\n\n**\ Subtleties\ with\ `vwait`\ and\ `\[unset\]`\ **\n**\ Subtleties\ with\ \[vwait\]\ and\ \[unset\]\ **\nTypical\ usage\ examples\ of\ `vwait`\ involve\ waiting\ until\ an\ unset\ variable\ is\ `\[set\]`\ or\ an\ existing\ variable\ is\ updated.\ \ The\ wording\ used\ in\ the\ `vwait`\ manual\ page\ is\ consistent\ with\ this\ pattern:\ it\ runs\ the\ event\ loop\ \"until\ a\ variable\ is\ written\",\ and\ also\ \"It\ continues\ processing\ events\ until\ some\ event\ handler\ sets\ the\ value\ of\ the\ global\ variable\".\ \ Apparently,\ however,\ \[unset%|%unsetting\]\ the\ variable\ will\ also\ cause\ `vwait`\ to\ return!\ \ For\ example:\nTypical\ usage\ examples\ of\ \[vwait\]\ involve\ waiting\ until\ an\ unset\ variable\ is\ \[set\]\ or\ an\ existing\ variable\ is\ updated.\ \ The\ wording\ used\ in\ the\ \[vwait\]\ manual\ page\ is\ consistent\ with\ this\ pattern:\ it\ runs\ the\ event\ loop\ \"until\ a\ variable\ is\ written\",\ and\ also\ \"It\ continues\ processing\ events\ until\ some\ event\ handler\ sets\ the\ value\ of\ the\ global\ variable\".\ \ Apparently,\ however,\ \[unset\]ting\ the\ variable\ will\ also\ cause\ the\ \[vwait\]\ to\ return!\ \ For\ example:\n======\nset\ ready\ 1\nafter\ 3000\ \{unset\ ready\}\nvwait\ ready\n#\ Returns\ after\ 3\ s.\n======\n\nI\ found\ this\ a\ bit\ surprising,\ and\ counter-intuitive.\ \ If\ using\ vwait\ to\ implement\ blocking\ of\ a\ shared\ resource,\ for\ example,\ this\ means\ that\ you\ can't\ just\ `vwait`,\ you\ have\ to\ do\ something\ like:\nI\ found\ this\ a\ bit\ surprising,\ and\ counter-intuitive.\ \ If\ using\ vwait\ to\ implement\ blocking\ of\ a\ shared\ resource,\ for\ example,\ this\ means\ that\ you\ can't\ just\ \[vwait\],\ you\ have\ to\ do\ something\ like:\n======\nwhile\ \{!\[info\ exists\ ready\]\}\ \{vwait\ ready\}\n======\n\nor\n\n======\nwhile\ \{!\$ready\}\ \{vwait\ ready\}\n======\n\n(To\ me,\ having\ to\ use\ a\ loop\ like\ this\ seems\ to\ go\ against\ Tcl's\ event-driven\ style.)\n\nIntriguingly,\ even\ if\ the\ unset\ fails\ (if\ the\ variable\ does\ not\ exist),\ `vwait`\ will\ still\ return:\nIntriguingly,\ even\ if\ the\ unset\ fails\ (if\ the\ variable\ does\ not\ exist),\ \[vwait\]\ will\ still\ return:\n======\nafter\ 3000\ \{catch\ \{unset\ nonexistent\}\}\nvwait\ nonexistent\n#\ Returns\ after\ 3\ s!\n======\n\n----\n\nKen:\ I\ have\ one\ a\ problem\ with\ the\ follow\ code.\ I\ intended\ to\ transfer\ control\nKen:\ I\ have\ one\ a\ problem\ with\ the\ follow\ code,\ i\ intended\ to\ transfer\ control\nto\ halt\ the\ procession\ of\ one\ function\ and\ go\ to\ other\ function\ which\ would\ncall\ it\ again?\ Below\ is\ the\ code\n\n======\nset\ Flag\ 0\nif\ \{\$Flag\}\ \{\n\ \ \ \ continue\n\}\ else\ \{\n\ \ \ \ vwait\ Flag\n\}\n======\n\nbut\ for\ this\ code\ it\ seems\ that\ it\ would\ prompt\ an\ error\ code\ which\ is\ \"can't\nwait\ for\ variable\ Flag\"\ if\ flag\ stays\ at\ 0.\ So\ how\ should\ i\ proceed\ so\ that\ it\nwould\ not\ prompt\ this\ error\ code.\n\n regexp2} CALL {my render vwait '''`\[http://www.tcl.tk/man/tcl/TclCmd/vwait.htm%|%vwait\]`''',\ a\ \[Tcl\ Commands%|%built-in\]\ Tcl\ command,\ enters\ the\ \[Tcl\ event\ loop%|%event\ loop\]\ and\ only\ returns\ once\nthe\ indicated\ variable\ is\ modified.\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''vwait'''\ ''varName''\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/vwait.htm%|%official\ man\ page\]:\ \ \ \n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[event-oriented\ programming\]:\ \ \ \n\n\ \ \ \[Tcl\ event\ loop\]:\ \ \ \n\n\ \ \ `\[update\]`:\ \ \ \n\ \ \ \[update\]:\ \ \ \n\ \ \ \[Update\ considered\ harmful\]:\ \ \ \n\n\n\n**\ Description\ **\n\n'''`vwait`'''\ enters\ the\ Tcl\ \[event\ loop\],\ and\ as\ events\ are\ processed,\ monitors\ the\ variable\ named\ by\ ''varName''\ for\ changes,\ \[return%|%returning\]\ only\ once\ some\ event\ handler\ modifies\ ''varName''.\ \ Thus,\ `vwait`\ effectively\ blocks\ execution\ of\ the\ foreground\ script\ until\ a\ modification\ of\ ''varName''\ occurs.\nAs\ soon\ as\ the\ event\ handler\ that\ modifies\ ''varName''\ returns,\ `vwait`\ returns.\ ''VarName''\ is\ resolved\ relative\ to\ the\ \[global\]\ scope,\ so\ the\ following\ pattern\ is\ often\ useful:\n\n======\nvwait\ \[namespace\ which\ -variable\ foo\]\n======\n\nSince\ the\ event\ handler\ that\ stores\ a\ value\ to\ ''varName''\ continues\ to\ completion\ before\ `vwait`\ can\ return,\ some\ time\ can\ pass\ betweeen\ when\ a\ value\ is\ stored\ to\ ''varName''\ and\ when\ `vwait`\ returns.\ \nFor\ example,\ if\ an\ event\ handler\ sets\n''varName''\ and\ then\ itself\ calls\ '''vwait'''\ to\ wait\ for\ a\ different\ variable,\nthen\ the\ outer\ `vwait`\ depends\ on\ the\ inner\ `vwait`,\ and\ may\ not\ return\ for\ a\ long\ time.\ \ In\ general,\ nested\ calls\ to\ `vwait`\ should\ be\ avoided.\ \n\n\n\n**\ `vwait\ forever`\ **\n**\ Avoiding\ Conflicting\ \[vwait\]'s\ **\n''Wish''\ has\ a\ built-in\ event\ loop.\ Tclsh\ has\ one\ too\ but\ enters\ that\ only\ on\ demand,\ for\ which\ the\ \[idiom\]\ is\ to\ write\ at\ the\ end\ of\ code\nPackages\ such\ as\ \[Tk\]\ and\ \[tclsvc\]\ themselves\ call\ \[vwait\]\ \ To\ avoid\ conflicting\ \[vwait\]'s:\n======\nvwait\ forever\nif\ \{!\[info\ exists\ tk_version\]\ &&\ !\[info\ exists\ tcl_service\]\}\ \{\ ...\n======\n\n\[PS\]\ 2004-03-09:\ \ For\ example,\ this\ script,\ which\ implements\ a\ TCP\ server\ in\ntclsh\ and\ wish,\ will\ not\ exit\ properly\ when\ you\ close\ its\ main\ window:\n\n======\nproc\ accept\ \{\ channel\ peer\ port\ \}\ \{\n\ \ \ \ close\ \$channel\n\}\nsocket\ -server\ accept\ 5000\n======\n\n\[RS\]:\ \ ''forever''\ being\ the\ name\ of\ a\ variable\ that\ is\ presumably\ never\ used,\ but\ you\ can\ set\ ''forever''\ to\ any\ value\ to\ terminate\ such\ a\ Tcl\ script).\nAfter\ you\ close\ the\ window,\ the\ wish\ app\ does\ not\ exit,\ but\ remains\ fully\ active\ in\ memory.\n\n\[DGP\]:\ \ This\ discussion\ is\ essentially\ another\nvote\ in\ favor\ of\ \[http://sf.net/tracker/?func=detail&aid=456548&group_id=12997&atid=362997%|%Tk\ Feature\ Request\ 456548\].\n\nThe\ flaw\ here\ is\ in\ Tk's\ continued\ assumptions\ about\ being\ in\ wish,\ rather\ than\nbeing\ an\ independent\ package\ that\ might\ be\ loaded\ into\ any\ Tcl\ interp.\ \ There's\nnothing\ wrong\ with\ \[\[vwait\]\]\ (at\ least\ nothing\ revealed\ in\ this\ discussion.\ :)\n).\n\n----\n\n\[Chris\ Nelson\]\ said\ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/3ebbe18159a8efac?tvc=2&q=multiple+vwaits%|%these\ golden\ words%|%\]\ on\ \[comp.lang.tcl\]:\n\n''Multiple\ vwaits\ nest,\ they\ do\ not\ happen\ in\ parallel.\ \ The\ outermost\ vwait\ cannot\ complete\ until\ all\ others\ return.''\n\n----\n\n'''vwait\ forever''':\ ''Wish''\ has\ a\ built-in\ event\ loop.\ Tclsh\ has\ one\ too\ but\ enters\ that\ only\ on\ demand,\ for\ which\ the\ \[idiom\]\ is\ to\ write\ at\ the\ end\ of\ code\n\n======\nvwait\ forever\n======\n\n\nSee\ the\ note\ below\ about\ namespaces\ -\ missing\ this\ note\ results\ in\ problems\ that\ occur\ quite\ commonly!\n\n\n----\n\n'''Timeout\ for\ vwait''':\ Wai\ Shun\ Au\ wrote\ in\ \[comp.lang.tcl\]:\n**\ Timeout\ for\ `vwait`\ **\nafter\ 30000\ \{set\ a\ \$a\}\nvwait\ a\n======\n\nThis\ way\ it\ would\ wait\ for\ ''a''\ to\ be\ changed\ or\ until\ 30\ seconds\ is\ up.\n\n\[Jeffrey\ Hobbs\]\ commented:\ \ You\ found\ the\ standard\ way,\ but\ you\ have\ to\ go\ a\nbit\ further\ to\ avoid\ weird\ bugs.\ \ Cache\ the\ \[after\]\ id\ and\ make\ sure\ to\ cancel\nit\ following\ the\ ''vwait''\ (no\ \[catch\]\ needed\ -\ if\ the\ after\ id\ no\ longer\nexists,\ because\ it\ was\ triggered,\ ''after\ cancel''\ doesn't\ care).\ \ That\ way\ you\nwon't\ get\ ''a''\ being\ reset\ no\ matter\ what\ in\ 30\ secs.\n\n----\n\n\[DKF\]:\ \ You\ can\ '''`vwait`\ on\ several\ variables\ simultaneously'''\ as\ long\ as\nall\ those\ variables\ are\ in\ the\ same\ array,\ and\ you\ are\ happy\ for\ any\ set\ of\ the\narray\ to\ cause\ the\ `vwait`\ to\ terminate.\ \ Do\ this\ by\ making\ the\ `vwait`\ be\non\ the\ overall\ array,\ and\ not\ any\ element\ of\ it.\n\n----\n\n\[BBH\]:\ \ Actually,\ you\ can\ combine\ the\ multiple\ variable\ &\ timeout\ nicely\nwithout\ the\ variables\ having\ to\ be\ related,\ and\ the\ timer\ won't\ affect\ the\nactual\ variables,\ Demonstrated\ by\ this\ code\ taken\ from\ dissussion\ on\n\[comp.lang.tcl\]\ (most\ of\ the\ original\ work\ by\ \[Donald\ Porter\],\ that\ I\ntweaked\ a\ little\ to\ add\ timeout\ option).\n\nkenstir:\ \ I\ have\ further\ tweaked\ this\ version\ of\ waitForAny\ that\ returns\ the\nvar\ (or\ vars)\ that\ got\ set\ during\ the\ vwait.\ \ This\ allows\ you\ to\ build\ a\ robust\nasynchronous\ queue.\ \ I'm\ submitting\ it\ as\ a\ patch\ to\ tcllib.sourceforge.net\nalong\ with\ tests.\n\n======\nnamespace\ eval\ control\ \{\n\ \ \ \ namespace\ export\ waitForAny\n\ \ \ \ variable\ waitForAnyKey\ 0\n\n\ \ \ \ #\ new\ \"vwait\"\ that\ takes\ multiple\ variables\ and/or\ optional\ timeout\n\ \ \ \ #\ usage:\ \ waitForAny\ ?timeout?\ variable\ ?variable\ ...?\n\ \ \ \ proc\ waitForAny\ \{args\}\ \{\n\ \ \ \ \ \ \ \ variable\ waitForAnyArray\n\ \ \ \ \ \ \ \ variable\ waitForAnyKey\n\n\ \ \ \ \ \ \ \ #\ if\ first\ arg\ is\ a\ number,\ then\ that\ is\ max\ wait\ time\n\ \ \ \ \ \ \ \ if\ \{\[string\ is\ int\ \[lindex\ \$args\ 0\]\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ timeout\ \[lindex\ \$args\ 0\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ create\ trigger\ script\ that\ will\ cause\ vwait\ to\ fall\ thru\n\ \ \ \ \ \ \ \ #\ (trailing\ comment\ is\ to\ eat\ appended\ args\ in\ trace\ command)\n\ \ \ \ \ \ \ \ set\ index\ \"Key\[incr\ waitForAnyKey\]\"\n\ \ \ \ \ \ \ \ set\ trigger\ \"\[namespace\ code\ \[list\ set\ waitForAnyArray(\$index)\ 1\]\]\ \;#\"\n\n\ \ \ \ \ \ \ \ #\ create\ trace\ to\ trip\ trigger\n\ \ \ \ \ \ \ \ foreach\ var\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ uplevel\ \\#0\ \[list\ trace\ variable\ \$var\ w\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ set\ timer\ is\ user\ requested\ one\n\ \ \ \ \ \ \ \ if\ \{\[info\ exists\ timeout\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ timerId\ \[after\ \$timeout\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ vwait\ \[namespace\ which\ -variable\ waitForAnyArray\](\$index)\n\n\ \ \ \ \ \ \ \ #\ remove\ all\ traces\n\ \ \ \ \ \ \ \ foreach\ var\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ uplevel\ \\#0\ \[list\ trace\ vdelete\ \$var\ w\ \$trigger\]\n\ \ \ \ \ \ \ \ \}\n\n\ \ \ \ \ \ \ \ #\ cancel\ timer\n\ \ \ \ \ \ \ \ if\ \[info\ exists\ timerId\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ after\ cancel\ \$timerId\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ cleanup\n\ \ \ \ \ \ \ \ unset\ waitForAnyArray(\$index)\n\ \ \ \ \}\n\}\n======\n\n\n----\n\n'''vwait\ in\ namespaces:'''\ The\ varName\ must\ be\ globally\ qualified\ as\ if\ in\ a\n\n======\nnamespace\ eval\ foo\ \{\n\ \ \ \ vwait\ bar\ \ \ \ \ \ \ \ \;#\ will\ never\ fire\n\ \ \ \ vwait\ ::foo::bar\ \;#\ does\ the\ job\n\n\ \ \ \ variable\ bar\ \ \ \ \ \;#\ These\ two\ lines\ also\ do\ the\ job\n\ \ \ \ vwait\ \[namespace\ which\ -variable\ bar\]\ \ \ \ \;#\ DGP\n\}\ \;#\ RS\n======\n\n**\ Avoiding\ Nested\ Calls\ to\ `vwait`\ **\n----\nA\ majority\ of\ the\ coding\ questions\ received\ in\ \[comp.lang.tcl\]\nabout\ `vwait`\ appear\ to\ result\ from\ deep\ misunderstandings\ of\ the\ command\ (as\nopposed\ to\ mere\ syntactic\ confusion,\ for\ example).\ \[Bruce\ Hartweg\]\ has\ rightly\nadvised\ that\ its\ proper\ use\ is\ restricted:\ \ \"IMHO\ vwaits\ shouldn't\ be\ used\ too\nmuch\ (the\ nesting\ issue\ creates\ unexpected\ results)\ because\ you\ are\ trying\ to\nforce\ a\ synchronous\ approach\n\nin\ an\ event\ world,\ it\ is\ much\ better\ to\ keep\ everything\ event\ driven.\nOccasionally\ for\ simple\ things\ (like\ dialogs)\ to\ use\ a\ vwait\ to\ avoid\ having\ to\nbreak\ something\ the\ has\ a\ couple\ of\ file\ picks\ and/or\ confirmations\ into\numpteen\ parts\ has\ its\ place.\"\ \ \[KBK\]\ agrees\ that\ the\ \[Tcl\ event\ loop\]\ is\ widely\nmisunderstood\ and\ discusses\ related\ issues\ in\ \[Update\ considered\ harmful\]\ and\nthe\ pages\ to\ which\ it\ links.\n\n----\n\nPackages\ such\ as\ \[Tk\]\ and\ \[tclsvc\]\ themselves\ call\ `vwait`.\ \ To\ avoid\ nested\ `vwait`\ calls:\nThis\ little\ program\ demonstrates\ what\ \[Chris\ Nelson\]\ stated\ above\ (vwaits\ nest):\n======\nset\ ::time\ 0\nset\ ::a\ 0\nset\ ::b\ 0\n\nproc\ a_vwait\ \{\}\ \{\n\ \ \ \ puts\ \"Waiting\ 15\ sec\ for\ ::a\"\n\ \ \ \ vwait\ ::a\n\ \ \ \ puts\ \"::a\ set\"\n\}\n\nproc\ b_vwait\ \{\}\ \{\n\ \ \ \ puts\ \"Waiting\ 30\ sec\ for\ ::b\"\n\ \ \ \ vwait\ ::b\n\ \ \ \ puts\ \"::b\ set\"\n\}\n\n\nproc\ timer\ \{\}\ \{\n\ \ \ \ incr\ ::time\ 1\n\ \ \ \ puts\ \"\$::time\ sec\"\n\ \ \ \ if\ \{\$::time\ ==\ 35\}\ \{\n\ \ \ \ \ \ \ \ exit\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ after\ 1000\ timer\n\ \ \ \ \}\n\}\n\nafter\ 1\ a_vwait\nafter\ 5\ b_vwait\nafter\ 10\ timer\n\nafter\ 15000\ \{set\ ::a\ 0\}\nafter\ 30000\ \{set\ ::b\ 0\}\n\nvwait\ forever\n======\n\nAlthough\ there\ are\ two\ events\ set\ to\ trigger\ in\ 15\ sec\ and\ 30\ sec\ respectively,\ the\ 30\ sec\ vwait\ blocks\ the\ 15\ sec\ vwait,\ opposite\ of\ the\ intuitive\ reaction\ to\ this\ program.\n\nWhen\ you\ understand\ this\ code\ snippit,\ you'll\ be\ free\ from\ the\ dangers\ of\ haphazardly\ using\ vwait.\n\n----\n\[Marty\ Backe\]\n2002-08-15\n\n\nChristian\ Klugesherz\ 2009-12-04:\ \ To\ understand\ what\ really\ happens,\ just\nreplace\ the\ above\ timer\ procedure,\ by\ adding\ \[after\ info\]\ which\ shows\ the\ existing\nreplace\ the\ above\ timer\ proc,\ by\ adding\ \[after\ info\]\ which\ shows\ the\ existing\n\n======\nproc\ timer\ \{\}\ \{\n\ \ \ \ incr\ ::time\ 1\n\ \ \ \ puts\ \"\$::time\ sec\"\n\ \ \ \ puts\ \[after\ info\]\n\ \ \ \ if\ \{\$::time\ ==\ 35\}\ \{\n\ \ \ \ \ \ \ \ exit\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ after\ 1000\ timer\n\ \ \ \ \ \ \ \ #puts\ \[after\ info\]\n\ \ \ \ \}\n\}\n======\n\n----\n\nPeter\ Newman\ 2004-03-09:\ '''Wish\ Is\ Buggy!'''\ It\ seems\ to\ me\ that\ all\ these\nproblems\ with\ `vwait`,\ `\[tkwait\]`,\ `\[update\]`\ and\ ''people\ not\ understanding\ the\nproblems\ with\ \[vwait\],\ \[tkwait\],\ \[update\]\ and\ ''people\ not\ understanding\ the\ndesign\ of\ wish\ -\ in\ that\ it\ automatically\ appends\ the\ event\ loop\ onto\ the\nscripts\ it\ runs.\n\nTake\ the\ following\ \"Hello\ World\"\ program:-\n\n======\npack\ \[button\ .mybutton\ -text\ \{Hello\ World!\}\ -command\ exit\]\ \;\n======\n\nIt's\ buggy!\ I\ forget\ to\ call\ the\ event\ loop.\ So\ it\ does\ nothing.\ But\ wish\ will\nrun\ it\ Ok.\ So\ wish's\ bug\ cancels\ out\ my\ bug\ -\ and\ the\ bug\ in\ my\ program\ gets\noverlooked.\ Almost\ all\ programs\ on\ this\ Wiki\ are\ like\ that.\ As\ written\ by\ the\nprogrammer,\ there's\ no\ call\ to\ the\ event\ loop.\n\nNow\ with\ \"Hello\ World\"\ programs\ it\ probably\ doesn't\ matter.\ But\ with\ncomplicated\ real\ world\ programs\ the\ event\ loop\ matters\ a\ lot.\ But\ wish\ permits\nand\ encourages\ Tcl\ programmers\ to\ ignore\ the\ event\ loop.\ We\ only\ worry\ about\ it\nwhen\ the\ roof\ caves\ in!\ Then\ we\ find\ out\ we\ haven't\ got\ a\ clue\ how\ it\ works.\ Or\nhow\ to\ write\ code\ that\ handles\ the\ event\ loop\ properly.\ (Then\ it's\ thank\ God\nfor\ pages\ like\ this\ on\ the\ Wiki,\ as\ you\ try\ and\ figure\ it\ out.)\n\nThe\ solution\ is\ to\ get\ rid\ of\ the\ auto-appending\ the\ event\ loop\ from\ wish.\ And\nforce\ Tcl\ programmers\ to\ learn\ and\ think\ about\ the\ event\ loop\ from\ the\ first,\nand\ with\ every\ subsequent,\ script\ they\ write.\n\n----\n\n\[schlenk\]:\ \ Not\ really,\ wish\ is\ ok,\ but\ there\ are\ tendencies\ to\ get\ rid\ of\ it\nin\ favor\ of\ tclsh\ and\ package\ require\ Tk.\ Tk\ starts\ the\ event\ loop\ by\ default,\nso\ there\ isn't\ any\ bug.\ If\ you\ use\ Tk,\ you\ have\ a\ running\ event\ loop.\ Why\ make\nthings\ more\ complex\ by\ forcing\ people\ to\ require\ the\ event\ loop\ explicitly\ if\nit\ is\ clear\ they\ need\ it?\n\n----\n\n\[PS\]\ 2004-03-09:\ \ I'd\ have\ to\ agree\ with\ schlenk\ that\ the\ current\ wish\nbehaviour\ is\ the\ right\ thing,\ but\ the\ whole\ reason\ I\ moved\ the\ 'check\ for\ tk'\nremark\ to\ the\ top\ of\ the\ page\ is\ that\ I\ was\ bitten\ by\ it\ *again*.\ Currently,\ if\nyou\ want\ the\ 'default'\ Tcl\ event\ loop,\ the\ recommended/standard\ way\ seems\ to\ be\nto\ call\ `\[vwait\ forever\]`.\ But\ there\ are\ more\ and\ more\ script\ out\ there\ that\nto\ call\ \[\[vwait\ forever\]\].\ But\ there\ are\ more\ and\ more\ script\ out\ there\ that\nemerge.\ Is\ checking\ for\ tk\ and\ tclsvr\ enough\ right\ now?\ Probably.\ Will\ it\ be\ in\nthe\ future?\ Probably\ not.\ What\ we\ really\ need\ is\ a\ function\ that\ I\ can\ call\ to\nstart\ the\ event\ loop,\ which\ -by\ default-\ will\ never\ return.\ Something\ like:\n\n======\ninterp\ eventloop\n\n#\ or\ just\neventloop\n\n#\ and\ for\ the\ special\ case\ which\ needs\ it:\n\n\{\ ...\ appInitCode\ \}\neventloop\ -pleaseReturnIfPossible\n\{\ ...\ appCleanupCode\ \}\n======\n\nOr\ bastardise\ `vwait`\ to\ do\ the\ same,\ when\ called\ with\ forever\ as\ its\ first\nargument\ (which\ would\ probably\ break\ things).\ And\ maybe\ \[\[interp\ eventloop\n\{script\}\]\]\ to\ provide\ the\ appropriate\ eventloop\ handler\ code.\n\n----\n\n\[NEM\]:\ \ It\ is\ worth\ pointing\ out\ here\ that\ \[tk_messageBox\]\ calls\ vwait\ninternally\ (at\ least\ on\ UNIX).\ This\ has\ been\ a\ cause\ of\ several\ bugs\ in\ event\ndriven\ code\ I\ have\ written.\ All\ the\ advice\ given\ on\ this\ page\ about\ not\ calling\nvwait\ should\ also\ apply\ to\ tk_messageBox.\ In\ particular,\ don't\ do\ something\nlike\ the\ following:\n\n======\nfileevent\ \$fd\ readable\ \[list\ readdata\ \$fd\]\nproc\ readdata\ fd\ \{\n\ \ \ \ global\ line\n\ \ \ \ set\ line\ \[gets\ \$fd\]\n\ \ \ \ #\ Some\ other\ stuff...\n\ \ \ \ tk_messageBox\ ...\n\ \ \ \ #\ Some\ more\ stuff...\n\}\n======\n\nThe\ problem\ is\ that\ the\ nested\ `vwait`\ means\ that\ `readdata`\ will\nlikely\ be\ re-entered,\ causing\ all\ kinds\ of\ mayhem\ to\ ensue.\ The\ way\ I\ coded\naround\ this\ was\ to\ implement\ my\ own\ dialog\ box\ code,\ which\ took\ a\ callback:\n\n======\nmessagebox\ ...\ -command\ \[list\ dosomething\ ...\]\n======\n\nBut\ then,\ you\ still\ have\ to\ deal\ with\ what\ to\ do\ with\ events\ that\ come\ in\ while\nthe\ dialog\ is\ still\ raised.\ (Do\ you\ process\ them,\ or\ should\ you\ wait\ until\ the\ndialog\ box\ is\ dismissed?)\ I\ never\ really\ decided\ what\ the\ ''correct''\ behaviour\nin\ this\ situation\ would\ be.\n\n----\n\n\[CMcC\]:\ \ In\ case\ it\ matters\ to\ you,\ this\ quickie\ will\ prevent\ recursive\ `vwait`\ while\ permitting\ iterative\ `vwait`:\n\n======\nrename\ ::vwait\ ::vwait_org\nproc\ ::vwait\ varname\ \{\n\ \ \ \ rename\ ::vwait\ ::no_vwait\n\ \ \ \ set\ result\ \[uplevel\ 1\ \[list\ vwait_org\ \$varname\]\]\n\ \ \ \ rename\ ::no_vwait\ ::vwait\n\ \ \ \ return\ \$result\n\}\n======\n\n\n**\ Subtleties\ with\ `vwait`\ and\ `\[unset\]`\ **\n**\ Subtleties\ with\ \[vwait\]\ and\ \[unset\]\ **\nTypical\ usage\ examples\ of\ `vwait`\ involve\ waiting\ until\ an\ unset\ variable\ is\ `\[set\]`\ or\ an\ existing\ variable\ is\ updated.\ \ The\ wording\ used\ in\ the\ `vwait`\ manual\ page\ is\ consistent\ with\ this\ pattern:\ it\ runs\ the\ event\ loop\ \"until\ a\ variable\ is\ written\",\ and\ also\ \"It\ continues\ processing\ events\ until\ some\ event\ handler\ sets\ the\ value\ of\ the\ global\ variable\".\ \ Apparently,\ however,\ \[unset%|%unsetting\]\ the\ variable\ will\ also\ cause\ `vwait`\ to\ return!\ \ For\ example:\nTypical\ usage\ examples\ of\ \[vwait\]\ involve\ waiting\ until\ an\ unset\ variable\ is\ \[set\]\ or\ an\ existing\ variable\ is\ updated.\ \ The\ wording\ used\ in\ the\ \[vwait\]\ manual\ page\ is\ consistent\ with\ this\ pattern:\ it\ runs\ the\ event\ loop\ \"until\ a\ variable\ is\ written\",\ and\ also\ \"It\ continues\ processing\ events\ until\ some\ event\ handler\ sets\ the\ value\ of\ the\ global\ variable\".\ \ Apparently,\ however,\ \[unset\]ting\ the\ variable\ will\ also\ cause\ the\ \[vwait\]\ to\ return!\ \ For\ example:\n======\nset\ ready\ 1\nafter\ 3000\ \{unset\ ready\}\nvwait\ ready\n#\ Returns\ after\ 3\ s.\n======\n\nI\ found\ this\ a\ bit\ surprising,\ and\ counter-intuitive.\ \ If\ using\ vwait\ to\ implement\ blocking\ of\ a\ shared\ resource,\ for\ example,\ this\ means\ that\ you\ can't\ just\ `vwait`,\ you\ have\ to\ do\ something\ like:\nI\ found\ this\ a\ bit\ surprising,\ and\ counter-intuitive.\ \ If\ using\ vwait\ to\ implement\ blocking\ of\ a\ shared\ resource,\ for\ example,\ this\ means\ that\ you\ can't\ just\ \[vwait\],\ you\ have\ to\ do\ something\ like:\n======\nwhile\ \{!\[info\ exists\ ready\]\}\ \{vwait\ ready\}\n======\n\nor\n\n======\nwhile\ \{!\$ready\}\ \{vwait\ ready\}\n======\n\n(To\ me,\ having\ to\ use\ a\ loop\ like\ this\ seems\ to\ go\ against\ Tcl's\ event-driven\ style.)\n\nIntriguingly,\ even\ if\ the\ unset\ fails\ (if\ the\ variable\ does\ not\ exist),\ `vwait`\ will\ still\ return:\nIntriguingly,\ even\ if\ the\ unset\ fails\ (if\ the\ variable\ does\ not\ exist),\ \[vwait\]\ will\ still\ return:\n======\nafter\ 3000\ \{catch\ \{unset\ nonexistent\}\}\nvwait\ nonexistent\n#\ Returns\ after\ 3\ s!\n======\n\n----\n\nKen:\ I\ have\ one\ a\ problem\ with\ the\ follow\ code.\ I\ intended\ to\ transfer\ control\nKen:\ I\ have\ one\ a\ problem\ with\ the\ follow\ code,\ i\ intended\ to\ transfer\ control\nto\ halt\ the\ procession\ of\ one\ function\ and\ go\ to\ other\ function\ which\ would\ncall\ it\ again?\ Below\ is\ the\ code\n\n======\nset\ Flag\ 0\nif\ \{\$Flag\}\ \{\n\ \ \ \ continue\n\}\ else\ \{\n\ \ \ \ vwait\ Flag\n\}\n======\n\nbut\ for\ this\ code\ it\ seems\ that\ it\ would\ prompt\ an\ error\ code\ which\ is\ \"can't\nwait\ for\ variable\ Flag\"\ if\ flag\ stays\ at\ 0.\ So\ how\ should\ i\ proceed\ so\ that\ it\nwould\ not\ prompt\ this\ error\ code.\n\n} CALL {my revision vwait} CALL {::oo::Obj2039938 process revision/vwait} CALL {::oo::Obj2039936 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4