Cheetah ControllerImpl Reference

The Controller class is just an interface class. All of the nontrivial processing takes place in subclasses of ControllerImpl. ControllerImpl itself is an abstract base class, and most of its functions are abstract virtual functions. All of the actual communication takes place in the virtual functions defined in the subclass.

For a general overview of the motivation and architecture and motivation for controllers, see the controller guide. Here we provide a detailed description of the interface and guidance for how to define subclasses for new communication layers.

Base Classes

RefCounted

All ControllerImpls are reference counted, so that multiple Controllers can easily refer to on ControllerImpl. This base class, together with RefCountedPtr, ensures that the ControllerImpl is destroyed when all of the Controllers referring to it are gone.

Constructors and Destructor

ControllerImpl()

The null ctor initializes the number of contexts and the current context to invalid values. The constructor for the subclass must overwrite these values with appropriate ones once the correct values are known.

Virtual ~Controller()

The destructor is defined to be virtual so that the subclasses' destructors are properly called, but takes no other action;

Typedefs

typedef void (*Handler_t)(int who, int tag, void* buf,int len);

The type for a handler called by ainvoke. 'Who' is the calling context, 'tag' is the integer ID that the calling context used to call this function, 'buf' is a pointer to the data buffer the calling context sent, and 'len' is the number of bytes in the buffer. The system will handle deleting the buffer, so the user should not free it.

Query Functions

int ncontexts() const

Return the number of contexts that are available through this controller. Asserts that the controller is valid.

int mycontext() const

Return the number for this context in [0...ncontexts-1]. Asserts that the controller is valid.

Messaging Functions

virtual int registerHandler(Handler_t handler) = 0

Register a new ainvoke handler with this controller. Returns an integer tag to be used in ainvoke to call this function remotely.

Virtual void ainvoke(int context, int tag, void *buffer, int len, int *local_bell) = 0

Call the function registered as 'tag' in 'context' with the provided 'buffer' of length 'len'. When the local buffer can be reused (either by copying it into a system buffer or into the network) the local bell is rung. If local_bell==0, this function becomes synchronous in the sense that the buffer can be reused immediately upon return from ainvoke.

No guarantees are made about when the remote function is actually invoked! In particular, ringing the local bell does not imply that the remote function has been called.

No guarantees are made about how the buffer is packed with user data: it is up the handler being called to understand the packing of the buffer.

No value is returned from the remote function. If the user wishes to return some result from calling the function it should be handled by passing information about how to return that value in the buffer.

The 'poll' or 'wait' function below must be called at some point in the remote context for the ainvoke to be called in that context.

virtual void put(int context, void *remote, void *local, int len, int *local_bell, int *remote_bell) = 0

Put data in the 'local' buffer of length 'len' to the 'remote' buffer in another 'context'. Ring 'local_bell' in this context when the local buffer can be reused, and ring 'remote_bell' in the remote context when the destination buffer has been filled.

In general, the 'poll' or 'wait' function below must be called at some point in the remote context for the data to be copied into the remote buffer.

virtual void get(int context, void *remote, void *local, int len, int *local_bell, int *remote_bell) = 0

Get data from a buffer 'remote' of length 'len' in a remote 'context' and put it in the 'local' buffer. Ring 'remote_bell' in the remote context when the data has been copied out of that buffer, and ring 'local_bell' when it has been copied into the local buffer.

In general, the 'poll' or 'wait' function below must be called in the local and remote contexts for the data to be copied.

virtual void barrier() = 0

Wait until all of the other contexts associated with this controller to also call barrier. No context will exit the barrier until all of the contexts have entered the barrier.

virtual void poll() = 0

Process the currently pending message events that have come off the wire, but don't wait around for any new things to come off the wire.

virtual void wait(volatile int *bell, int value) = 0

Wait until the provided bell reaches the provided value. Call poll while waiting to keep messages flowing.

Command Line Factory

We want to be able to select the communication layer using command line arguments, and we want to be able to add new subclasses of ControllerImpl without modifying any of the existing subclasses. We handle this with a factory mechanism.

typedef ControllerImpl* (*Factory_t)(int &argc, char **&argv)

Each subclass that can be initialized through the command line arguments must define a static function of type Factory_t. The arguments to that function will be the command line arguments, and it must return a pointer to a new ControllerImpl of that subclass type. It can use any of the command line arguments it chooses to in order to initialize the new ControllerImpl.

static void registerFactory(const char *name, Factory_t)

Before you try to use the command line argument factory, each subclass must register its factory function by calling this function together with its name. Each subclass should choose a unique name, and whichever name appears on the command line will be the factory function that gets called to generate the appropriate ControllerImpl.

static ControllerImpl* factory(int &argc, char **&argv)

In the constructor for Controller which takes command line arguments, it calls this static member function of the abstract base class ControllerImpl. This function scans through the command line to find a string that matches one of the registered factory names. If it finds a match it calls the registered factory with the provided command line to build the ControllerImpl.