Phase 1 is to implement a single processor, single monitor, threaded solution. Each thread gets a row and executes the code shown in the assignment. A "broadcast" means entering the monitor, copying your row in, and executing a notifyAll(). "wait for row" means entering the monitor, and wait()'ing until row k is there, then copying row k.
Phase 3 is to distribute the threads onto multiple processors using the RMI servers. The threads should act as if they're on a local machine, accessing a local monitor. They needn't be aware that other threads are on other processors. The monitor functions for "broadcast" and/or "waitforrow" will handle the communication with other servers on other processors.
Be careful, though. In the sequential algorithm, A[1,2] will be updated before A[1,3]. In other words, if myCol is greater than k, then I need to wait until A[i,k] is updated before I get its value. Thus the "send to my row" loop is broken into two parts.
message Elem{int row; int col; int elem};
entity RowEntity(int myRow,
int myCol,
int numberOfRows) {
int i, k;
int myElement;
ename thisRow[N];
ename thisCol[N];
int Akj, Aik;
/* initialize */
for (k = 0; k < numberOfRows; k++) {
if (k == myRow) {
/* broadcast my element to my column */
for (i = 0; i < numberOfRows; i++) {
if (i != myRow) /* to prevent wastefully sending to self */
send Elem{myRow, myCol, myElement} to thisCol[i];
}
Akj = myElement;
}
else {
receive (Elem elem) when (elem.row == k && elem.col == myCol) {
Akj = elem.elem;
}
}
if (k == myCol) {
/* broadcast my element to my left */
for (i = 0; i < myCol; i++) {
send Elem{myRow, myCol, myElement} to thisRow[i];
}
Aik = myElement;
}
else {
receive (Elem elem) when (elem.row == myRow && elem.col == k) {
Aik = elem.elem;
}
}
/* update my element */
if (Aik + Akj < myElement)
myElement = Aik + Akj;
/* broadcast my element to my right */
if (k == myCol) {
for (i = myCol + 1; i < numberOfRows; i++) {
send Elem{myRow, myCol, myElement} to thisRow[i];
}
}
}
/* send output */
}