TiOS is a single-thread system. All events are executed by the VM one-after-one and in the order in which they entered the event queue.

But what if you never exit the event handler for one of the events, or exit it after a long delay? All other events will be waiting in the queue unhandled and that may pose a problem!

Fortunately, there is a doevents statement. Put it in your code and when the VM reaches doevents, the execution of the current event handler chain will be put on hold.

The VM will then execute all events waiting in the queue. After that, the VM will resume the execution of the original event handler chain.

If new events are added to the queue while doevents is executing, they will not be processed on the same doevents "round."

To summarize, doevents provides a way for a procedure to let other events execute while the procedure is doing something lengthy:

sub on_sys_init 'calculate the sum total of all array elements -- this will surely take time!
   dim f as word
   sum = 0
   for f = 0 to 49999
      sum = sum + arr(f)
      doevents 'don't stall other events while we are going through the entire array
   next f
end sub

A block diagram illustrating the handling of the doevents statement.

Nesting Doevents

Let's say you had the doevents statement in the on_sys_init chain.

The execution reaches there, then starts handling other events in the queue. One of these events is ON_SOCK_DATA_ARRIVAL and there is a second doevents in the event handler chain for this event.

What will happen? A secondary, independent doevents round will begin!

After that secondary doevents finishes the execution, it will return to the first doevents, and from it — to the original event handler chain.

A block diagram illustrating the handling of nested doevents statements.

Doevents for Events of the Same Type

For some types of events, only one instance of the event may be present in the queue at any given time. The next event of the same kind may only be generated after the current one has completed processing.

For other events, multiple instances are allowed to be queued.

For example, there may be multiple instances of the ON_SOCK_DATA_ARRIVAL event — potentially, one per each active socket.

Let's assume that there is a doevents statement in the on_sock_data_arrival call chain. The statement is reached, the event handler is put on hold, the VM starts to execute other events in the queue.

One of the events waiting in the queue is another ON_SOCK_DATA_ARRIVAL event. What is the VM supposed to do?

It cannot start this event's execution, because, with the original ON_SOCK_DATA_ARRIVAL event already on hold, this would be tantamount to re-entrant execution, and that's a no-no!

So, the VM will just skip over this second ON_SOCK_DATA_ARRIVAL and execute everything else it can execute.

The unprocessed ON_SOCK_DATA_ARRIVAL #2 event will remain in the queue until the current ON_SOCK_DATA_ARRIVAL finishes. It will then be processed in the normal fashion.

A block diagram illustrating the handling of multiple doevents statements of the same type.


Nesting Doevents

Doevents for Events of the Same Type