#include "charm.h"
#include <stdlib.h>

#define NITER 10000000

int idx_mychare;
int idx_next;
int idx_createChare;

typedef struct {
  double stime;
  int iter;
  CkChareID myid;
} mychare;

void createChare(void *msg, mychare *c)
{
  CkGetChareID(&(c->myid));
  CkSendMsg(idx_next, msg, &(c->myid));
  c->iter = 0;
  c->stime = CkWallTimer();
}

void next(void *msg, mychare *c)
{
  c->iter++;
  if(c->iter==NITER)
  {
    double etime = CkWallTimer();
    CkPrintf("Time per iteration = %lf microseconds\n", 
             (etime-c->stime)*1.e6/NITER);
    CkFreeSysMsg(msg);
    CkExit();
  } else
  {
    CkSendMsg(idx_next, msg, &(c->myid));
  }
}

void registerSched(void)
{
  idx_mychare = CkRegisterChare("mychare", sizeof(mychare));
  idx_createChare = CkRegisterEp("createChare", (CkCallFnPtr) createChare,
                                   0, idx_mychare);
  idx_next = CkRegisterEp("next", (CkCallFnPtr) next, 0, idx_mychare);
}

int idx_Main;
int idx_createMain;

typedef struct {
  int dummy;
} Main;

void createMain(CkArgMsg *msg, Main *main)
{
  CkFreeMsg(msg);
  CkCreateChare(idx_mychare, idx_createChare, CkAllocSysMsg(), 0, 0);
}

void CkRegisterMainModule(void)
{
  registerSched();
  idx_Main = CkRegisterChare("Main", sizeof(Main));
  idx_createMain = CkRegisterEp("createMain", (CkCallFnPtr) createMain,
                                0, idx_Main);
  CkRegisterMainChare(idx_Main, idx_createMain);
}
