MSA: Consolidate handle-based API
authorPhil Miller <mille121@illinois.edu>
Wed, 8 Dec 2010 01:02:48 +0000 (19:02 -0600)
committerPhil Miller <mille121@illinois.edu>
Wed, 8 Dec 2010 01:29:56 +0000 (19:29 -0600)
Factor out the handle classes from the individual MSA dimensions, so
that they all behave the same way.

- Standardize on handles passed by value in the process.
- Remove the Accum::accumulate(int x, [int y[, int z,] ENTRY e)
  methods, because they can be ambiguous with an ENTRY type
  convertible to int.

Update ParFUM's parallel remeshing and some examples correspondingly.

examples/multiphaseSharedArrays/moldyn/moldyn.C
examples/multiphaseSharedArrays/simpleTestVarsize/t3.C
examples/multiphaseSharedArrays/simpletest/t3.C
src/libs/ck-libs/ParFUM/MsaHashtable.C
src/libs/ck-libs/ParFUM/MsaHashtable.h
src/libs/ck-libs/ParFUM/ParFUM_internals.h
src/libs/ck-libs/ParFUM/adapt_adj.C
src/libs/ck-libs/ParFUM/adapt_adj.h
src/libs/ck-libs/ParFUM/parallel_part.C
src/libs/ck-libs/multiphaseSharedArrays/msa-distArray.h

index 0438604f4d6d1b37da60eb177a80ba49ac94807b..f8cff797e2e47066e82e23f9ca187cf072368bfe 100644 (file)
@@ -26,9 +26,9 @@ public:
 };
 PUPbytes(AtomInfo);
 
-typedef MSA1D<XYZ, DefaultEntry<XYZ,false>, NEPP> XyzMSA;
-typedef MSA1D<AtomInfo, DefaultEntry<AtomInfo,false>, NEPP> AtomInfoMSA;
-typedef MSA2D<bool, DefaultEntry<bool,false>, NEPP, MSA_ROW_MAJOR> NeighborMSA;
+typedef MSA::MSA1D<XYZ, DefaultEntry<XYZ,false>, NEPP> XyzMSA;
+typedef MSA::MSA1D<AtomInfo, DefaultEntry<AtomInfo,false>, NEPP> AtomInfoMSA;
+typedef MSA::MSA2D<bool, DefaultEntry<bool,false>, NEPP, MSA_ROW_MAJOR> NeighborMSA;
 
 #include "moldyn.decl.h"
 
@@ -218,19 +218,18 @@ protected:
        return sqrt(dx*dx + dy*dy + dz*dz);
   }
 
-  void PlimptonMD(XyzMSA::Handle &hCoords, XyzMSA::Handle &hForces, 
-                                 NeighborMSA::Handle &hNbr, AtomInfoMSA::Read &rAtominfo)
+  void PlimptonMD(XyzMSA::Handle hCoords, XyzMSA::Handle hForces, NeighborMSA::Handle hNbr)
   {
        unsigned int i_start, i_end, j_start, j_end;
        GetMyIndices(NUM_ATOMS-1, toX(), numWorkers2D(), i_start, i_end);
        GetMyIndices(NUM_ATOMS-1, toY(), numWorkers2D(), j_start, j_end);
 
-       XyzMSA::Read rCoords = coords.syncToRead(hCoords);
-       NeighborMSA::Read rNbr = nbrList.syncToRead(hNbr);
+       XyzMSA::Read rCoords = hCoords.syncToRead();
+       NeighborMSA::Read rNbr = hNbr.syncToRead();
 
        for (unsigned int timestep = 0; timestep < NUM_TIMESTEPS; timestep++) {
          // Force calculation for a section of the interaction matrix
-         XyzMSA::Accum aForces = forces.syncToAccum(hForces);
+         XyzMSA::Accum aForces = hForces.syncToAccum();
          for (unsigned int i = i_start; i< i_end; i++)
                for (unsigned int j = j_start; j< j_end; j++)
                  if (rNbr(i,j)) {
@@ -244,15 +243,15 @@ protected:
 
          // Movement Integration for our subset of atoms
          unsigned int myAtomsBegin, myAtomsEnd;
-         XyzMSA::Read rForces = forces.syncToRead(aForces);
-         XyzMSA::Write wCoords = coords.syncToWrite(rCoords);
+         XyzMSA::Read rForces = aForces.syncToRead();
+         XyzMSA::Write wCoords = rCoords.syncToWrite();
          for (unsigned int k = myAtomsBegin; k<myAtomsEnd; k++)
                wCoords(k) = integrate(rAtominfo(k), rForces(k));
 
          // Neighbor list recalculation for our section of the interaction matrix
-         rCoords = coords.syncToRead(wCoords);
+         rCoords = wCoords.syncToRead();
          if  (timestep % 8 == 0) { // update neighbor list every 8 steps
-               NeighborMSA::Write wNbr = nbrList.syncToWrite(rNbr);
+               NeighborMSA::Write wNbr = rNbr.syncToWrite();
                for (unsigned int i = i_start; i< i_end; i++)
                  for (unsigned int j = j_start; j< j_end; j++)
                        if (distance(rCoords(i), rCoords(j)) < CUTOFF_DISTANCE) {
@@ -262,7 +261,7 @@ protected:
                          wNbr.set(i,j) = false;
                          wNbr.set(j,i) = false;
                        }
-               rNbr = nbrList.syncToRead(wNbr);
+               rNbr = wNbr.syncToRead();
          }
 
          hForces = rForces;
@@ -365,7 +364,7 @@ public:
 
         if(verbose) ckout << thisIndex << ": product" << endl;
 
-        PlimptonMD(coords.getInitialWrite(), forces.getInitialWrite(), nbrList.getInitialWrite(), rAtominfo);
+        PlimptonMD(coords.getInitialWrite(), forces.getInitialWrite(), nbrList.getInitialWrite());
         times.push_back(CkWallTimer()); // 5
         description.push_back("    work");
 
index 6eb0126ad678e81eb4924f0d15c99f34d2823bdc..f79b964653db5dd82f4c0369e75f7cfc36939411 100644 (file)
@@ -1,7 +1,7 @@
 // -*- mode: c++; tab-width: 4 -*-
 #include "msa/msa.h"
 class Double;
-typedef MSA2D<Double, DefaultEntry<Double,true>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
+typedef MSA::MSA2D<Double, DefaultEntry<Double,true>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
 
 #include "t3.decl.h"
 
@@ -279,7 +279,7 @@ class TestArray : public CBase_TestArray
 {
 protected:
     MSA2DRM arr1;       // row major
-       MSA2DRM::Read *r2;
+       MSA2DRM::Read r2;
 
     unsigned int rows1, cols1, numWorkers;
 
@@ -298,13 +298,13 @@ protected:
 
     void FindProduct(MSA2DRM::Accum &a)
     {
-        a.accumulate(arr1.getIndex(0,0), 2.0 + thisIndex);
-        a.accumulate(arr1.getIndex(0,0), 100.0 + thisIndex);
+        a(arr1.getIndex(0,0)) += 2.0 + thisIndex;
+        a(arr1.getIndex(0,0)) += 100.0 + thisIndex;
     }
 
     void TestResults()
     {
-               MSA2DRM::Read &rh = *r2;
+               MSA2DRM::Read rh = r2;
         int error1 = 0, error2 = 0, error3=0;
 
         // verify the results
@@ -352,12 +352,12 @@ public:
     {
         arr1.enroll(numWorkers); // barrier
         if(do_message) ckout << "w" << thisIndex << ": filling" << endl;
-               MSA2DRM::Write &w = arr1.getInitialWrite();
+               MSA2DRM::Write w = arr1.getInitialWrite();
         FillArray(w);
-               r2 = &arr1.syncToRead(w);
+               r2 = w.syncToRead();
         if(do_message)
                        ckout << "w" << thisIndex << ":value "
-                                 << r2->get(XVAL,YVAL) << "," << r2->get(XVAL,YVAL+1)  << endl;
+                                 << r2.get(XVAL,YVAL) << "," << r2.get(XVAL,YVAL+1)  << endl;
 //         (arr1.getCacheGroup()).emitBufferValue(6, 0);
         if(do_message)
                        ckout << "w" << thisIndex << ": syncing" << endl;
@@ -372,17 +372,17 @@ public:
         if(do_message) ckout << thisIndex << ": testing after fillarray, sync, and redn" << endl;
         TestResults();
 
-               MSA2DRM::Accum &a = arr1.syncToAccum(*r2);
+               MSA2DRM::Accum a = r2.syncToAccum();
 
         if(do_message) ckout << thisIndex << ": producting" << endl;
         FindProduct(a);
 
-               r2 = &arr1.syncToRead(a);
+               r2 = a.syncToRead();
 //         if(do_message) ckout << thisIndex << ": tetsing after product" << endl;
 //      TestResults();
 
         // Print out the accumulated element.
-        ckout << "p" << CkMyPe() << "w" << thisIndex << ":" << r2->get(0,0) << endl;
+        ckout << "p" << CkMyPe() << "w" << thisIndex << ":" << r2.get(0,0) << endl;
 
         Contribute();
     }
index 086dab8ed3d3f1900cccb1211850734ea8a42f9b..5c4e7940c43e20a9f463cdc996e1c02611b92832 100644 (file)
@@ -1,7 +1,8 @@
 // -*- mode: c++; tab-width: 4 -*-
 #include "msa/msa.h"
 
-typedef MSA2D<double, DefaultEntry<double>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
+
+typedef MSA::MSA2D<double, DefaultEntry<double>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
 
 #include "t3.decl.h"
 
@@ -157,9 +158,9 @@ public:
     void Start()
     {
         arr1.enroll(numWorkers); // barrier
-               MSA2DRM::Write &w = arr1.getInitialWrite();
+               MSA2DRM::Write w = arr1.getInitialWrite();
         FillArray(w);
-               MSA2DRM::Read &r = arr1.syncToRead(w);
+               MSA2DRM::Read r = w.syncToRead();
         TestResults(r);  // test before doing a reduction
         Contribute();
     }
index 24e3e317fe3d77f03e6dbd4acae779b27ab660ad..8f4a05bc7162890fcd8802b68be2a32a7e49ffe9 100644 (file)
@@ -2,45 +2,38 @@
 #include "ParFUM_internals.h"
 #include "MsaHashtable.h"
 
+using namespace MSA;
+
 void operator+=(Hashtuple &t, const Hashnode &n)
 {
     t.vec->push_back(n);
 }
 
-MsaHashtable::Add& MsaHashtable::getInitialAdd()
+MsaHashtable::Add MsaHashtable::getInitialAdd()
 {
        if(initHandleGiven)
                throw MSA_InvalidHandle();
        
-       Add *a = new Add(*this);
-       sync();
        initHandleGiven = true;
-       return *a;
+       return Add(&this->msa);
 }
 
-MsaHashtable::Add& MsaHashtable::syncToAdd(Read &r)
+MsaHashtable::Add MsaHashtable::Read::syncToAdd()
 {
-       r.checkInvalidate(this);
-       delete &r;
-       sync();
-       Add *a = new Add(*this);
-       return *a;
+    syncDone();
+    return Add(msa);
 }
 
-MsaHashtable::Read& MsaHashtable::syncToRead(Add &a)
+MsaHashtable::Read MsaHashtable::Add::syncToRead()
 {
-       a.checkInvalidate(this);
-       delete &a;
-       sync();
-       Read *r = new Read(*this);
-       return *r;
+       syncDone();
+       return Read(msa);
 }
 
 void MsaHashtable::Read::print()
 {
-       unsigned nEntries = MSA1DHASH::Read::msa.length();
        char str[100];
-       for(int i=0;i<nEntries;i++){
+       for(int i=0; i < msa->length(); i++) {
                const Hashtuple &t = get(i);
                for(int j=0;j<t.vec->size();j++){
                        Hashnode &tuple = (*t.vec)[j];
@@ -53,8 +46,7 @@ void MsaHashtable::Read::print()
 
 int MsaHashtable::Add::addTuple(int *tuple,int nodesPerTuple,int chunk,int elementNo)
 {
-       int slots = msa.length();
-
+    int slots = msa->length();
        // sort the tuples to get a canonical form
        // bubble sort should do just as well since the number
        // of nodes is less than 10.
index 3a79680c1661aa7d5946c943a207b402cc87e304..91bb3cba1a26deea81572d77d691baf7f6611fc6 100644 (file)
@@ -5,55 +5,46 @@
 #include "ParFUM_internals.h"
 
 typedef UniqElemList<Hashnode> Hashtuple;
-typedef MSA1D<Hashtuple,DefaultListEntry<Hashtuple,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DHASH;
+typedef MSA::MSA1D<Hashtuple,DefaultListEntry<Hashtuple,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DHASH;
 
-class MsaHashtable : private MSA1DHASH
+class MsaHashtable
 {
+    MSA1DHASH msa;
+    bool initHandleGiven;
+
 public:
        class Read; class Add;
-       Read& syncToRead(Add&);
-       Add&  syncToAdd(Read&);
-       Add& getInitialAdd();
-       using MSA1DHASH::pup;
-       using MSA1DHASH::enroll;
+       friend class Read; friend class Add;
+       Add getInitialAdd();
+       void pup(PUP::er &p) { p|msa; }
+       void enroll(int n) { msa.enroll(n); }
 
-       class Read : private MSA1DHASH::Read
+       class Read : private MSA::MSARead<MSA1DHASH>
        {
        public:
-               using MSA1DHASH::Read::get;
-               // Non-specific friend declarations because Sun's
-               // C++ compiler doesn't understand that it should
-               // fully parse outer classes before examining nested
-               // classes. (2008-10-23)
-               /*
-               friend Read &MsaHashtable::syncToRead(Add&);
-               friend Add& MsaHashtable::syncToAdd(Read&);
-               */
+           using MSA::MSARead<MSA1DHASH>::get;
+
                friend class MsaHashtable;
                void print();
+               Add syncToAdd();
 
        private:
-       Read(MsaHashtable &m) : MSA1DHASH::Read(m) { }
+       Read(MSA1DHASH *m) : MSA::MSARead<MSA1DHASH>(m) { }
        };
 
-       class Add : private MSA1DHASH::Accum
+       class Add : private MSA::MSAAccum<MSA1DHASH>
        {
-               using MSA1DHASH::Accum::accumulate;
-               // See comments above about non-specific friends
-               /*
-               friend Add& MsaHashtable::syncToAdd(Read&);
-               friend Read &MsaHashtable::syncToRead(Add&);
-               friend Add& MsaHashtable::getInitialAdd();
-               */
-               friend class MsaHashtable;
-       Add(MsaHashtable &m) : MSA1DHASH::Accum(m) { }
+           using MSA::MSAAccum<MSA1DHASH>::accumulate;
+           friend class MsaHashtable;
+       Add(MSA1DHASH *m) : MSA::MSAAccum<MSA1DHASH>(m) { }
        public:
                int addTuple(int *tuple, int nodesPerTuple, int chunk, int elementNo);
+               Read syncToRead();
        };
 
 
 MsaHashtable(int _numSlots,int numWorkers)
-       : MSA1DHASH(_numSlots, numWorkers) { }
+    : msa(_numSlots, numWorkers), initHandleGiven(false) { }
        MsaHashtable(){};
 };
 
index 89da545934a5173ac400eea1b69da36f39060f82..0e2a6f4820d9cfcbac2e6390d7c1e2ecb86188ba 100644 (file)
@@ -2467,17 +2467,17 @@ public:
   }
 };
 
-typedef MSA2D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
+typedef MSA::MSA2D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
 
-typedef MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINT;
+typedef MSA::MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINT;
 
 typedef UniqElemList<int> IntList;
-typedef MSA1D<IntList, DefaultListEntry<IntList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINTLIST;
+typedef MSA::MSA1D<IntList, DefaultListEntry<IntList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINTLIST;
 
 typedef UniqElemList<NodeElem> NodeList;
-typedef MSA1D<NodeList, DefaultListEntry<NodeList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DNODELIST;
+typedef MSA::MSA1D<NodeList, DefaultListEntry<NodeList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DNODELIST;
 
-typedef MSA1D<MeshElem,DefaultEntry<MeshElem,true>,1> MSA1DFEMMESH;
+typedef MSA::MSA1D<MeshElem,DefaultEntry<MeshElem,true>,1> MSA1DFEMMESH;
 
 
 
index 9f1034b3fc88bb55ff99814664902bbb5a0784a9..49238a4870d6cb401b228eb3b3cf17e1902edc24 100644 (file)
@@ -280,7 +280,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
     }
     MPI_Bcast_pup(*requestTable,0,MPI_COMM_WORLD);
     requestTable->enroll(numChunks);
-    MSA1DREQLIST::Accum &requestTableAcc = requestTable->getInitialAccum();
+    MSA1DREQLIST::Accum requestTableAcc = requestTable->getInitialAccum();
 
     makeAdjacencyRequests(
             numNodes,
@@ -291,7 +291,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
             myRank,
             elemType);
 
-    MSA1DREQLIST::Read &reqTableRead = requestTable->syncToRead(requestTableAcc);
+    MSA1DREQLIST::Read reqTableRead = requestTableAcc.syncToRead();
     //printf("[%d] All face requests made \n",myRank);
 
     MSA1DREPLYLIST *replyTable;
@@ -302,7 +302,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
     }
     MPI_Bcast_pup(*replyTable,0,MPI_COMM_WORLD);
     replyTable->enroll(numChunks);
-    MSA1DREPLYLIST::Accum &replyAcc = replyTable->getInitialAccum();
+    MSA1DREPLYLIST::Accum replyAcc = replyTable->getInitialAccum();
 
     replyAdjacencyRequests(
             reqTableRead.get(myRank).vec,
@@ -317,8 +317,8 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
             elemType,
             false);
 
-    requestTable->syncToRead(reqTableRead);
-    replyTable->syncToRead(replyAcc);
+    reqTableRead.syncDone();
+    replyAcc.syncDone();
 
 //    // Once the replies are back, loop through each reply and update the
 //    // adjacencies for each element in the reply
@@ -350,7 +350,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
         }
         MPI_Bcast_pup(*edgeRequestTable,0,MPI_COMM_WORLD);
         edgeRequestTable->enroll(numChunks);
-       MSA1DREQLIST::Accum &edgeRequestTableAcc = requestTable->getInitialAccum();
+       MSA1DREQLIST::Accum edgeRequestTableAcc = requestTable->getInitialAccum();
 
         makeAdjacencyRequests(
                 numNodes,
@@ -361,7 +361,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
                 myRank,
                 elemType);
 
-       MSA1DREQLIST::Read &edgeReqRead = edgeRequestTable->syncToRead(edgeRequestTableAcc);
+       MSA1DREQLIST::Read edgeReqRead = edgeRequestTableAcc.syncToRead();
         //printf("[%d] All edge requests made \n",myRank);
 
         if (myRank == 0) {
@@ -371,7 +371,7 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
         }
         MPI_Bcast_pup(*edgeReplyTable,0,MPI_COMM_WORLD);
         edgeReplyTable->enroll(numChunks);
-       MSA1DREPLYLIST::Accum &edgeReplyAcc = edgeReplyTable->getInitialAccum();
+       MSA1DREPLYLIST::Accum edgeReplyAcc = edgeReplyTable->getInitialAccum();
 
         replyAdjacencyRequests(
                 edgeReqRead.get(myRank).vec,
@@ -386,8 +386,8 @@ void CreateAdaptAdjacencies(int meshid, int elemType)
                 elemType,
                 true);
 
-        edgeRequestTable->syncToRead(edgeReqRead);
-        edgeReplyTable->syncToRead(edgeReplyAcc);
+        edgeReqRead.syncDone();
+        edgeReplyAcc.syncDone();
 
 //        // Once the replies are back, loop through each reply and update the
 //        // adjacencies for each element in the reply
index 8f227807375891937b9acabf5cd66f415153d443..7b25c6de077bce02567a92a2e511abb04c183bca 100644 (file)
@@ -203,10 +203,10 @@ class adjReply {
 
 
 typedef ElemList<adjRequest> AdjRequestList;
-typedef MSA1D<AdjRequestList, DefaultListEntry<AdjRequestList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DREQLIST;
+typedef MSA::MSA1D<AdjRequestList, DefaultListEntry<AdjRequestList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DREQLIST;
 
 typedef ElemList<adjReply> AdjReplyList;
-typedef MSA1D<AdjReplyList, DefaultListEntry<AdjReplyList,true>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DREPLYLIST;
+typedef MSA::MSA1D<AdjReplyList, DefaultListEntry<AdjReplyList,true>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DREPLYLIST;
 
 /** Create Adaptivity Adjacencies for elemType; dimension inferred. */
 void CreateAdaptAdjacencies(int meshid, int elemType);
index 3f4a0323b8bbac732a042d6ca2caef394088834e..885ecb91ae61951d24ec92071d5c180c3d337639 100644 (file)
@@ -75,8 +75,8 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
 
   eptrMSA.enroll(numChunks);
   eindMSA.enroll(numChunks);
-  MSA1DINT::Write &wPtr = eptrMSA.getInitialWrite();
-  MSA1DINT::Write &wInd = eindMSA.getInitialWrite();
+  MSA1DINT::Write wPtr = eptrMSA.getInitialWrite();
+  MSA1DINT::Write wInd = eindMSA.getInitialWrite();
   int indcount=0,ptrcount=0;
   for(int t=0;t<m->elem.size();t++){
     if(m->elem.has(t)){
@@ -113,8 +113,8 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
     call parmetis
   */
   double  parStartTime = CkWallTimer();
-  MSA1DINT::Read &rPtr = eptrMSA.syncToRead(wPtr);
-  MSA1DINT::Read &rInd = eindMSA.syncToRead(wInd);
+  MSA1DINT::Read rPtr = wPtr.syncToRead();
+  MSA1DINT::Read rInd = wInd.syncToRead();
   printf("starting FEM_call_parmetis \n");
   struct partconndata *partdata = FEM_call_parmetis(data.nelem, rPtr, rInd, comm_context);
 
@@ -129,12 +129,12 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
   MSA1DINTLIST nodepart(totalNodes,numChunks);
   MPI_Bcast_pup(nodepart,masterRank,(MPI_Comm)comm_context);
   nodepart.enroll(numChunks);
-  MSA1DINTLIST::Accum &nodepartAcc = nodepart.getInitialAccum();
+  MSA1DINTLIST::Accum nodepartAcc = nodepart.getInitialAccum();
        
   FEM_write_nodepart(nodepartAcc,partdata,(MPI_Comm)comm_context);
   printf("Creating mapping of node to partition took %.6lf\n",CkWallTimer()-dataArrangeStartTime);
   dataArrangeStartTime = CkWallTimer();
-  MSA1DINTLIST::Read &nodepartRead = nodepart.syncToRead(nodepartAcc);
+  MSA1DINTLIST::Read nodepartRead = nodepartAcc.syncToRead();
        
   /*
     Set up a msa to store the nodes that belong to a partition
@@ -142,7 +142,7 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
   MSA1DNODELIST part2node(numChunks,numChunks);
   MPI_Bcast_pup(part2node,masterRank,(MPI_Comm)comm_context);
   part2node.enroll(numChunks);
-  MSA1DNODELIST::Accum &part2nodeAcc = part2node.getInitialAccum();
+  MSA1DNODELIST::Accum part2nodeAcc = part2node.getInitialAccum();
 
   FEM_write_part2node(nodepartRead, part2nodeAcc, partdata, (MPI_Comm)comm_context);
 
@@ -150,7 +150,7 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
   /*
     Get the list of elements and nodes that belong to this partition
   */
-  MSA1DNODELIST::Read &rPart2node = part2node.syncToRead(part2nodeAcc);
+  MSA1DNODELIST::Read rPart2node = part2nodeAcc.syncToRead();
   NodeList lnodes = rPart2node.get(masterRank);
   lnodes.uniquify();
 //  IntList lelems = part2elem.get(masterRank);
@@ -166,13 +166,13 @@ int FEM_master_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context
   MSA1DFEMMESH part2mesh(numChunks,numChunks);
   MPI_Bcast_pup(part2mesh,masterRank,(MPI_Comm)comm_context);
   part2mesh.enroll(numChunks);
-  MSA1DFEMMESH::Accum &aPart2mesh = part2mesh.getInitialAccum();
+  MSA1DFEMMESH::Accum aPart2mesh = part2mesh.getInitialAccum();
 
   FEM_write_part2mesh(aPart2mesh,partdata, &data,nodepartRead,numChunks,masterRank,&mypiece);
   /*
     Get your mesh consisting of elements and nodes out of the mesh MSA
   */
-  MSA1DFEMMESH::Read &rPart2mesh = part2mesh.syncToRead(aPart2mesh);
+  MSA1DFEMMESH::Read rPart2mesh = aPart2mesh.syncToRead();
   MeshElem me = rPart2mesh.get(masterRank);
   //printf("[%d] Number of elements in my partitioned mesh %d number of nodes %d \n",masterRank,me.m->nElems(),me.m->node.size());
        
@@ -257,8 +257,8 @@ int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context)
   /*
     call parmetis and get the resuts back from it
   */
-  MSA1DINT::Read &rPtr = data.arr1.syncToRead(data.arr1.getInitialWrite());
-  MSA1DINT::Read &rInd = data.arr2.syncToRead(data.arr1.getInitialWrite());
+  MSA1DINT::Read rPtr = data.arr1.getInitialWrite().syncToRead();
+  MSA1DINT::Read rInd = data.arr1.getInitialWrite().syncToRead();
   struct partconndata *partdata = FEM_call_parmetis(data.nelem, rPtr, rInd, comm_context);
        
   /*
@@ -267,7 +267,7 @@ int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context)
   MSA1DINTLIST nodepart;
   MPI_Bcast_pup(nodepart,masterRank,(MPI_Comm)comm_context);
   nodepart.enroll(numChunks);
-  MSA1DINTLIST::Accum &nodepartAcc = nodepart.getInitialAccum();
+  MSA1DINTLIST::Accum nodepartAcc = nodepart.getInitialAccum();
        
   FEM_write_nodepart(nodepartAcc,partdata,(MPI_Comm)comm_context);
        
@@ -278,8 +278,8 @@ int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context)
   MSA1DNODELIST part2node;
   MPI_Bcast_pup(part2node,masterRank,(MPI_Comm)comm_context);
   part2node.enroll(numChunks);
-  MSA1DNODELIST::Accum &part2nodeAcc = part2node.getInitialAccum();
-  MSA1DINTLIST::Read &nodepartRead = nodepart.syncToRead(nodepartAcc);
+  MSA1DNODELIST::Accum part2nodeAcc = part2node.getInitialAccum();
+  MSA1DINTLIST::Read nodepartRead = nodepartAcc.syncToRead();
 
 
   FEM_write_part2node(nodepartRead, part2nodeAcc, partdata, (MPI_Comm)comm_context);
@@ -287,7 +287,7 @@ int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context)
   /*
     Get the list of elements and nodes that belong to this partition
   */
-  MSA1DNODELIST::Read &part2nodeRead = part2node.syncToRead(part2nodeAcc);
+  MSA1DNODELIST::Read part2nodeRead = part2nodeAcc.syncToRead();
   NodeList lnodes = part2nodeRead.get(myRank);
   lnodes.uniquify();
 //  IntList lelems = part2elem.get(myRank);
@@ -298,13 +298,13 @@ int FEM_slave_parallel_part(int fem_mesh,int masterRank,FEM_Comm_t comm_context)
   MSA1DFEMMESH part2mesh;
   MPI_Bcast_pup(part2mesh,masterRank,(MPI_Comm)comm_context);
   part2mesh.enroll(numChunks);
-  MSA1DFEMMESH::Accum &aPart2mesh = part2mesh.getInitialAccum();
+  MSA1DFEMMESH::Accum aPart2mesh = part2mesh.getInitialAccum();
   FEM_write_part2mesh(aPart2mesh, partdata, &data, nodepartRead,numChunks, myRank, &mypiece);
        
   /*
     Get your mesh consisting of elements and nodes out of the mesh MSA
   */
-  MSA1DFEMMESH::Read &rPart2mesh = part2mesh.syncToRead(aPart2mesh);
+  MSA1DFEMMESH::Read rPart2mesh = aPart2mesh.syncToRead();
   MeshElem me = rPart2mesh.get(myRank);
   //printf("[%d] Number of elements in my partitioned mesh %d number of nodes %d \n",myRank,me.m->nElems(),me.m->node.size());
        
@@ -440,7 +440,7 @@ void FEM_write_nodepart(MSA1DINTLIST::Accum &nodepart,struct partconndata *data,
     int start=data->eptr[i];
     int end = data->eptr[i+1];
     for(int j=start;j<end;j++){
-      nodepart.accumulate(data->eind[j],data->part[i]);
+       nodepart(data->eind[j]) += data->part[i];
        DEBUG(printf(" write_nodepart %d %d \n",data->eind[j],data->part[i]));
     }
   }
@@ -481,7 +481,7 @@ void FEM_write_part2node(MSA1DINTLIST::Read &nodepart,
 
     for(int j=0;j<t.vec->size();j++){
       UniqElemList <NodeElem> en(n);
-      part2node.accumulate((*t.vec)[j],en);
+      part2node((*t.vec)[j]) += en;
     }
   }
   DEBUG(printf("done write_part2node\n"));
@@ -493,7 +493,7 @@ void FEM_write_part2node(MSA1DINTLIST::Read &nodepart,
 void FEM_write_part2elem(MSA1DINTLIST::Accum &part2elem,struct partconndata *data,MPI_Comm comm_context)
 {
   for(int i=0;i<data->nelem;i++){
-    part2elem.accumulate(data->part[i],data->startindex+i);
+      part2elem(data->part[i]) += data->startindex+i;
   }
 }
 
@@ -837,7 +837,7 @@ void makeGhost(FEM_Mesh *m,
 
 
   //   distTab->table.sync((numChunks == 1));
-  MsaHashtable::Add &aDistTab = distTab->getInitialAdd();
+  MsaHashtable::Add aDistTab = distTab->getInitialAdd();
 
   DEBUG(printf("Chunk %d Mesh: *********************************** \n",myChunk));
   //DEBUG(m->print(0));
@@ -940,8 +940,7 @@ void makeGhost(FEM_Mesh *m,
       }
     }
   }
-  MsaHashtable::Read &rDistTab = distTab->syncToRead(aDistTab);
-
+  MsaHashtable::Read rDistTab = aDistTab.syncToRead();
 
   //debug - print the whole table
   /*   printf("Ghosts chunk %d \n",myChunk);*/
@@ -961,7 +960,7 @@ void makeGhost(FEM_Mesh *m,
   ghostmeshes->enroll(numChunks);
   DEBUG(printf("[%d] id %d says ghostmeshes enroll done \n",CkMyPe(),myChunk));
 
-  MSA1DFEMMESH::Accum &aGhostMeshes = ghostmeshes->getInitialAccum();
+  MSA1DFEMMESH::Accum aGhostMeshes = ghostmeshes->getInitialAccum();
 
   DEBUG(printf("[%d] id %d says ghostmeshes sync done \n",CkMyPe(),myChunk));
   /*
@@ -1061,7 +1060,7 @@ void makeGhost(FEM_Mesh *m,
 
   DEBUG(printf("[%d] finished creating ghost mesh \n",myChunk));
 
-  MSA1DFEMMESH::Read& rGhostMeshes = ghostmeshes->syncToRead(aGhostMeshes);
+  MSA1DFEMMESH::Read rGhostMeshes = aGhostMeshes.syncToRead();
 
   /*
     Go through the ghost nodes and check for nodes that dont exist in the hashtable
index ba01e5bf76f46111d577af9f866ef851bd5e6ec4..c36e7fddec27690f3f40889885426493069a5bce 100644 (file)
@@ -6,6 +6,10 @@
 #include <algorithm>
 #include "msa-DistPageMgr.h"
 
+namespace MSA {
+
+static const int DEFAULT_SYNC_SINGLE = 0;
+static const bool MSA_CLEAR_ALL = true;
 
 struct MSA_InvalidHandle { };
 
@@ -19,23 +23,341 @@ public:
     inline const ENTRY& operator= (const ENTRY& rhs) { e = rhs; return rhs; }
 };
 
-template <typename ENTRY, class ENTRY_OPS_CLASS>
+template <class MSA>
 class Accumulable
 {
+    typedef typename MSA::T ENTRY;
     ENTRY &e;
     
 public:
     Accumulable(ENTRY &e_) : e(e_) {}
     template<typename T>
     void operator+=(const T &rhs_)
-        { ENTRY_OPS_CLASS::accumulate(e, rhs_); }
+    { MSA::OPS::accumulate(e, rhs_); }
     template<typename T>
     void accumulate(const T& rhs)
         {
-            ENTRY_OPS_CLASS::accumulate(e, rhs);
+            MSA::OPS::accumulate(e, rhs);
         }
 };
 
+template<class MSA> class MSARead;
+template<class MSA> class MSAWrite;
+template<class MSA> class MSAAccum;
+
+template<class MSA>
+class MSAHandle
+{
+protected:
+    MSA *msa;
+    bool valid;
+
+    void inline checkInvalidate()
+    {
+        if (!valid)
+            throw MSA_InvalidHandle();
+        valid = false;
+    }
+
+    MSAHandle(MSA *msa_)
+        : msa(msa_), valid(true)
+    { }
+    inline void checkValid()
+    {
+        if (!valid)
+            throw MSA_InvalidHandle();
+    }
+
+public:
+    inline void syncRelease()
+    {
+        checkInvalidate();
+        if (msa->active)
+            msa->cache->SyncRelease();
+        else
+            CmiAbort("sync from an inactive thread!\n");
+        msa->active = false;
+    }
+
+    inline void syncDone()
+    {
+        checkInvalidate();
+        msa->sync();
+    }
+
+    inline MSARead<MSA> syncToRead()
+    {
+        checkInvalidate();
+        msa->sync();
+        return MSARead<MSA>(msa);
+    }
+
+    inline MSAWrite<MSA> syncToWrite()
+    {
+        checkInvalidate();
+        msa->sync();
+        return MSAWrite<MSA>(msa);
+    }
+
+    inline MSAWrite<MSA> syncToReWrite()
+    {
+        checkInvalidate();
+        msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
+        return MSAWrite<MSA>(msa);
+    }
+
+    inline MSAAccum<MSA> syncToAccum()
+    {
+        checkInvalidate();
+        msa->sync();
+        return MSAAccum<MSA>(msa);
+    }
+
+    inline MSAAccum<MSA> syncToEAccum()
+    {
+        checkInvalidate();
+        msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
+        return MSAAccum<MSA>(msa);
+    }
+
+    void pup(PUP::er &p)
+    {
+        p|valid;
+        if (valid) {
+            if (p.isUnpacking())
+                msa = new MSA;
+            p|(*msa);
+        }
+        else if (p.isUnpacking())
+            msa = NULL;
+    }
+
+    inline int length() { return msa->length(); }
+
+    MSAHandle() : msa(NULL), valid(false) {}
+};
+
+template <class MSA>
+class MSARead : public MSAHandle<MSA>
+{
+protected:
+    using MSAHandle<MSA>::checkValid;
+    using MSAHandle<MSA>::checkInvalidate;
+    using MSAHandle<MSA>::msa;
+
+    typedef typename MSA::T ENTRY;
+
+public:
+    MSARead(MSA *msa_)
+        :  MSAHandle<MSA>(msa_) { }
+    MSARead() {}
+
+    // 1D Array access
+    inline const ENTRY& get(int x)
+    {
+        checkValid();
+        return msa->get(x);
+    }
+    inline const ENTRY& operator()(int x) { return get(x); }
+    inline const ENTRY& get2(int x)
+    {
+        checkValid();
+        return msa->get2(x);
+    }
+
+    // 2D Array access
+    inline const ENTRY& get(int x, int y)
+    {
+        checkValid();
+        return msa->get(x, y);
+    }
+    inline const ENTRY& operator()(int x, int y) { return get(x, y); }
+    inline const ENTRY& get2(int x, int y)
+    {
+        checkValid();
+        return msa->get2(x, y);
+    }
+
+    // 3D Array Access
+    inline const ENTRY& get(int x, int y, int z)
+    {
+        checkValid();
+        return msa->get(x, y, z);
+    }
+    inline const ENTRY& operator()(int x, int y, int z) { return get(x, y, z); }
+    inline const ENTRY& get2(int x, int y, int z)
+    {
+        checkValid();
+        return msa->get2(x, y, z);
+    }
+
+    // Reads the specified range into the provided buffer in row-major order
+    void read(ENTRY *buf, int x1, int y1, int z1, int x2, int y2, int z2)
+    {
+        checkValid();
+
+        CkAssert(x1 <= x2);
+        CkAssert(y1 <= y2);
+        CkAssert(z1 <= z2);
+
+        CkAssert(x1 >= msa->xa);
+        CkAssert(y1 >= msa->ya);
+        CkAssert(z1 >= msa->za);
+
+        CkAssert(x2 <= msa->xb);
+        CkAssert(y2 <= msa->yb);
+        CkAssert(z2 <= msa->zb);
+
+        int i = 0;
+
+        for (int ix = x1; ix <= x2; ++ix)
+            for (int iy = y1; iy <= y2; ++iy)
+                for (int iz = z1; iz <= z2; ++iz)
+                    buf[i++] = msa->get(ix, iy, iz);
+    }
+};
+
+template <class MSA>
+class MSAWrite : public MSAHandle<MSA>
+{
+protected:
+    using MSAHandle<MSA>::checkValid;
+    using MSAHandle<MSA>::checkInvalidate;
+    using MSAHandle<MSA>::msa;
+
+    typedef typename MSA::T ENTRY;
+
+public:
+    MSAWrite(MSA *msa_)
+        : MSAHandle<MSA>(msa_) { }
+    MSAWrite() {}
+
+    // 1D Array access
+    inline Writable<ENTRY> set(int x)
+    {
+        checkValid();
+        return Writable<ENTRY>(msa->set(x));
+    }
+    inline Writable<ENTRY> operator()(int x)
+    {
+        return set(x);
+    }
+
+    // 2D Array access
+    inline Writable<ENTRY> set(int x, int y)
+    {
+        checkValid();
+        return Writable<ENTRY>(msa->set(x,y));
+    }
+    inline Writable<ENTRY> operator()(int x, int y)
+    {
+        return set(x,y);
+    }
+
+    // 3D Array access
+    inline Writable<ENTRY> set(int x, int y, int z)
+    {
+        checkValid();
+        return Writable<ENTRY>(msa->set(x,y,z));
+    }
+    inline Writable<ENTRY> operator()(int x, int y, int z)
+    {
+        return set(x,y,z);
+    }
+
+    void write(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
+    {
+        checkValid();
+
+        CkAssert(x1 <= x2);
+        CkAssert(y1 <= y2);
+        CkAssert(z1 <= z2);
+
+        CkAssert(x1 >= msa->xa);
+        CkAssert(y1 >= msa->ya);
+        CkAssert(z1 >= msa->za);
+
+        CkAssert(x2 <= msa->xb);
+        CkAssert(y2 <= msa->yb);
+        CkAssert(z2 <= msa->zb);
+
+        int i = 0;
+
+        for (int ix = x1; ix <= x2; ++ix)
+            for (int iy = y1; iy <= y2; ++iy)
+                for (int iz = z1; iz <= z2; ++iz)
+                    {
+                        msa->set(ix, iy, iz) = buf[i++];
+                    }
+    }
+};
+
+template<class MSA>
+class MSAAccum : public MSAHandle<MSA>
+{
+protected:
+    using MSAHandle<MSA>::checkValid;
+    using MSAHandle<MSA>::checkInvalidate;
+    using MSAHandle<MSA>::msa;
+
+    typedef typename MSA::T ENTRY;
+
+public:
+    MSAAccum(MSA *msa_)
+        : MSAHandle<MSA>(msa_) { }
+    MSAAccum() {}
+
+    // 1D Array Access
+    inline Accumulable<MSA> accumulate(int x)
+    {
+        checkValid();
+        return Accumulable<MSA>(msa->accumulate(x));
+    }
+    inline Accumulable<MSA> operator() (int x)
+    { return accumulate(x); }
+
+    // 2D Array Access
+    inline Accumulable<MSA> accumulate(int x, int y)
+    {
+        checkValid();
+        return Accumulable<MSA>(msa->accumulate(x,y));
+    }
+    inline Accumulable<MSA> operator() (int x, int y)
+    { return accumulate(x,y); }
+
+    // 3D Array Access
+    inline Accumulable<MSA> accumulate(int x, int y, int z)
+    {
+        checkValid();
+        return Accumulable<MSA>(msa->accumulate(x,y,z));
+    }
+    inline Accumulable<MSA> operator() (int x, int y, int z)
+    { return accumulate(x,y,z); }
+
+    void accumulate(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
+    {
+        checkValid();
+        CkAssert(x1 <= x2);
+        CkAssert(y1 <= y2);
+        CkAssert(z1 <= z2);
+
+        CkAssert(x1 >= msa->xa);
+        CkAssert(y1 >= msa->ya);
+        CkAssert(z1 >= msa->za);
+
+        CkAssert(x2 <= msa->xb);
+        CkAssert(y2 <= msa->yb);
+        CkAssert(z2 <= msa->zb);
+
+        int i = 0;
+
+        for (int ix = x1; ix <= x2; ++ix)
+            for (int iy = y1; iy <= y2; ++iy)
+                for (int iz = z1; iz <= z2; ++iz)
+                    msa->accumulate(ix, iy, iz, buf[i++]);
+    }
+};
+
 
 /**
    The MSA1D class is a handle to a distributed shared array of items
@@ -65,117 +387,17 @@ public:
     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
     typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
 
-    // Sun's C++ compiler doesn't understand that nested classes are
-    // members for the sake of access to private data. (2008-10-23)
-    class Read; class Write; class Accum;
-    friend class Read; friend class Write; friend class Accum;
-
-       class Handle
-       {
-    public:
-        inline unsigned int length() const { return msa->length(); }
-
-       protected:
-        MSA1D *msa;
-        bool valid;
-
-        friend class MSA1D;
-
-        void inline checkInvalidate(MSA1D *m) 
-        {
-            if (m != msa || !valid)
-                throw MSA_InvalidHandle();
-            valid = false;
-        }
-
-        Handle(MSA1D *msa_) 
-            : msa(msa_), valid(true) 
-        { }
-        Handle() : msa(NULL), valid(false) {}
-        void checkValid()
-        {
-            if (!valid)
-                throw MSA_InvalidHandle();
-        }
-
-    private:
-        // Disallow copy construction
-        Handle(Handle &);
-    };
-
-    class Read : public Handle
-    {
-    protected:
-        friend class MSA1D;
-        Read(MSA1D *msa_)
-            :  Handle(msa_) { }
-        using Handle::checkValid;
-        using Handle::checkInvalidate;
-
-    public:
-        inline const ENTRY& get(unsigned int idx)
-        {
-            checkValid();
-            return Handle::msa->get(idx); 
-        }
-        inline const ENTRY& operator[](unsigned int idx) { return get(idx); }
-        inline const ENTRY& operator()(unsigned int idx) { return get(idx); }
-        inline const ENTRY& get2(unsigned int idx)
-        {
-            checkValid();
-            return Handle::msa->get2(idx);
-        }
-        Read() {}
-    };
-
-    class Write : public Handle
-    {
-    protected:
-        friend class MSA1D;
-        Write(MSA1D *msa_)
-            : Handle(msa_) { }
-
-    public:
-        inline Writable<ENTRY> set(unsigned int idx)
-        {
-            Handle::checkValid();
-            return Writable<ENTRY>(Handle::msa->set(idx));
-        }
-        inline Writable<ENTRY> operator()(unsigned int idx)
-            { return set(idx); }
-    };
-
-    class Accum : public Handle
-    {
-    protected:
-        friend class MSA1D;
-        Accum(MSA1D *msa_)
-            : Handle(msa_) { }
-        using Handle::checkInvalidate;
-    public:
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> accumulate(unsigned int idx)
-        { 
-            Handle::checkValid();
-            return Accumulable<ENTRY, ENTRY_OPS_CLASS>(Handle::msa->accumulate(idx));
-        }
-        inline void accumulate(unsigned int idx, const ENTRY& ent)
-        {
-            Handle::checkValid();
-            Handle::msa->accumulate(idx, ent);
-        }
-
-        void contribute(unsigned int idx, const ENTRY *begin, const ENTRY *end)
-        {
-            Handle::checkValid();
-            for (const ENTRY *e = begin; e != end; ++e, ++idx)
-                {
-                    Handle::msa->accumulate(idx, *e);
-                }
-        }
-
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> operator() (unsigned int idx)
-            { return accumulate(idx); }
-    };
+    typedef ENTRY T;
+    typedef ENTRY_OPS_CLASS OPS;
+    typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
+    typedef MSAHandle<thisMSA> Handle;
+    typedef MSARead<thisMSA> Read;
+    typedef MSAAccum<thisMSA> Accum;
+    typedef MSAWrite<thisMSA> Write;
+    friend class MSAHandle<thisMSA>;
+    friend class MSARead<thisMSA>;
+    friend class MSAWrite<thisMSA>;
+    friend class MSAAccum<thisMSA>;
 
 protected:
     /// Total number of ENTRY's in the whole array.
@@ -352,52 +574,22 @@ public:
         cache->UnlockPages(page1, page2);
     }
 
-    static const int DEFAULT_SYNC_SINGLE = 0;
-
-    inline Read &syncToRead(Handle &m, int single = DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        sync(single);
-        return *(new Read(*this));
-    }
-
-    inline Write &syncToWrite(Handle &m, int single = DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        sync(single);
-        return *(new Write(*this));
-    }
-
-    inline Accum &syncToAccum(Handle &m, int single = DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        sync(single);
-        return *(new Accum(*this));
-    }
-
-    inline Write &getInitialWrite()
+    inline Write getInitialWrite()
     {
         if (initHandleGiven)
             throw MSA_InvalidHandle();
 
-        Write *w = new Write(*this);
-        sync();
         initHandleGiven = true;
-        return *w;
+        return Write(this);
     }
 
-    inline Accum &getInitialAccum()
+    inline Accum getInitialAccum()
     {
         if (initHandleGiven)
             throw MSA_InvalidHandle();
 
-        Accum *a = new Accum(*this);
-        sync();
         initHandleGiven = true;
-        return *a;
+        return Accum(this);
     }
 
   // These are the meat of the MSA API, but they are only accessible
@@ -475,6 +667,18 @@ public:
     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
     typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> super;
 
+    typedef ENTRY T;
+    typedef ENTRY_OPS_CLASS OPS;
+    typedef MSA2D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
+    typedef MSAHandle<thisMSA> Handle;
+    typedef MSARead<thisMSA> Read;
+    typedef MSAAccum<thisMSA> Accum;
+    typedef MSAWrite<thisMSA> Write;
+    friend class MSAHandle<thisMSA>;
+    friend class MSARead<thisMSA>;
+    friend class MSAWrite<thisMSA>;
+    friend class MSAAccum<thisMSA>;
+
 protected:
     unsigned int rows, cols;
 
@@ -486,120 +690,6 @@ public:
        p|rows; p|cols;
     };
 
-       class Handle
-       {
-       protected:
-        MSA2D *msa;
-        bool valid;
-
-        friend class MSA2D;
-
-        inline void checkInvalidate(MSA2D *m)
-        {
-            if (*msa != m || !valid)
-                throw MSA_InvalidHandle();
-            valid = false;
-        }
-
-        Handle(MSA2D *msa_) 
-            : msa(msa_), valid(true) 
-        { }
-        Handle() : msa(NULL), valid(false) {}
-
-        inline void checkValid()
-        {
-            if (!valid)
-                throw MSA_InvalidHandle();
-        }
-    private:
-        // Disallow copy construction
-        Handle(Handle &);
-    };
-
-    class Read : public Handle
-    {
-    private:
-        friend class MSA2D;
-        Read(MSA2D *msa_)
-            :  Handle(msa_) { }
-
-    public: 
-        inline const ENTRY& get(unsigned int row, unsigned int col)
-        {
-            Handle::checkValid();
-            return Handle::msa->get(row, col);
-        }
-        inline const ENTRY& get2(unsigned int row, unsigned int col)
-        {
-            Handle::checkValid();
-            return Handle::msa->get2(row, col);
-        }
-
-        inline const ENTRY& operator() (unsigned int row, unsigned int col)
-            {
-                return get(row,col);
-            }
-
-        Read() { }
-    };
-
-    class Write : public Handle
-    {
-    private:
-        friend class MSA2D;
-        Write(MSA2D *msa_)
-            :  Handle(msa_) { }
-
-    public: 
-        inline Writable<ENTRY> set(unsigned int row, unsigned int col)
-        {
-            Handle::checkValid();
-            return Writable<ENTRY>(Handle::msa->set(row, col));
-        }
-
-        inline Writable<ENTRY> operator()(unsigned int row, unsigned int col)
-            { return set(row, col); }
-    };
-
-    class Accum : public Handle
-    {
-    protected:
-        friend class MSA2D;
-        Accum(MSA2D *msa_)
-            : Handle(msa_) { }
-        using Handle::checkInvalidate;
-    public:
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> accumulate(unsigned int idx)
-        {
-            Handle::checkValid();
-            return Accumulable<ENTRY, ENTRY_OPS_CLASS>(Handle::msa->accumulate(idx));
-        }
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> accumulate(unsigned int x, unsigned int y)
-        {
-            Handle::checkValid();
-            return Accumulable<ENTRY, ENTRY_OPS_CLASS>(Handle::msa->accumulate(Handle::msa->getIndex(x, y)));
-        }
-        inline void accumulate(unsigned int idx, const ENTRY& ent)
-        {
-            Handle::checkValid();
-            Handle::msa->accumulate(idx, ent);
-        }
-
-        void contribute(unsigned int idx, const ENTRY *begin, const ENTRY *end)
-        {
-            Handle::checkValid();
-            for (const ENTRY *e = begin; e != end; ++e, ++idx)
-                {
-                    Handle::msa->accumulate(idx, *e);
-                }
-        }
-
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> operator() (unsigned int idx)
-            { return accumulate(idx); }
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> operator() (unsigned int x, unsigned int y)
-            { return accumulate(x, y); }
-    };
-
     inline MSA2D(unsigned int rows_, unsigned int cols_, unsigned int numwrkrs,
                  unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
         :super(rows_*cols_, numwrkrs, maxBytes)
@@ -672,52 +762,24 @@ public:
         MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::Unlock(index1, index2);
     }
 
-    inline Read& syncToRead(Handle &m, int single = super::DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        super::sync(single);
-        return *(new Read(*this));
-    }
-
-    inline Write& syncToWrite(Handle &m, int single = super::DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        super::sync(single);
-        return *(new Write(*this));
-    }
-
-    inline Accum& syncToAccum(Handle &m, int single = super::DEFAULT_SYNC_SINGLE)
-    {
-        m.checkInvalidate(this);
-        delete &m;
-        super::sync(single);
-        return *(new Accum(*this));
-    }
-
-    inline Write& getInitialWrite()
+    inline Write getInitialWrite()
     {
         if (super::initHandleGiven)
             throw MSA_InvalidHandle();
 
-        Write *w = new Write(*this);
         super::initHandleGiven = true;
-        return *w;
+        return Write(this);
     }
 
-    inline Accum &getInitialAccum()
+    inline Accum getInitialAccum()
     {
         if (super::initHandleGiven)
             throw MSA_InvalidHandle();
 
-        Accum *a = new Accum(*this);
-        sync();
         super::initHandleGiven = true;
-        return *a;
+        return Accum(this);
     }
 
-
 protected:
     inline const ENTRY& get(unsigned int row, unsigned int col)
     {
@@ -737,12 +799,6 @@ protected:
     }
 };
 
-namespace MSA
-{
-    using std::min;
-    using std::max;
-
-
 /**
    The MSA3D class is a handle to a distributed shared array of items
    of data type ENTRY. There are nEntries total numer of ENTRY's, with
@@ -776,253 +832,17 @@ public:
     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
     typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
 
-    // Sun's C++ compiler doesn't understand that nested classes are
-    // members for the sake of access to private data. (2008-10-23)
-    class Read; class Write; class Accum;
-    friend class Read; friend class Write; friend class Accum;
-
-       class Handle
-       {
-       protected:
-        MSA3D *msa;
-        bool valid;
-
-        friend class MSA3D;
-
-        void inline checkInvalidate() 
-        {
-            if (!valid)
-                throw MSA_InvalidHandle();
-            valid = false;
-        }
-
-        Handle(MSA3D *msa_) 
-            : msa(msa_), valid(true) 
-        { }
-        void checkValid()
-        {
-            if (!valid)
-                throw MSA_InvalidHandle();
-        }
-        
-    public:
-        inline void syncRelease()
-            {
-                checkInvalidate();
-                if (msa->active)
-                    msa->cache->SyncRelease();
-                else
-                    CmiAbort("sync from an inactive thread!\n");
-                msa->active = false;
-            }
-
-        inline void syncDone()
-            {
-                checkInvalidate();
-                msa->sync(DEFAULT_SYNC_SINGLE);
-            }
-
-        inline Read syncToRead()
-            {
-                checkInvalidate();
-                msa->sync(DEFAULT_SYNC_SINGLE);
-                return Read(msa);
-            }
-
-        inline Write syncToWrite()
-            {
-                checkInvalidate();
-                msa->sync(DEFAULT_SYNC_SINGLE);
-                return Write(msa);
-            }
-
-        inline Write syncToReWrite()
-            {
-                checkInvalidate();
-                msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
-                return Write(msa);
-            }
-
-        inline Accum syncToAccum()
-            {
-                checkInvalidate();
-                msa->sync(DEFAULT_SYNC_SINGLE);
-                return Accum(msa);
-            }
-
-        inline Accum syncToEAccum()
-        {
-            checkInvalidate();
-            msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
-            return Accum(msa);
-        }
-
-        void pup(PUP::er &p)
-            {
-                p|valid;
-                if (valid)
-                {
-                    if (p.isUnpacking())
-                        msa = new MSA3D;
-                    p|(*msa);
-                }
-                else if (p.isUnpacking())
-                    msa = NULL;
-            }
-
-        Handle() : msa(NULL), valid(false) {}
-    };
-
-    class Read : public Handle
-    {
-    protected:
-        friend class MSA3D;
-        Read(MSA3D *msa_)
-            :  Handle(msa_) { }
-        using Handle::checkValid;
-        using Handle::checkInvalidate;
-
-    public:
-        Read() {}
-
-        inline const ENTRY& get(unsigned x, unsigned y, unsigned z)
-        {
-            checkValid();
-            return Handle::msa->get(x, y, z); 
-        }
-        inline const ENTRY& operator()(unsigned x, unsigned y, unsigned z) { return get(x, y, z); }
-        inline const ENTRY& get2(unsigned x, unsigned y, unsigned z)
-        {
-            checkValid();
-            return Handle::msa->get2(x, y, z);
-        }
-
-        // Reads the specified range into the provided buffer in row-major order
-        void read(ENTRY *buf, unsigned x1, unsigned y1, unsigned z1, unsigned x2, unsigned y2, unsigned z2)
-        {
-            checkValid();
-
-            CkAssert(x1 <= x2);
-            CkAssert(y1 <= y2);
-            CkAssert(z1 <= z2);
-
-            CkAssert(x1 >= Handle::msa->xa);
-            CkAssert(y1 >= Handle::msa->ya);
-            CkAssert(z1 >= Handle::msa->za);
-
-            CkAssert(x2 <= Handle::msa->xb);
-            CkAssert(y2 <= Handle::msa->yb);
-            CkAssert(z2 <= Handle::msa->zb);
-
-            unsigned i = 0;
-
-            for (unsigned ix = x1; ix <= x2; ++ix)
-                for (unsigned iy = y1; iy <= y2; ++iy)
-                    for (unsigned iz = z1; iz <= z2; ++iz)
-                        buf[i++] = Handle::msa->get(ix, iy, iz);
-        }
-    };
-
-    class Write : public Handle
-    {
-    protected:
-        friend class MSA3D;
-        Write(MSA3D *msa_)
-            : Handle(msa_) { }
-
-    public:
-        Write() {}
-
-        inline Writable<ENTRY> set(unsigned x, unsigned y, unsigned z)
-        {
-            Handle::checkValid();
-            return Writable<ENTRY>(Handle::msa->set(x,y,z));
-        }
-        inline Writable<ENTRY> operator()(unsigned x, unsigned y, unsigned z)
-        {
-            return set(x,y,z);
-        }
-
-        void write(unsigned x1, unsigned y1, unsigned z1, unsigned x2, unsigned y2, unsigned z2, const ENTRY *buf)
-        {
-            Handle::checkValid();
-
-            CkAssert(x1 <= x2);
-            CkAssert(y1 <= y2);
-            CkAssert(z1 <= z2);
-
-            CkAssert(x1 >= Handle::msa->xa);
-            CkAssert(y1 >= Handle::msa->ya);
-            CkAssert(z1 >= Handle::msa->za);
-
-            CkAssert(x2 <= Handle::msa->xb);
-            CkAssert(y2 <= Handle::msa->yb);
-            CkAssert(z2 <= Handle::msa->zb);
-
-            unsigned i = 0;
-
-            for (unsigned ix = x1; ix <= x2; ++ix)
-                for (unsigned iy = y1; iy <= y2; ++iy)
-                    for (unsigned iz = z1; iz <= z2; ++iz)
-                    {
-                        if (isnan(buf[i]))
-                            CmiAbort("Tried to write a NaN!");
-                        Handle::msa->set(ix, iy, iz) = buf[i++];
-                    }
-        }
-#if 0
-    private:
-        Write(Write &);
-#endif
-    };
-
-    class Accum : public Handle
-    {
-    protected:
-        friend class MSA3D;
-        Accum(MSA3D *msa_)
-            : Handle(msa_) { }
-        using Handle::checkInvalidate;
-    public:
-        Accum() {}
-
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> accumulate(unsigned int x, unsigned int y, unsigned int z)
-        {
-            Handle::checkValid();
-            return Accumulable<ENTRY, ENTRY_OPS_CLASS>(Handle::msa->accumulate(x,y,z));
-        }
-        inline void accumulate(unsigned int x, unsigned int y, unsigned int z, const ENTRY& ent)
-        {
-            Handle::checkValid();
-            Handle::msa->accumulate(x,y,z, ent);
-        }
-
-        void accumulate(unsigned x1, unsigned y1, unsigned z1, unsigned x2, unsigned y2, unsigned z2, const ENTRY *buf)
-        {
-            Handle::checkValid();
-            CkAssert(x1 <= x2);
-            CkAssert(y1 <= y2);
-            CkAssert(z1 <= z2);
-
-            CkAssert(x1 >= Handle::msa->xa);
-            CkAssert(y1 >= Handle::msa->ya);
-            CkAssert(z1 >= Handle::msa->za);
-
-            CkAssert(x2 <= Handle::msa->xb);
-            CkAssert(y2 <= Handle::msa->yb);
-            CkAssert(z2 <= Handle::msa->zb);
-
-            unsigned i = 0;
-
-            for (unsigned ix = x1; ix <= x2; ++ix)
-                for (unsigned iy = y1; iy <= y2; ++iy)
-                    for (unsigned iz = z1; iz <= z2; ++iz)
-                        Handle::msa->accumulate(ix, iy, iz, buf[i++]);
-        }
-
-        inline Accumulable<ENTRY, ENTRY_OPS_CLASS> operator() (unsigned int x, unsigned int y, unsigned int z)
-            { return accumulate(x,y,z); }
-    };
+    typedef ENTRY T;
+    typedef ENTRY_OPS_CLASS OPS;
+    typedef MSA3D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
+    typedef MSAHandle<thisMSA> Handle;
+    typedef MSARead<thisMSA> Read;
+    typedef MSAAccum<thisMSA> Accum;
+    typedef MSAWrite<thisMSA> Write;
+    friend class MSAHandle<thisMSA>;
+    friend class MSARead<thisMSA>;
+    friend class MSAWrite<thisMSA>;
+    friend class MSAAccum<thisMSA>;
 
 protected:
     /// Total number of ENTRY's in the whole array.
@@ -1236,16 +1056,11 @@ public:
         cache->UnlockPages(page1, page2);
     }
 
-    static const int DEFAULT_SYNC_SINGLE = 0;
-    static const bool MSA_CLEAR_ALL = true;
-
     inline Write getInitialWrite()
     {
         if (initHandleGiven)
             CmiAbort("Trying to get an MSA's initial handle a second time");
 
-        //Write *w = new Write(*this);
-        //sync();
         initHandleGiven = true;
         return Write(this);
     }
@@ -1255,8 +1070,6 @@ public:
         if (initHandleGiven)
             CmiAbort("Trying to get an MSA's initial handle a second time");
 
-        //Accum *a = new Accum(*this);
-        //sync();
         initHandleGiven = true;
         return Accum(this);
     }