In order to reduce the complexity of program development, as demonstrated in Figure 4.3 without adding any overheads such a thread creation and context switching (Figure 4.5), a coordination language called Structured Dagger has been developed on top of Charm++. Structured Dagger language is defined by augmenting Charm++ with structured entry-methods, which specify pieces of computations (when-blocks) and dependences among computations and messages. A when-block is guarded by dependences that must be satisfied before it can be scheduled for execution. These dependences include arrival of messages or completion of other constructs. Before describing the Structured Dagger language in detail, let us consider the molecular dynamics example once again, and show how it can be coded in Structured Dagger.
{CodeThree}
class compute_object
sdagentry compute_object(MSG *msg){
atomic {
PatchManager->Get(msg->idx1,...);
PatchManager->Get(msg->idx2,...);
}
overlap {
when recv_first(Patch *first)
atomic { filter(first); }
when recv_second(Patch *second)
atomic { filter(second); }
}
atomic {
computeInteractions(first, second);
}
}
Figure 4.6 shows the compute object written using Structured Dagger. Whenever the entries recv_first or recv_second receive messages, the filter method is called. After both patches arrive, the computeInteractions function is called. Structured Dagger takes care of the bookkeeping functions such as incrementing counters, flags and buffering the messages. Therefore, the resulting code is more readable (consequently easy to program and modify), and retains the performance benefits of the message-driven model.