// ************************************************************** // * * // * Spheres -- GridRout.cpp * // * * // * (C) Christian Scheideler, 2003 * // * * // ************************************************************** // GridRout.cpp routes packets acc. to problem 12 in an arbitrary nxn-grid // Special definitions and operations provided by Spheres.h: // // - Sphere: class that enables non-blocking method invocations (NMI). // To ensure the correct execution of NMIs, every method in a class // derived from Sphere that is to be called by NMI has to have the form // // void MethodName(usertype *plist) // // where plist is a pointer to any kind of usertype. // // - void Send(SpherePtr, SphereObj::Method, ParList): // This requests to call the method SphereObj::Method in the user object // referenced by SpherePtr using the parameter list referenced by ParList. // // - void Simulate(Time): // This runs a simulation for Time many rounds. // The Spheres.h class provides an environment for the simulation of // concurrent data structures, where concurrent executions are done at the // level of method invocations (i.e. each method invocation completes before // another method is invoked). To avoid inconsistencies in the data structure, // some general rules have to be obeyed: // // - A method may not have any side-effects other than modifying the // data inside the object. // // - A method must be total, meaning that it is well-defined for // EVERY legal state of the object. #include #include #include "Spheres.h" // parameter list for Node::Sync method class SPList { public: int ID; // origin of sync message int round; // round number of sync int dest; // destination of packet piggybacked by sync message SPList *next; // pointer to next object (for buffering) SPList(int i, int r, int d) { ID = i; round = r; dest = d; next = NULL; } }; class Node: public Sphere { private: int ID; // own ID int degree; // own degree int length; // side length of grid int round; // current round SPList **current; // neighbor syncs for current round SPList **next; // neighbor syncs for next round Node **neighbor; // pointers to neighbors int *neighID; // IDs of neighbors SPList **buffer; // buffer for packets (works like stack) public: Node(int u, int l) { ID = u; length = l; } void Connect(int d, Node** np, int *IDs) { int v; degree = d; neighbor = np; neighID = IDs; // initialize sync variables and buffers round = 1; current = new (SPList *)[degree]; next = new (SPList *)[degree]; buffer = new (SPList *)[degree]; for (v=0; vdest) delete p; // packet reached destination else { x = (ID % length) - (p->dest % length); // difference in x-koord if (x<0) n=ID+1; // move right if (x>0) n=ID-1; // move left if (x==0) { if (ID > p->dest) n=ID-length; // move down else n=ID+length; // move up } for (v=0; vnext = buffer[v]; // move packet to buffer buffer[v] = p; } } } void printXY(int v) { cout << "(" << v%length << "," << (v-(v%length))/length << ")"; } void Sync(SPList *p) { int v, complete; SPList *lp; if (p->dest>=0) { printXY(ID); cout << ": received in round " << p->round << " from "; printXY(p->ID); cout << " packet to destination "; printXY(p->dest); cout << "\n"; } // locate neighbor in list v=0; while (neighID[v] != p->ID) v++; // sync if (p->round == round) { current[v] = p; complete = 1; for (v=0; vdest<0) delete current[v]; // only sync packet else XYRoute(current[v]); } // reset sync indicators for (v=0; vnext; // update ID and round and reset next pointer lp->ID = ID; lp->round = round; lp->next = NULL; } Send(neighbor[v], Node::Sync, lp); } } } else next[v] = p; } void Start(void *p) { int d, v; SPList *lp; // put initial packets in buffers d = ID+length-2*(ID % length)-1; // (n-x-1,y) lp = new SPList(ID, round, d); XYRoute(lp); d = length*length-ID-1; // (n-x-1, n-y-1) lp = new SPList(ID, round, d); XYRoute(lp); // send syncs (plus packets) to all neighbors for (v=0; vnext; lp->next = NULL; } Send(neighbor[v], Node::Sync, lp); } } }; void GridSync() { int n; // side length of grid Node **List; // list of all nodes int x,y; // node (x,y) int left, right, up, down; // all possible edges int deg; // degree Node **NL; // neighbor pointers int *NID; // neighbor IDs int v; // input n cout << "Side length of grid: "; cin >> n; // generate set of node objects List = new (Node *)[n*n]; for (v=0; vConnect(deg, NL, NID); } } // generate requests to call Node::Start in every node of the list for (v=0; v> i; // just to see the output }