Advanced synchronization

We’ve already talked about about the two models offered by NetSimLan, called semisynchronous and asynchronous communication. In some cases we need a more complex model. Let’s say you need all nodes to finish a task before they start the next one. We call the time between starting a task and starting the next one a round.

To realize model, think of the following picture: There’s an additional server. Every node sends a message to that server when it’s finished with a round. When the server got a message from every (not dead) node, it sends a message to all nodes to start a new round.

This technique is realized in NetSimLan. You don’t need to write the server explicitly and connect every node to it, but you do the following:

When a node has finished its round, it calls synchronize(). Now it’s marked cyan in the visualization. Until the next round starts, it doesn’t call its timeout function anymore. But it still processes incoming messages, so other nodes can finish the round too. As soon as all (not dead) nodes have called synchronize, a function startRound() will be called on every node if it’s implemented.

Let’s get to practice: When a round starts, we want every node to send a message to another one, such that every node will send and receive exactly one. The node 1 shall send the message to 25, the node 2 to 24 etc. When a node got it’s message it shall finish its round.

To do so, we just need to add a call of synchronize(); right after the print of the message. In addition we need a startRound like this:

startRound(){
    message ("hello" , size^^2 + 1 - id(this));
}

To start this immediately with the simulation, add a call of startRound(); to the end of init(). Try it out, add the code and run the simulation.

Final code

When you followed the tutorial up to this point, your code should look something like that:

gridNode{
    int size = 5; int x_this; int y_this;
    node top blue; node left yellow;
    node bottom red; node right green;
    [int,node] nextHop ignore hidden;
    [int,int] distance;
    [int, string] buffer;
    int L = 5; /* limit for string length per message */
    message (string text, int to_id){
        int i; /* startindex of part start */
        int strid = hash(text);
        int len = str_len(text);
        for (i = 0 ; i < len ; i+=L){
            string part = sub_str(text,i,i+L);
            forwardpart (part, to_id, strid, i, len);
        }
    }
    forwardpart (string part, int to_id, int strid,
                    int start, int totallength){
        if (to_id==id(this)) {
            receivepart (part, strid, start, totallength);
        } else {
            if (nextHop[to_id] == null){
                /* messages shall not be lost, so delay */
                this -> forwardpart (part, to_id, strid,
                                    start, totallength);
            }
            nextHop[to_id] -> forwardpart (part, to_id, strid,
                                    start, totallength);
        }
        mark (true);
    }
    receivepart (string part, int strid,
                    int start, int totallength){
        string previousparts = buffer [strid];
        if ( str_len (previousparts) < start ){
            /* parts arrived out of order. delay this part */
            this ->
                receivepart (part, strid, start, totallength);
        } else {
            string newparts = previousparts + part;
            if ( str_len(newparts) == totallength ){
                /* message arrived completly */
                print("Message " + newparts + " received.");
                buffer <[strid]< ;
                synchronize();
            } else {
                /* parts still missing. Update the buffer */
                buffer [ strid ] = newparts;
            }
        }
    }
    updateDistance(int dst, int newDistance, node newNextHop){
        if (!containts(nextHop, dst) |
                            distance[dst] > newDistance){
            nextHop[dst] = newNextHop;
            distance[dst] = newDistance;
            right -> updateDistance(dst, newDistance+1, this);
            top -> updateDistance(dst, newDistance+1, this);
            left -> updateDistance(dst, newDistance+1, this);
            bottom->updateDistance(dst, newDistance+1, this);
            /* for the case this call is faster than entry */
            entry (newNextHop);
        }
    }
    entry(node n){
        int x_n=(id(n)-1)/size; int y_n=(id(n)-1)%size;
        if (x_n == x_this+1 & y_n == y_this) right=n;
        if (x_n == x_this & y_n == y_this+1) top=n;
        if (x_n == x_this-1 & y_n == y_this) left=n;
        if (x_n == x_this & y_n == y_this-1) bottom=n;
        updateDistance(id(n), 1, n);
        /* take care of race conditions */
        for (int dstNode : int nodeDistance : distance){
            n -> updateDistance(dstNode,nodeDistance+1,this);
        }
    }
    timeout(){
        mark(false);
    }
    init(){
        x_this=(id(this)-1)/size; y_this=(id(this)-1)%size;
        startRound();
    }
    startRound(){
        message ("hello" , size^^2 + 1 - id(this));
    }
}


Previous: String Operations Next: API

The University for the Information Society