Fleet

Fleet is a simple concurrent programming tool for JTcl. This is a very early release of Fleet and is mostly intended for experimentation. Fleet consists of Java code that implements the "fleet" command and a set of Tcl procedures in the "::fleet" namespace that are used to initialize a fleet and manage message flow to the fleet members. The low level fleet code can be used in many ways. The procs in the ::fleet namespace provide one method to manage concurrent calculations.

Usage

Load the fleet Java extension in Tcl source files:

    package require fleet

fleet create

::fleet create -name fleet-name

::fleet create creates a new fleet and a new Tcl level command for manipulating fleets.

Arguments

  • -name fleetName

    The name given to the fleet and the name of the Tcl level command that will be created. If this optional argument is not included the fleet will be named fleetN where N is an integer starting at 0 and incrementing for each fleet created.

fleetName member

::fleetName member -name fleet-name

::fleetName member creates a new member of the fleet.

Arguments

  • -name memberName

    The name given to the new member of the fleet If this optional argument is not included the member will be named memberN where N is an integer starting at 0 and incrementing for each member created.

Example:

  set fl [fleet create -name webfleet]
  set m1 [$fl member -name web1]

fleetName tell

::fleetName tell memberName msg -reply replyCmd -var doneVar

::fleetName tell sends a message representing a script to be executed in the fleet member with name memberName.

Arguments

  • memberName

    The name of the member to send the message to. If memberName is "*" then the same message is sent to all members of the fleet.

  • msg

    A Tcl script that will be executed in by the member in its own interpreter and thread.

  • -reply replyCmd

    A command that will be executed in the Tcl interpreter that sent the message when the command has finished executing.

  • -var varName

    A variable that will be set in the Tcl interpreter that sent the message when the command has finished executing.

  • Both -reply and -var are optional, but only one of them should be set.

Result

The argument to the procedure specified by a -reply argument, and the variable set with the -var argument, are both Tcl dictionary values with the following key/value pairs:

  • status

    OK or FAIL depending on the return code of the procedure executed

  • fleet

    the name of the fleet that the command was executed in

  • member

    the name of the fleet member that executed the command

  • value

    the result of executing the command

  • count

    the number of items in the members execution key when this result was returned

Example:

  set msg {set x [expr {sqrt(3.0)}]}
  $fl tell $m1 $msg -reply doneCmd 

fleetName forget

::fleetName forget memberName

::fleetName forget sends a message telling member to forget (remove from its queue) all messages that haven't yet been executed)

Arguments

  • memberName

fleetName count

::fleetName count -messages memberName

::fleetName count returns a count of items in the fleet. What items are counted depend on the specified arguments.

Arguments

  • -messages memberName

    Return a count of the number of messages in the specified members queue. As the member might be continuously acting on, and removing messages from the queue, this is only an estimate.

fleetName destroy

::fleetName destroy ?memberName?

::fleetName destroy destroys a member (if memberName is specified) or the entire fleet if no memberName argument is present. The destroy message is placed on the members input queue and will not be acted upon until all messages already in the queue are acted upon. Use the forget command to clear the queue if you want the destroy action to happen as soon as the the current message (if any) is done being acted upon.

Arguments

  • memberName

    The name of the member to destroy. If not specified the whole fleet is destroyed.

::fleet::initFleet

set fleet [::fleet::initFleet 2 initScript]

This procedure creates a fleet and an associated namespace with parameters set to default values and initializes the fleet members

Arguments

  • nMembers

    The number of members to create for the fleet.

  • script

    A script to run in each member of the fleet when the member is first created

::fleet::configure

::fleet::configure $fleet -messageProc sendMessage -calcProc accumulateResults -doneProc reportResults

This procedure creates a fleet and an associated namespace with parameters set to default values and initializes the fleet members

Arguments

  • fleetName

    The name of the fleet to configure

  • -messageProc

    The procedure used to send messages to fleet members. Defaults to "messageProc"

  • -calcProc

    The procedure that processes the result value sent back from each member. Defaults to "calcProc"

  • -doneProc

    The procedure called when all messages have been processed. Defaults to "reportProc"

  • -nMembers

    The number of members in fleet (normally set with initFleet command)

  • -lowWater

    If number of items in a fleet members queue falls below this level send more messages. Defaults to 50.

  • -highWater

    When sending messages send a count that will bring the total in members queue up to the highWater value. Defaults to 100.

  • -nMessages

    The total number of messages that need to be send to complete the calculation currently be performed by fleet. Defaults to 10000.

  • -nResults

    The number of results that have been returned by the fleet members. Initialized to 0

  • -messageNum

    The number of messages that have been sent to the fleet members. Initialized to 0

::fleet::sendMessages

::fleet::sendMessages $fleet

Start sending messages to the specified fleet.

Arguments

  • fleetName

    The name of the fleet to send messages to.

::fleet::jproc

eval ::fleet::jproc $fleet $procScript

Send a script representing a Java method to be compiled (using Hyde)

Arguments

  • fleetName

    The name of the fleet generate the method in.

  • script

    The script to be compiled into a Java method.

::fleet::reset

::fleet::reset $fleet

Reset the message counts for the fleet and its members so a new calculation can be begun.

Arguments

  • fleetName

    The name of the fleet to reset.

Example

proc readyCmd {args} {
   puts "done $args"
}

proc checkReadyVar {varName varElem mode} {
   upvar #0 $varName var
   puts $var($varElem)
}

package require java
package require fleet

set script {
    proc count {n} {
        set x 0.0
        for {set i 0} {$i <$n} {incr i} {
           set x [expr {$x+rand()}]
        }
        return $x
    }
}
set fl1 [fleet create]
set m1 [$fl1 member]
set m2 [$fl1 member]

$fl1 tell $m1 $script -reply readyCmd
$fl1 tell $m2 $script -reply readyCmd
for {set i 0} {$i < 10} {incr i} {
    puts $i
    $fl1 tell $m1 "count 100000" -reply readyCmd
}
for {set i 0} {$i < 10} {incr i} {
    puts $i
    $fl1 tell $m2 "count 100000" -var readyVar($i)
}
trace add variable  readyVar write checkReadyVar
#$fl1 destroy $m1
#$fl1 destroy $m2
vwait done

Example

## Calculate pi using concurrent program
## Compare to example in the Akka "getting started" documentation (http://akka.io)

package require hyde
package require fleet

proc sendMessage {fleet member messageNum} {
    set nElems 10000
    $fleet tell $member "calcPiFor $messageNum $nElems"  -reply ::fleet::processReply
}

proc accumulateResults {value} {
    global acc
    set acc [expr {$value+$acc}]
}

proc reportResults {} {
    global acc done
    puts "pi is $acc"
    set done $acc
}


set procScript {
    double calcPiFor {int start int nElem} {
        double acc = 0.0;
        int iStart = start*nElem;
        int iEnd = (start+1)*nElem-1;
        for (int i=iStart;i<=iEnd;i++) {
            acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1);
        }
        return acc;
    }
}

set initScript "package require java"
set fleet [::fleet::initFleet 2 $initScript]
eval ::fleet::jproc $fleet $procScript
::fleet::configure $fleet -messageProc sendMessage -calcProc accumulateResults -doneProc reportResults
::fleet::configure $fleet -nMessages 10000 -highWater 500

set acc 0.0
::fleet::sendMessages $fleet

vwait done