Subsections


15 . Chare and Message Inheritance

Charm++ supports C++ like inheritance among Charm++ objects such as chares, groups, and messages, making it easier to keep applications modular and allowing reuse of code.


15 . 1 Chare Inheritance

Chare inheritance makes it possible to remotely invoke methods of a base chare from a proxy of a derived chare. Suppose a base chare is of type BaseChare, then the derived chare of type DerivedChare needs to be declared in the Charm++ interface file to be explicitly derived from BaseChare. Thus, the constructs in the .ci file should look like:

   chare BaseChare {
    entry BaseChare(someMessage *);
    entry void baseMethod(void);
    ...
  }
  chare DerivedChare : BaseChare {
    entry DerivedChare(otherMessage *);
    entry void derivedMethod(void);
    ...
  }

Note that the access specifier public is omitted, because Charm++ interface translator only needs to know about the public inheritance, and thus public is implicit. A Chare can inherit privately from other classes too, but the Charm++ interface translator does not need to know about it, because it generates support classes ( proxies ) to remotely invoke only public methods. The class definitions of these chares should look like:


   class BaseChare : public CBase_BaseChare {
    // private or protected data
    public:
      BaseChare(someMessage *);
      void baseMethod(void);
  };
  class DerivedChare : public CBase_DerivedChare {
    // private or protected data
    public:
      DerivedChare(otherMessage *);
      void derivedMethod(void);
  };

It is possible to create a derived chare, and invoke methods of base chare from it, or to assign a derived chare proxy to a base chare proxy as shown below:


   ...
  otherMessage *msg = new otherMessage();
  CProxy_DerivedChare pd = CProxy_DerivedChare::ckNew(msg);
  pd.baseMethod();     // OK
  pd.derivedMethod();  // OK
  ...
  CProxy_BaseChare pb = pd;
  pb.baseMethod();    // OK
  pb.derivedMethod(); // COMPILE ERROR

To pass constructor arguments from DerivedChare::DerivedChare(someMessage*) to BaseChare::BaseChare(someMessage*), they can be forwarded through the CBase type constructor as follows:


 DerivedChare::DerivedChare(someMessage *msg)
: CBase_DerivedChare(msg) // Will forward all arguments to BaseChare::BaseChare


If no arguments are provided, the generated C++ code for the CBase_DerivedChare constructor calls the default constructor of the base class BaseChare.

Entry methods are inherited in the same manner as methods of sequential C++ objects. To make an entry method virtual, just add the keyword virtual to the corresponding chare method declaration in the class header- no change is needed in the interface file. Pure virtual entry methods also require no special description in the interface file.

15 . 2 Inheritance for Messages

Messages cannot inherit from other messages. A message can, however, inherit from a regular C++ class. For example:


 //In the .ci file:
  message BaseMessage1;
  message BaseMessage2;

//In the .h file:
  class Base {
    // ...
  };
  class BaseMessage1 : public Base, public CMessage_BaseMessage1 {
    // ...
  };
  class BaseMessage2 : public Base, public CMessage_BaseMessage2 {
    // ...
  };

Messages cannot contain virtual methods or virtual base classes unless you use a packed message. Parameter marshalling has complete support for inheritance, virtual methods, and virtual base classes via the PUP::able framework.


 %#define CK_TEMPLATES_ONLY
%#include "stlib.def.h"
%#undef CK_TEMPLATES_ONLY
%

 %  template <class DType=int, int N=3> message TMessage;
%  message TMessage<>; // same as TMessage<int,3>
%  message TMessage<double>; // same as TMessage<double, 3>
%  message TMessage<UserType, 1>;
%

 %module SCTL {
%  template <class dtype> message  Singleton;
%  template <class dtype> group Reducer {
%    entry Reducer(void);
%    entry void submit(Singleton<dtype> *);
%  }
%  template <class dtype> chare ReductionClient {
%    entry void recvResult(Singleton<dtype> *);
%  }
%};
%
%module User {
%  extern module SCTL;
%  message Singleton<int>;
%  group Reducer<int>;
%  chare RedcutionClient<int>;
%  chare UserClient : ReductionClient<int> {
%    entry UserClient(void);
%  }
%};
%