Example

## 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).