#include <HPCxx_Profile.h>
#include <math.h>
#include <assert.h>
#include <iostream.h>
#include <hpcxx_rts.h>
#include <HPCxx_Sync.cc>
#include <hpcxx_invoke.cc>
#include <hpcxx_register.cc>
#include <HPCxx_GlobalPtr.cc>
#include <hpcxx_invokeImpl.cc>
#include <HPCxx_GlobalRefImpl.cc>

/***********************************************************************
tjs - 98.10.07

This example is to show the basic functioning of global pointers

Run this example with two contexts:

tim_gp_xmpl -nx -n 1

This example was mostly stolen from TestGP.

I don't know why but sometimes when this is run it hangs with the error
message:

select: protocol failure in circuit setup.

***********************************************************************/

HPCxx_Mutex outLock;


HPCxx_GlobalPtr<int> getGP(void);

HPCxx_GlobalPtr<int> intGPExport;

HPCxx_GlobalPtr<int> getGP(void)
{
  return(intGPExport);
}

int main(int argc, char* argv[])
{
  int intArray[10];

  //
  // initialize HPC++
  //
  HPCxx_Group* group;
  hpcxx_init(argc, argv, group);

  //
  // all processes are executing in SPMD mode at this point
  //

  int numContexts = group->getNumContexts() - 1;
  int myContext = group->getLocalIndex();

  // declare the global pointer.  Initially it is local to the
  // context in which it is declared
  
  HPCxx_GlobalPtr<int> intGP(intArray);

  // get a pointer to the context ID of the master server context
  HPCxx_ContextID serverContext = *group->getContextID(0);

  // register the function that will provide the global pointer to
  // the client contexts

  int getGPID = hpcxx_register(getGP,10);

  if(myContext == 0) {

    // note, if context 0 hasn't set the global pointer that
    // context 1 will use to get the data, the program will crash.
    // a barrier can prevent this.

    sleep(10);
    for(int i=0;i<10;i++) intArray[i] = i;
    intGPExport = intGP;
    hpcxx_barrier();
  }

  if(myContext == 1) {

    // call the remotefunction, arguments are
    // context in which to execute, the return value, the function ID,
    // and the argument.

    hpcxx_barrier();

    hpcxx_invoke(serverContext, intGP, getGPID);  
    cout << "Context " << myContext << " got GP"
	 << endl << flush;


    intGP.read(intArray,10);
    for(int i=0;i<10;i++) cout << "intArray[ " << i << "] = " << i
	 << endl << flush;
  }

  return hpcxx_exit(group);
}
