// ************************************************************** // * * // * Spheres -- DHT.cpp * // * * // * (C) Christian Scheideler, 2003 * // * * // ************************************************************** // DHT.cpp demonstrates consistent hashing in a 10-node ring // 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::Search method class SPList { public: float source; // source of message float key; // search key of message SPList(float s, float k) { source = s; key = k; } }; class Node: public Sphere { private: float ID; // own ID Node **neighbor; // pointers to neighbors float *neighID; // IDs of neighbors public: Node(float u) { ID = u; } void Connect(Node** np, float *IDs) { neighbor = np; neighID = IDs; } void Search(SPList *p) { // reached destination? if ((ID>=p->key && (neighID[0]key || neighID[0]>ID)) || (IDkey && (neighID[0]>ID && neighID[0]key))) { cout << ID << ": received search request and reply back\n"; p->key = p->source; // back to source p->source = ID; Send(this, Node::Reply, p); } else { cout << ID << ": received search request\n"; Send(neighbor[1], Node::Search, p); } } void Reply(SPList *p) { if (ID==p->key) // reached destination { cout << ID << ": received reply from " << p->source << "\n"; delete p; } else { cout << ID << ": received reply\n"; Send(neighbor[1], Node::Reply, p); } } }; float Hash(int i, int n) { return i/(1.0*n); } void Cycle() { int n; // size of cycle Node **List; // list of all nodes Node **NL; // neighbor pointers float *NID; // neighbor IDs int v; float k; SPList *p; // search request // input n cout << "Size of cycle: "; cin >> n; // generate set of node objects List = new (Node *)[n]; for (v=0; v0) // predecessor { NL[0] = List[v-1]; NID[0] = Hash(v-1,n); } else { NL[0] = List[n-1]; NID[0] = Hash(n-1,n); } if (vConnect(NL, NID); } // generate a search request cout << "Source of search request: "; cin >> v; cout << "Search key: "; cin >> k; p = new SPList(Hash(v,n),k); Send(List[v], Node::Search, p); // run the simulation Simulate(2*n); } void main() { int i; Cycle(); cin >> i; // just to see the output }