7.4 Example
Here we present a simple example use of the Tcl peer multitasking
facilities. The full programs (Tcl and ECLiPSe code) are available in
the ECLiPSe distribution as example_multi.ecl and example_multi.tcl.
The Tcl program uses the remote Tcl peer interface to create a window that
interacts with the ECLiPSe process it is attached to. Multiple copies of
the program can be run, and attached to the same ECLiPSe process with a
different remote peer. Each window has three buttons:
-
run: a button to send an ERPC goal to ECLiPSe (in this case a simple
writeln with the peer name;
- end: a button to end interaction with ECLiPSe and return control
to ECLiPSe;
- reg: a button to toggle the registration/deregistration of the peer
for peer multitasking;
The program interacts with ECLiPSe when the run button is pressed. This
can be done either during a peer multitasking phase, or when the program's specific
peer is given control on its own. When the peer is given control on its
own, only it can interact with ECLiPSe; while during peer multitasking,
all the multitasking peers (the copies of the program that are running) can
interact with ECLiPSe, i.e. the run buttons in all the windows can all
be pressed.
After attaching to ECLiPSe with ec_remote_init, the program sets
various handlers for the handing of control between ECLiPSe and itself
with ec_running_set_commands:
ec_running_set_commands ec_start ec_end {} disable_buttons
The handlers for when control is handed back to ECLiPSe, ec_start,
and when control is handed over from ECLiPSe, ec_end, are defined
thus:
proc ec_end {} {
if {[ec_multi:get_multi_status] != "on"} {
enable_buttons
}
}
proc ec_start {} {
if {[ec_multi:get_multi_status] != "on"} {
disable_buttons
}
}
enable_buttons and disable_buttons enables and disables the
buttons for the window, respectively. The code tests if the peer is
multitasking with ec_multi:get_multi_status. This is needed because
during a peer multitasking phase, control is repeatedly handed back and
forth, and we don't want the buttons to be repeatedly enabled and disabled
during this phase.
Next, the program registers the peer for peer multitasking:
ec_multi:peer_register [list start multi_start_handler \
interact multi_interact_handler]
No special handler is
needed for the end of multitasking, as no special action is needed beyond
disabling the buttons. The return code is stored in a global variable return_code. The start handler is defined thus:
proc multi_start_handler {type} {
global return_code
if {$type == "demo"} {
set return_code continue
enable_buttons
} else {
set return_code no
}
return $return_code
}
As discussed, multitasking phases can be of different types. For
demonstrating this multitasking features of this example program, the type
is “demo”. Therefore the handler tests for this and enables the button if
the phase is “demo”. On the ECLiPSe side, the multitasking phase is
started with the following predicate call:
peer_do_multitask(demo),
The interact handler is defined thus:
proc multi_interact_handler {type} {
global return_code
if {$return_code == "terminate"} {
disable_buttons
}
return $return_code
The code checks for the two cases where the user has requested to terminate
the multitasking phase by pressing the .end button, and disables the
buttons. The end button itself invokes the following code to set return_code:
proc end_interaction {} {
global return_code
set return_code terminate
if {[ec_multi:get_multi_status] != "on"} {
ec_resume
}
}
The code checks if it is in a peer multitasking phase, and if so,
return_code is set to terminate, so that when the handler
returns, the multitasking phase will terminate.
Otherwise, the peer has been explicitly handed control exclusively,
and so control is handed back to ECLiPSe in the normal way using ec_resume.
The program also allows a peer to deregister from multitasking or, if
already deregistered, to register again for multitasking. This is handling
by the following two procedures:
proc register_for_multi {} {
ec_multi:peer_register [list start multi_start_handler]
.reg configure -command {deregister_for_multi}
.reg configure -text "Deregister multitasking"
}
proc deregister_for_multi {} {
ec_multi:peer_deregister
.reg configure -command {register_for_multi}
.reg configure -text "Register multitasking"
}
Pressing the .reg button will either call register_for_multi or
deregister_for_multi, depending on if the peer is currently
deregistered or registered for peer multitasking (respectively). The
procedure also changes the button to toggle to the other state.
Pressing the button during a peer multitasking phase will remove the peer
from multitasking immediately. If pressed while the peer is given exclusive
control, the peer will not participate in future multitasking phase (unless
it is re-registered).