# TIP 455: Extensions to [vwait]: Variable Sets and Scripted Access to Tcl_DoOneEvent
	Author:	Christian Werner <chw@ch-werner.de>
	State:	Draft
	Type:	Project
	Tcl-Version:	8.7
	Vote:	Pending
	Created:	07-Oct-2016
	Keywords:	Tcl, event loop
	Post-History:	
-----

# Abstract

This TIP generalizes the **vwait** command to allow waiting on zero, one, or
more variable changes, on zero or more file events, to time-limit the wait,
and to control on which kinds of events is to be waited by partially exposing
the underlying API, namely _Tcl\_DoOneEvent\(\)_.

# Rationale

One remarkable property of Tcl is the ability to add traces, i.e., the
execution of callback functions, on certain operations affecting variables.
The **vwait** command combines the variable trace facility with the \(a\)
event loop, i.e., the \(a\) program main loop waiting and processing various
types of events generated by I/O channels, time, and internal activities of
the running Tcl program.

The current implementation of **vwait** allows to open an unconstrained
event loop which is terminated by writing or unsetting exactly one global
variable given as argument to **vwait**.

This proposal extends **vwait** to terminate its event loop on occurence of

 1. zero or more variable modifications

 2. readability/writability of zero or more file channels \(usually sockets\)

 3. an optional timeout specified as milliseconds as in the **after**
    command.

Additional flags to **vwait** control which types of events are to be dealt
with in its event loop, i.e. the underlying _Tcl\_DoOneEvent\(\)_ API.

When more than one kind of active input \(both, variables and file channels\)
is involved in an instance of **vwait**, another flag controls if any one of
the inputs or all inputs must have been activated in order to terminate the
event loop. This allows for scenarios, where **vwait** can be used as a kind
of "barrier" getting broken if all required conditions are fulfilled, i.e.,
axe, saw, spade, fire accelerant, water, in order to demolish, burn down,
extinct the glow, and finally bury the trellis-work fence.

However, in contrast to the illustrious demolition job, the order of occurence
of events breaking that "barrier" is indeterminate.

If the **vwait** is constrained by a timeout, and the time limit is reached,
its event loop terminates early and **vwait** indicates that timeout by a
negative integer result. Otherwise, the return value is the remaining number
of milliseconds \(positive integer which can be zero\) of the timeout
constraint. This property combined with [[302]](302.md) allows to implement
\(soft real-time\) control loops.

An extended result list can be obtained from **vwait** by another flag
which gives detailed information on the cause of the termination of the
event loop.

# Proposal

The **vwait** command shall have the following signature:

 > **vwait** _var-name_ - well known and implemented behaviour

 > **vwait** _options_ ?_var-names_? - all available enhanced
    features; more than one variable name may be given, in which case the wait
    will terminate when any of the variables are written to \(unless the
    **-all** option below is given\)

where _options_ are:

  **--**:                   indicates end of options

  **-all**:                 all \(except timeout\) conditions must be met

  **-extended**:            result is a list (see below)

  **-nofileevents**:        don't consider file events

  **-noidleevents**:        don't consider idle events

  **-notimerevents**:       don't consider timer events

  **-nowindowevents**:      don't consider window system events

  **-readable** _channel_:  _channel_ becomes readable

  **-timeout** _ms_:        timeout in milliseconds

  **-variable** _var-name_: _var-name_ is written or unset

  **-writable** _channel_:  _channel_ becomes writable

The return value of **vwait** shall be the empty string except when the
**-timeout** and/or **-extended** options are in effect \(see above\).

The normal result format when **-timeout** is given is the number of
milliseconds remaining in the wait. Otherwise it's an empty string.

The extended result format is a list with even number of elements. Odd
elements take the values **readable**, **timeleft**, **variable**, and
**writable**, i.e. qualify the event. 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.

Where the combination of options doesn't make sense, or even conflicts, an
appropriate error message shall be thrown, e.g., **-timeout** and
**-notimerevents** can't be specified at the same time.

If all event types except idle events are excluded, the event loop
\(_Tcl\_DoOneEvent_\) shall be constrained by **TCL\_DONT\_WAIT**.

Interesting analogies to the **update** command can be infered: **vwait
--** is equivalent to **update**, **vwait -nofileevents -notimerevents
-nowindoevents** is equivalent to **update idletasks**.

# Copyright

This document has been placed in the public domain. In legislations where this
concept does not exist the CC0 license applies.

