The CommManager class defines functions required for communication between LogicalProcesses over MPI. As previously mentioned, communication between simulation objects local to each other occurs by direct insertion into the input queue, so the CommManager is not involved. Objects sending events to non-local destinations use the CommManager to do so.
Like the simulation objects, the CommManager has a method called recvEvent(BasicEvent *) to receive events that simulation objects wish the CommManager to handle. In addition, the CommManager has several overloaded versions of a method called recvMsg which are used by the LP and the GVTManager to send messages to other objects on other LPs. The types of messages defined include the following (these definitions can be found in KernelMsgs.hh):
Additional information in the fields senderLP and sequence is filled in automatically before the message is given to MPI. senderLP is the id of the LP sending the message, and sequence is a monotonically increasing long long the counts the number of messages sent from the sending LP to the destination LP.
The above conclude the base message types. The following message types are also included in the base WARPED kernel to implement the PGVT algorithm. Future releases of WARPED will remove these message classes from the base kernel definition.
For each of the above message types, the method CommManager::recvMsg is overloaded to handle the message correctly. For instance, if the CommManager receives a TerminateMsg, it will deliver the message to all of the LPs in the simulation. In the case of an EventMsg, the message is simply delivered to the correct LP, and the receiving CommManager delivers the message to the correct simulation object. Similarly, the method remoteSend is overloaded for all of the mentioned message types to send messages over MPI to other LPs.
The CommManager's declaration follows:
class CommManager : public BasicTimeWarp {
friend class GVTManager;
public:
CommManager();
~CommManager();
void initialize(ObjectRecord*, // pointer to simulation array
GVTManager*, // pointer to the GVT Manager
int); // The number of LPs
int getID() { return id; };
// These methods are for the _Commucation Manager_ to receive the types
// of events passed in ( by local objects )
void recvEvent( BasicEvent* );
void recvMsg( TerminateMsg * );
void recvMsg( LGVTMsg * );
void recvMsg( LowerLGVTMsg * );
void recvMsg( newGVTMsg * );
void recvMsg( GVTAckMsg * );
void recvMsg( LPAckMsg * );
void recvMsg( InitMsg * );
void recvMsg( StartMsg * );
void recvMsg( CheckIdleMsg * );
void recvMsg( DummyMsg * );
void recvMsg( DummyRequestMsg * );
// this is a method the LP calls to let everyone know that he's got a
// certain simulation object in his posession.
void iHaveObject(int);
int recvMPI(int = 1); // wait for the number of messages specified (and
// deliver them). If there aren't that many
// messages, stop receiving them. In either case,
// return the number of messages actually received.
BasicMsg * recvMPIMsg(); // grab ONE message from MPI and return it..
// return NULL if there are none...
void terminateSimulation( TerminateMsg * );
long long getSequence( int ); // returns the sequence number of the
// next message to the LP with the id
// passed in
void waitForStart();
void waitForInit( int numExpected );
// since the general model of memory in this system is that whoever
// news memory, deletes it, the commanager gets to garbage collect
// too
void gcollect(VTime gtime);
// these are to please the compiler
void executeProcess();
BasicEvent* getEvent();
void simulate();
VTime calculateMin();
private:
int numLPs;
ObjectRecord *simArray;
GVTManager *gVTHandle;
// these will be filled in with arrays so that each communication channel
// has a unique sequence running
long long * sendSequenceArray;
long long * recvSequenceArray;
// we have to define this in order to please the compiler
void sendEvent( BasicEvent*);
// These methods are to allow the Communation Manager to deliver messages to
// local objects only
void deliver(BasicEvent *);
void deliver(LGVTMsg *);
void deliver(LowerLGVTMsg *);
void deliver(newGVTMsg *);
void deliver(LPAckMsg *);
void deliver(GVTAckMsg *);
void deliver(CheckIdleMsg *);
void deliver(DummyMsg *);
void deliver(DummyRequestMsg *);
// this method takes an LP Msg, figures out what kind of derived type it is,
// and then delivers it to the LOCAL entity that is receiving it.
void routeMsg( BasicMsg *);
void remoteSend( BasicMsg *, int );
};