## Tcl9.0.3/Tk9.0.3 Documentation > Tcl Commands > vwait

### Tcl/Tk Applications | Tcl Commands | Tk Commands | [incr Tcl] Package Commands | SQLite3 Package Commands | TDBC Package Commands | tdbc::mysql Package Commands | tdbc::odbc Package Commands | tdbc::postgres Package Commands | tdbc::sqlite3 Package Commands | Thread Package Commands | Tcl C API | Tk C API | [incr Tcl] Package C API | TDBC Package C API

  NAME
    vwait — 変数に書込まれる迄行事を処置する Process events until a variable is written
  構文 SYNOPSIS
  説明 DESCRIPTION
    --
    -all
    -extended
    -nofileevents
    -noidleevents
    -notimerevents
    -nowindowevents
    -readable channel
    -timeout milliseconds
    -variable varName
    -writable channel
  用例 EXAMPLES
  NESTED VWAITS BY EXAMPLE
  SEE ALSO
  KEYWORDS

### NAME

vwait — 変数に書込まれる迄行事を処置する Process events until a variable is written

### 構文 SYNOPSIS

vwait varName

vwait ?options? ?varName ...?

### 説明 DESCRIPTION

この命令は､行事を処理する為に Tcl 行事巡回待機に入り､行事が準備できるまで､応用譜(の進行)を抑制する｡どれかの行事処理機構が大域変数 varName の値を設定する迄､行事の処理を続行する｡一たび､ varName が設定されると､この vwait 命令は修正された varName が完了した行事処理機構に出来る限り速く戻る｡ varName 引数は常に大域名前空間を考慮して変数の名前が解釈されるが､もし完全に修飾された名前が与えられるとどの名前空間の変数も参照できる｡ This command enters the Tcl event loop to process events, blocking the application if no events are ready. It continues processing events until some event handler sets the value of the global variable varName. Once varName has been set, the vwait command will return as soon as the event handler that modified varName completes. The varName argument is always interpreted as a variable name with respect to the global namespace, but can refer to any namespace's variables if the fully-qualified name is given.

二番目のやや複雑な命令形式内では､optionsは､ 待ち処理の更なる微細な制御､及び､多重の行事原資を扱う事を､許容す｡ In the second more complex command form options allow for finer control of the wait operation and to deal with multiple event sources. Options can be made up of:

--
  指示項目の末尾を記す｡引続く全ての引数は変数名として取扱われる｡ Marks the end of options. All following arguments are handled as variable names.

-all
  待つ処理のための全ての状態は､wait操作を完遂する為に合致せねばならない｡ そうでない場合(無為設定)､最初の行事が待ちを完遂す｡ All conditions for the wait operation must be met to complete the wait operation. Otherwise (the default) the first event completes the wait.

-extended
  リスト形式の拡張された結果が返される､説明は下を参照されたい｡ An extended result in list form is returned, see below for explanation.

-nofileevents
  ファイル行事は待ち操作では処理されない｡ File events are not handled in the wait operation.

-noidleevents
  待ち操作の間､行事待ち処理子は､起動されない｡ Idle handlers are not invoked during the wait operation.

-notimerevents
  待ち操作の間､時限処理子は､機能しない｡ Timer handlers are not serviced during the wait operation.

-nowindowevents
  窓操作系の行事は､待ち操作の間､処理されない｡ Events of the windowing system are not handled during the wait operation.

-readable channel
  channelは､読込みの為のTcl 通信路の名前でなければならない｡ もし､channelが読込可か､可になると､待ち処理は完了する｡ Channel must name a Tcl channel open for reading. If channel is or becomes readable the wait operation completes.

-timeout milliseconds
  待ち処理はmillisecondsに制約される｡ The wait operation is constrained to milliseconds.

-variable varName
  varNameは大域変数の名前でなければならない｡ この変数を書くか､未設定なら､待ち操作を完遂する｡ VarName must be the name of a global variable. Writing or unsetting this variable completes the wait operation.

-writable channel
  channelは書込み用に開いたTcl 通信路の名前でなければならない｡ もしchannelが書込み可か､可になれば､待ち処理は完了する｡ Channel must name a Tcl channel open for writing. If channel is or becomes writable the wait operation completes.

vwaitに返された結果は､単純な形式の空文字列である｡ もし､-timeout指示項目が指定されると､結果は､待ち状態を満たす迄の残りの千分の一秒単位の数字であり､待ち処理が時間切れでは-1である｡ The result returned by vwait is for the simple form an empty string. If the -timeout option is specified, the result is the number of milliseconds remaining when the wait condition has been met, or -1 if the wait operation timed out.

もし､-extended指示項目が指定されると､結果は､偶数要素を伴う Tcl リストが 作上げられる｡奇数要素は値 readableとtimeleftとvariableとwritableをとる｡ 偶数要素は､対応する変数と通信路名か千分の一秒の残り数か､である｡ リストは､常に一番最後になるtimeleftの例外を除いて､行事の生じた順に並ぶ｡ If the -extended option is specified, the result is made up of a Tcl list with an even number of elements. Odd elements take the values readable, timeleft, variable, and writable. Even elements are the corresponding variable and channel names or the remaining number of milliseconds. The list is ordered by the occurrences of the event(s) with the exception of timeleft which always comes last.

変数名 が設定された後､いくつかの場合では､varNameが設定された後､ vwait 命令が即座には戻らないことがある｡これは､変数名 を設定する行事処理機構が即座に完了しないときに起りる｡譬えば､行事処理機構が変数名 を設定し､そのまま vwait を呼出して違う変数を待つ､そうすると､長時間戻らないことがあり得る｡この間､最上位の vwait は行事処理機構を完了させる為に待機して抑制される､それで､どちらも戻ることが出来なくなる(下の NESTED VWAITS BY EXAMPLE を参照されたい)｡ In some cases the vwait command may not return immediately after varName et.al. is set. This happens if the event handler that sets varName does not complete immediately. For example, if an event handler sets varName and then itself calls vwait to wait for a different variable, then it may not return for a long time. During this time the top-level vwait is blocked waiting for the event handler to complete, so it cannot return either. (See the NESTED VWAITS BY EXAMPLE below.)

明確化のために言うと､多重 vwait 呼び出しは入れ子になり並行動作はおこならない｡最外 vwait 呼出しは内側のものが全て帰るまで帰らない｡符号命令が入れ子になっている様な vwait 呼出しをしない(行事呼戻しに入れることを避けることにより)ことを推奨するが､避けられない時は､厳密には必要でない vwait の全ての再入呼出しを防ぐ符号命令への相互拘束変数の追加に註意すべきである｡内部で vwait を使う Tcl 梱包(譬えば http)の操作の同期様式に気配りすべきである; 行事待合わせを遣う場合､利用できるこれ等の梱包の操作の非同期呼戻し様式の使用が最良である｡　 To be clear, multiple vwait calls will nest and will not happen in parallel. The outermost call to vwait will not return until all the inner ones do. It is recommended that code should never nest vwait calls (by avoiding putting them in event callbacks) but when that is not possible, care should be taken to add interlock variables to the code to prevent all reentrant calls to vwait that are not strictly necessary. Be aware that the synchronous modes of operation of some Tcl packages (e.g., http) use vwait internally; if using the event loop, it is best to use the asynchronous callback-based modes of operation of those packages where available.

### 用例 EXAMPLES

何らかの行事が exit を呼出す迄､何時までも行事巡回待機をする｡(此処で使った変数以外のどんな名前でも使用できるが､ forever [永遠]という名前なら一瞥して意図が判るだろう｡) Run the event-loop continually until some event calls exit. (You can use any variable not mentioned elsewhere, but the name forever reminds you at a glance of the intent.)

    vwait forever

集中処理装置の通信接続機能への接続に5秒待つか､さもなければ通信接続機能を閉じて､処理譜の実行を続行する: Wait five seconds for a connection to a server socket, otherwise close the socket and continue running the script:

    # 初期設定する
    # Initialise the state
    after 5000 set state timeout
    set server [socket -server accept 12345]
    proc accept {args} {
        global state connectionInfo
        set state accepted
        set connectionInfo $args
    }

    # 何かが起るまで待機
    # Wait for something to happen
    vwait state

    # 生じ得た行事を消去
    # Clean up events that could have happened
    close $server
    after cancel set state timeout

    # 終了様態に依拠し行動...
    # Do something based on how the vwait finished...
    switch $state {
        timeout {
            puts "no connection on port 12345"
        }
        accepted {
           puts "connection: $connectionInfo"
           puts [lindex $connectionInfo 0] "Hello there!"
        }
    }

設定される名前空間変数を待つことによる時間遅れを待つ命令｡入子になった待合わせを防ぐ為の連結を含む｡ A command that will wait for some time delay by waiting for a namespace variable to be set. Includes an interlock to prevent nested waits.

    namespace eval example {
        variable v done
        proc wait {delay} {
            variable v
            if {$v ne "waiting"} {
                set v waiting
                after $delay [namespace code {set v done}]
                vwait [namespace which -variable v]
            }
            return $v
        }
    }

coroutine の内部で実行されている時､外の行事待機を得る為に vwait を使う代りに yield を使い､変数が設定された時､又は無為状態の後に再度実行する｡ When running inside a coroutine, an alternative to using vwait is to yield to an outer event loop and to get recommenced when the variable is set, or at an idle moment after that.

    coroutine task apply {{} {
        # [after 1000]を擬制する
        # simulate [after 1000]
        after 1000 [info coroutine]
        yield

        # 通常通りに､大域変数設定を予定する
        # schedule the setting of a global variable, as normal
        after 2000 {set var 1}

        # [vwait var]を擬制する
        # simulate [vwait var]
        proc updatedVar {task args} {
            after idle $task
            trace remove variable ::var write "updatedVar $task"
        }
        trace add variable ::var write "updatedVar [info coroutine]"
        yield
    }}

#### NESTED VWAITS BY EXAMPLE

この用例は vwait が入れ子になっている時に何が起るかを例証する｡その記述譜は決して終了しない､理由は a 変数の待機が決して終了しない; vwait 命令は依然 after により計画された記述譜の完了を待つ､それは､外側の vwait が (a の設定) を待っているにも拘らず､内部の vwait (b の為の) が実行されると生じる｡ This example demonstrates what can happen when the vwait command is nested. The script will never finish because the waiting for the a variable never finishes; that vwait command is still waiting for a script scheduled with after to complete, which just happens to be running an inner vwait (for b) even though the event that the outer vwait was waiting for (the setting of a) has occurred.

    after 500 {
        puts "waiting for b"
        vwait b
        puts "b was set"
    }
    after 1000 {
        puts "setting a"
        set a 10
    }
    puts "waiting for a"
    vwait a
    puts "a was set"
    puts "setting b"
    set b 42

もし上の命令符号を実行すると､この出力が得られる: If you run the above code, you get this output:

    waiting for a
    waiting for b
    setting a

vwait 命令が入れ子になっている為に､記述譜は “b was set” が印刷された後になる迄 “a was set” を印刷することはない ､それで記述譜は暗礁に乗上げている｡之を回避する唯一の道は､継続して渡す様式に全体の算譜を組立てるか､継続を内在する為に coroutine を使用するかのどちらかである｡第１の選択はこう書かれる: The script will never print “a was set” until after it has printed “b was set” because of the nesting of vwait commands, and yet b will not be set until after the outer vwait returns, so the script has deadlocked. The only ways to avoid this are to either structure the overall program in continuation-passing style or to use coroutine to make the continuations implicit. The first of these options would be written as:

    after 500 {
        puts "waiting for b"
        trace add variable b write {apply {args {
            global a b
            trace remove variable ::b write \
                    [lrange [info level 0] 0 1]
            puts "b was set"
            set ::done ok
        }}}
    }
    after 1000 {
        puts "setting a"
        set a 10
    }
    puts "waiting for a"
    trace add variable a write {apply {args {
        global a b
        trace remove variable a write [lrange [info level 0] 0 1]
        puts "a was set"
        puts "setting b"
        set b 42
    }}}
    vwait done

第2の選択は､コルーチンと幾つかの補助手続函数で､この様になされている: The second option, with coroutine and some helper procedures, is done like this:

    # コルーチンを使用した値待機命令
    # A coroutine-based wait-for-variable command
    proc waitvar globalVar {
        trace add variable ::$globalVar write \
                [list apply {{v c args} {
            trace remove variable $v write \
                    [lrange [info level 0] 0 3]
            after 0 $c
        }} ::$globalVar [info coroutine]]
        yield
    }
    # コルーチンを使用した暇つぶし命令
    # A coroutine-based wait-for-some-time command
    proc waittime ms {
        after $ms [info coroutine]
        yield
    }

    coroutine task-1 eval {
        puts "waiting for a"
        waitvar a
        puts "a was set"
        puts "setting b"
        set b 42
    }
    coroutine task-2 eval {
        waittime 500
        puts "waiting for b"
        waitvar b
        puts "b was set"
        set done ok
    }
    coroutine task-3 eval {
        waittime 1000
        puts "setting a"
        set a 10
    }
    vwait done

### SEE ALSO

global, update

### KEYWORDS

asynchronous I/O, event, variable, wait
Copyright © 1995-1996 Sun Microsystems, Inc.