\chapter{\converse{} Master-Slave Library}

\section{Introduction}

CMS is the implementation of the master-slave (or manager-worker or
agenda) parallel programming paradigm on top of \converse{}.

\section{Available Functions}

Following functions are available in this library:

\function{typedef int (*CmsWorkerFn) (void *, void *);}
\desc{Prototype for the worker function. See below.}

\function{typedef int (*CmsConsumerFn) (void *, int);}
\desc{Prototype for the consumer function. See below.}

\function{void CmsInit(CmsWorkerFn worker, int max); }
\desc{
  This function must be called before firing any tasks for the workers.
  \uw{max} is the largest possible number of tasks you will fire
  before calling either \kw{CmsAwaitResponses} or \kw{CmsProcessResponses}
  next. (So the system know how many it may have to buffer).
}

\function{int worker(void *t, void **r)}
\desc{
  The user writes this function. Its name does not have to be 
  \uw{worker}; It can be anything. \uw{worker} can be any function
  that the use writes to perform the task on the slave
  processors. It must allocate and compute the response 
  data structure, and return a pointer to it, by assigning to \uw{r};
  It must also return the size of the response data structure as
  its return value.
}

\function{void CmsFireTask(int ref, void * t, int size)}
\desc{
  Creates task to be worked on by a worker. The task description
  is pointed to by \uw{t}, and goes on for \uw{size} bytes. \uw{ref} 
  must be a unique serial number between 0 and \uw{max} (see \kw{CmsInit}).
}

\function{void CmsAwaitResponses(void); }
\desc{  
  This call allows the system to use processor 0 as a worker. It
  returns after all the tasks have sent back their responses. The
  responses themselves can be extracted using \kw{CmsGetResponse}.
}

\function{void *CmsGetResponse(int ref);}
\desc{
  Extracts the response associated with the reference number \uw{ref}
  from the system's buffers.
}

\function{void CmsProcessResponses(CmsConsumerFn consumer);}
\desc{
  Instead of using \kw{CmsAwaitResponses}/\kw{CmsGetResponse} pair, 
  you can use this call alone. It turns the control over to the CMS system
  on processor 0, so it can be used as a worker. As soon as a
  response is available on processor 0, cms calls the user
  specified \uw{consumer} function with two parameters: the
  response (a void *) and an integer \uw{refnum}. 
  (Question:\experimental{} should the size of the response be passed as a
  parameter to the consumer? User can do that as an explicit
  field of the response themselves, if necessary.)
}

\function{void CmsExit(void);}
\desc{
  Must be called on all processors to terminate execution.
}

Once either \kw{CmsProcessResponses} or \kw{CmsAwaitResponses} returns, you may
fire the next batch of tasks via \kw{CmsFireTask} again.

\section{Example Program}

\begin{alltt}
#include "cms.h"

#define MAX 10

typedef struct \{
    float a;
\} Task;

typedef struct \{
    float result;
\} Response;

Task t;

int worker(Task *t, Response **r)
\{
    /* do work and generate a single response */
    int i;
    Task *t1;
    int k;

    CmiPrintf("%d: in worker %f \verb+\n+", CmiMyPe(), t->a);
    *r = (Response *) malloc(sizeof(Response));
    (*r)->result = t->a * t->a;
    return sizeof(Response);
\}

int consumer(Response * r, int refnum)
\{
    CmiPrintf("consumer: response with refnum = %d is %f\verb+\n+", refnum,
              r->result);
\}

main(int argc, char *argv[])
\{
    int i, j, k, ref;
    /* 2nd parameter is the max number of tasks 
     * fired before "awaitResponses"
     */
    CmsInit((CmsWorkerFn)worker, 20);
    if (CmiMyPe() == 0) \{ /* I am the manager */
        CmiPrintf("manager inited\verb+\n+");
        for (i = 0; i < 3; i++) \{ /* number of iterations or phases */
          /* prepare the next generation of problems to solve */
          /* then, fire the next batch of tasks for the worker */
            for (j = 0; j < 5; j++) \{
                t.a = 10 * i + j;
                ref = j;  /* a ref number to associate with the task, */
                /* so that the reponse for this task can be identified. */
                CmsFireTask(ref, \&t, sizeof(t));
            \}
          /* Now wait for the responses */
            CmsAwaitResponses();  /* allows proc 0 to be used as a worker. */
            /* Now extract the resoneses from the system */
            for (j = 0; j < 5; j++) \{
                Response *r = (Response *) CmsGetResponse(j);
                CmiPrintf("Response %d is: %f \verb+\n+", j, r->result);
            \}
          /* End of one mast-slave phase */
            CmiPrintf("End of phase %d\verb+\n+", i);
        \}
    \}

    CmiPrintf("Now the consumerFunction mode\verb+\n+");

    if (CmiMyPe() == 0) \{ /* I am the manager */
       for (i = 0; i < 3; i++) \{
           t.a = 5 + i;
           CmsFireTask(i, \&t, sizeof(t));
       \}
       CmsProcessResponses((CmsConsumerFn)consumer);
       /* Also allows proc. 0 to be used as a worker. 
        * In addition, responses will be processed on processor 0 
        * via the "consumer" function as soon as they are available 
        */
    \}
    CmsExit();
\}
\end{alltt}
