defines virtual destructor to fix gcc4 warnings like: warning: ‘class CharismaInPort...
[charm.git] / src / ck-core / charisma.h
1 #ifndef CHARISMA_H
2 #define CHARISMA_H
3
4 #include "charisma.decl.h"
5
6 class Name
7 {
8   private:
9     char *curname;
10     int curbuflen;
11     int curlen;
12   public:
13     Name(void)
14     {
15       curbuflen = 100;
16       curname = new char[curbuflen];
17       curname[0] = '\0';
18       curlen = 0;
19     }
20     void add(const char *n)
21     {
22       int len = strlen(n);
23       if((curlen+len+2) > curbuflen) {
24         char *t = new char[curlen+len+2];
25         strcpy(t, curname);
26         delete[] curname;
27         curname = t;
28         curbuflen = curlen+len+2;
29       }
30       if(curlen!=0) {
31         strcat(curname, ".");
32         curlen++;
33       }
34       strcat(curname, n);
35       curlen += len;
36     }
37     void remove(const char *n)
38     {
39       int len = strlen(n);
40       curlen = curlen-len;
41       curname[curlen] = '\0';
42       if(curlen!=0) {
43         curname[--curlen] = '\0';
44       }
45     }
46     inline operator char *() const { return curname; }
47     ~Name()
48     {
49       delete[] curname;
50     }
51 };
52
53 class Component
54 {
55   private:
56     char *name;
57     char *type;
58     int idx; // unique index for every component given for partitioning
59     int pe; // mapping resulting from partitioning
60     int nout; // number of output ports
61     int nin; // number of input ports
62     int ncout; // number of connected output ports
63     int ncin; // number of connected input ports
64   public:
65     Component(const char *n, const char *t)
66     {
67       name = new char[strlen(n)+1];
68       strcpy(name,n);
69       type = new char[strlen(t)+1];
70       strcpy(type,t);
71       ncout = ncin = nout = nin = 0;
72       idx = pe = (-1); // something invalid
73     }
74     ~Component()
75     {
76       delete[] type;
77     }
78     char *getName(void) { return name; }
79     char *getType(void) { return type; }
80     void setIdx(int _idx) { idx = _idx; }
81     int getIdx(void) { return idx; }
82     void setPe(int _pe) { pe = _pe; }
83     int getPe(void) { return pe; }
84     void addOutPort(void) { nout++; }
85     void addInPort(void) { nin++; }
86     void connectOutPort(void) { ncout++; }
87     void connectInPort(void) { ncin++; }
88     int getNumPorts(void) { return nout + nin; }
89     int getNumConnectedPorts(void) { return ncout + ncin; }
90 };
91
92 #define CHARISMA_IN 1
93 #define CHARISMA_OUT 2
94
95 class Port
96 {
97   private:
98     int inout; // IN/OUT
99     char *name;
100     Component *comp;
101     char *type;
102     Port *peer;
103   public:
104     Port(const char *n, Component *c, const char *t, int io)
105     {
106       name = new char[strlen(n)+1];
107       strcpy(name,n);
108       comp = c;
109       type = new char[strlen(t)+1];
110       strcpy(type,t);
111       inout = io;
112       peer = 0;
113     }
114     void setPeer(Port *p)
115     {
116       peer = p;
117     }
118     ~Port()
119     {
120       delete[] name;
121       delete[] type;
122     }
123     char *getName(void) { return name; }
124     char *getType(void) { return type; }
125     Port *getPeer(void) { return peer; }
126     Component *getComp(void) { return comp; }
127 };
128
129 extern "C"
130 void METIS_PartGraphRecursive(int* n, int* xadj, int* adjncy, int* vwght,
131     int* adjwgt, int* wgtflag, int* numflag, int* nparts, int* options,
132     int* edgecut, int* part);
133
134 class CharismaGraph
135 {
136   private:
137     CkHashtableTslow<const char *, Port *> ports;
138     CkHashtableTslow<const char *, Component *> comps;
139     Name *curname;
140   public:
141     CharismaGraph(void)
142     {
143       curname = new Name;
144     }
145     // indicate that all the following registrations belong to component
146     // named name.
147     void start(const char *name, const char *type)
148     {
149       curname->add(name);
150       CkPrintf("starting registration for %s\n", (char *) curname);
151       Component *curcomp = new Component((const char *)curname, type);
152       comps.put((const char *)curname) = curcomp;
153     }
154     // end registrations for component called name
155     void end(const char *name)
156     {
157       CkPrintf("ending registration for %s\n", (char *) curname);
158       curname->remove(name);
159     }
160     // register an output port
161     void registerOutPort(const char *name, const char *type)
162     {
163       Component *curcomp = comps.get((const char *) curname);
164       curcomp->addOutPort();
165       curname->add(name);
166       CkPrintf("registering outport %s\n", (char *) curname);
167       ports.put((const char *)curname) = new Port((const char *)curname,
168           curcomp, type, CHARISMA_OUT);
169       curname->remove(name);
170     }
171     // register an input port
172     void registerInPort(const char *name, const char *type)
173     {
174       Component *curcomp = comps.get((const char *) curname);
175       curcomp->addInPort();
176       curname->add(name);
177       CkPrintf("registering outport %s\n", (char *) curname);
178       ports.put((const char *)curname) = new Port((const char *) curname,
179           curcomp, type, CHARISMA_IN);
180       curname->remove(name);
181     }
182     // connect an output port name1 to input port name2
183     void connect(const char *name1, const char *name2)
184     {
185       curname->add(name1);
186       char *oname = new char[strlen((char*)curname)+1];
187       strcpy(oname, (char*) curname);
188       curname->remove(name1);
189       curname->add(name2);
190       char *iname = new char[strlen((char*)curname)+1];
191       strcpy(iname, (char*) curname);
192       curname->remove(name2);
193       Port *oport = ports.get(oname);
194       Port *iport = ports.get(iname);
195       if(strcmp(oport->getType(), iport->getType())!=0)
196         CkAbort("Types of connected ports do not match !!!\n");
197       oport->setPeer(iport);
198       iport->setPeer(oport);
199       oport->getComp()->connectOutPort();
200       iport->getComp()->connectInPort();
201       delete[] oname;
202       delete[] iname;
203     }
204     void Partition(void)
205     {
206       int i;
207       int n = 0; // number of objects
208       CkHashtableIterator *ht = comps.iterator();
209       CkHashtableIterator *pt = ports.iterator();
210       // count the number of components, assigning unique index to each
211       // component, this index will be used for partitioning
212       ht->seekStart();
213       while(ht->hasNext()) {
214         Component *c = (Component *) ht->next();
215         c->setIdx(n);
216         n++;
217       }
218       int *nconnect = new int[n];
219       int tadj = 0;
220       ht->seekStart();
221       while(ht->hasNext()) {
222         Component *c = (Component *) ht->next();
223         nconnect[c->getIdx()] = c->getNumConnectedPorts();
224         tadj += nconnect[c->getIdx()];
225       }
226       // now the nconnect array contains the number of edges for each vertex
227       // and tadj contains total number of connections
228       int *xadj = new int[n];
229       int *adjncy = new int[tadj];
230       // construct the adjcency in CSR format as required by Metis
231       xadj[0] = 0;
232       for(i=1;i<n;i++)
233         xadj[i] = xadj[i-1] + nconnect[i-1];
234       for(i=0;i<tadj;i++)
235         adjncy[i] = (-1); // set to something invalid
236       pt->seekStart();
237       while(pt->hasNext()) {
238         Port *p = (Port *) pt->next();
239         Port *peer = p->getPeer();
240         if(peer==0) // an unconnected port
241           continue;
242         Component *comp1 = p->getComp();
243         Component *comp2 = peer->getComp();
244         int idx1 = comp1->getIdx();
245         int idx2 = comp2->getIdx();
246         int i;
247         for(i=xadj[idx1];adjncy[i]!=(-1);i++);
248         adjncy[i] = idx2;
249       }
250       int *vwgt = new int[n];
251       int *adjwgt = new int[tadj];
252       // currently all vertices are assumed to be of same wgt
253       // this will change after embellishing the connection code
254       for(i=0;i<n; i++)
255         vwgt[i] = 1;
256       // currently all vertices are assumed to be of same wgt
257       // this will change after embellishing the connection code
258       for(i=0;i<tadj; i++)
259         adjwgt[i] = 1;
260       int wgtflag = 3; // weights on both vertices and edges
261       int numflag = 0; // we use C-style numbering (starting with 0)
262       int nparts = CkNumPes(); // number of partitions desired
263       int options[5];
264       options[0] = 0; // use default options
265       int edgecut; // contains edgecut after partitioning
266       int *part = new int[n]; // contains mapping output to processor number
267       METIS_PartGraphRecursive(&n, xadj, adjncy, vwgt, adjwgt, &wgtflag,
268           &numflag, &nparts, options, &edgecut, part);
269       ht->seekStart();
270       while(ht->hasNext()) {
271         Component* c = (Component *) ht->next();
272         c->setPe(part[c->getIdx()]);
273       }
274     }
275 };
276
277 class CkArrayIndexCharisma: public CkArrayIndex
278 {
279   int i, j, k;
280   public:
281     CkArrayIndexCharisma(int _i) {
282       i = _i; j = 0; k = 0;
283       nInts = 1;
284     }
285     CkArrayIndexCharisma(int _i, int _j) {
286       i = _i; j= _j; k= 0;
287       nInts = 2;
288     }
289     CkArrayIndexCharisma(int _i, int _j, int _k) {
290       i = _i; j = _j; k= _k;
291       nInts = 3;
292     }
293 };
294
295 class CharismaInPort
296 {
297   public:
298     virtual ~CharismaInPort() {}
299     virtual void send(void *msg, int len) = 0;
300     void _create(const char *name)
301     {
302       // todo: tell Charisma that the inport is created
303     }
304 };
305
306 class CharismaOutPort
307 {
308   protected:
309     CharismaInPort *inport;
310   public:
311     virtual ~CharismaOutPort() {}
312     virtual void emitData(void *data, int len)
313     {
314       inport->send(data, len);
315     }
316     void _create(const char *name)
317     {
318       // todo: tell charisma that the outport is created
319     }
320 };
321
322 template <class d>
323 class CkOutPort: public CharismaOutPort
324 {
325   public:
326     CkOutPort(const char *name) { _create(name); }
327     void emit(d &_d)
328     {
329       CharismaOutPort::emitData((void *) &_d, sizeof(d));
330     }
331 };
332
333 template <class d>
334 class CkInPort : public CharismaInPort
335 {
336   private:
337     CkCallback cb;
338     CkInPort() {} // prevent illegal inports
339   public:
340     CkInPort(const char *name, int ep,const CkChareID &id)
341     {
342       _create(name);
343       CkCallback _cb(ep,id);
344       cb = _cb;
345     }
346     CkInPort(const char *name, int ep,int onPE,const CkGroupID &id)
347     {
348       _create(name);
349       CkCallback _cb(ep,onPE,id);
350       cb = _cb;
351     }
352     CkInPort(const char *name, int ep,const CkArrayIndex &idx,
353              const CkArrayID &id)
354     {
355       _create(name);
356       CkCallback _cb(ep,idx,id);
357       cb = _cb;
358     }
359     void send(void *data, int len)
360     {
361       send((d&) (*((d*)data)));
362     }
363     void send(d &_d)
364     {
365       int impl_off=0,impl_arrstart=0;
366       { //Find the size of the PUP'd data
367         PUP::sizer implP;
368         implP|_d;
369         impl_arrstart=CK_ALIGN(implP.size(),16);
370         impl_off+=impl_arrstart;
371       }
372       CkMarshallMsg *impl_msg=new (impl_off,0)CkMarshallMsg;
373       { //Copy over the PUP'd data
374         PUP::toMem implP((void *)impl_msg->msgBuf);
375         implP|_d;
376       }
377       CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;
378       impl_amsg->array_setIfNotThere(CkArray_IfNotThere_buffer);
379       cb.send(impl_msg);
380     }
381 };
382
383 class CkOutPortString : public CharismaOutPort
384 {
385   public:
386     CkOutPortString(const char *name) { _create(name); }
387     void emit(char *str)
388     {
389       CharismaOutPort::emitData((void *) str, (int) strlen(str)+1);
390     }
391 };
392
393 class CkInPortString : public CharismaInPort
394 {
395   private:
396     CkCallback cb;
397     CkInPortString() {} // prevent illegal inports
398   public:
399     CkInPortString(const char *name, int ep,const CkChareID &id)
400     {
401       _create(name);
402       CkCallback _cb(ep,id);
403       cb = _cb;
404     }
405     CkInPortString(const char *name, int ep,int onPE,const CkGroupID &id)
406     {
407       _create(name);
408       CkCallback _cb(ep,onPE,id);
409       cb = _cb;
410     }
411     CkInPortString(const char *name, int ep,const CkArrayIndex &idx,
412                    const CkArrayID &id)
413     {
414       _create(name);
415       CkCallback _cb(ep,idx,id);
416       cb = _cb;
417     }
418     void send(void *data, int len)
419     {
420       send((char *) data);
421     }
422     void send(char *str)
423     {
424       CkMarshallMsg *impl_msg=new (strlen(str)+1,0)CkMarshallMsg;
425       strcpy((char *)(impl_msg->msgBuf),str);
426       CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;
427       impl_amsg->array_setIfNotThere(CkArray_IfNotThere_buffer);
428       cb.send(impl_msg);
429     }
430 };
431
432 template <class d>
433 class CkOutPortArray : public CharismaOutPort
434 {
435   public:
436     CkOutPortArray(const char *name) { _create(name); }
437     void emit(int n, const d *a)
438     {
439       CharismaOutPort::emitData((void *)a, n*sizeof(d));
440     }
441 };
442
443 template <class d>
444 class CkInPortArray : public CharismaInPort
445 {
446   private:
447     CkCallback cb;
448     CkInPortArray() {} // prevent illegal inports
449   public:
450     CkInPortArray(const char *name, int ep,const CkChareID &id)
451     {
452       _create(name);
453       CkCallback _cb(ep,id);
454       cb = _cb;
455     }
456     CkInPortArray(const char *name, int ep,int onPE,const CkGroupID &id)
457     {
458       _create(name);
459       CkCallback _cb(ep,onPE,id);
460       cb = _cb;
461     }
462     CkInPortArray(const char *name, int ep,const CkArrayIndex &idx,
463                   const CkArrayID &id)
464     {
465       _create(name);
466       CkCallback _cb(ep,idx,id);
467       cb = _cb;
468     }
469     void send(void *data, int len)
470     {
471       send(len/sizeof(d), (const d*) data);
472     }
473     void send(int n, const d *a)
474     {
475       //Marshall: int n, const int *a
476       int impl_off=0,impl_arrstart=0;
477       int impl_off_a, impl_cnt_a;
478       impl_off_a=impl_off=CK_ALIGN(impl_off,sizeof(int));
479       impl_off+=(impl_cnt_a=sizeof(int)*(n));
480       { //Find the size of the PUP'd data
481         PUP::sizer implP;
482         implP|n;
483         implP|impl_off_a;
484         impl_arrstart=CK_ALIGN(implP.size(),16);
485         impl_off+=impl_arrstart;
486       }
487       CkMarshallMsg *impl_msg=new (impl_off,0)CkMarshallMsg;
488       { //Copy over the PUP'd data
489         PUP::toMem implP((void *)impl_msg->msgBuf);
490         implP|n;
491         implP|impl_off_a;
492       }
493       char *impl_buf=impl_msg->msgBuf+impl_arrstart;
494       memcpy(impl_buf+impl_off_a,a,impl_cnt_a);
495     }
496 };
497
498 class CkOutPortVoid : public CharismaOutPort
499 {
500   public:
501     CkOutPortVoid(const char *name) { _create(name); }
502     void emit(void)
503     {
504       CharismaOutPort::emitData((void*) 0, 0);
505     }
506 };
507
508 class CkInPortVoid : public CharismaInPort
509 {
510   private:
511     CkCallback cb;
512     CkInPortVoid() {} // prevent illegal inports
513   public:
514     CkInPortVoid(const char *name, int ep,const CkChareID &id)
515     {
516       _create(name);
517       CkCallback _cb(ep,id);
518       cb = _cb;
519     }
520     CkInPortVoid(const char *name, int ep,int onPE,const CkGroupID &id)
521     {
522       _create(name);
523       CkCallback _cb(ep,onPE,id);
524       cb = _cb;
525     }
526     CkInPortVoid(const char *name, int ep,const CkArrayIndex &idx,
527                  const CkArrayID &id)
528     {
529       _create(name);
530       CkCallback _cb(ep,idx,id);
531       cb = _cb;
532     }
533     void send(void *data, int len)
534     {
535       send();
536     }
537     void send(void)
538     {
539       void *impl_msg = CkAllocSysMsg();
540       cb.send(impl_msg);
541     }
542 };
543
544 template <class d>
545 class CkOutPortMsg : public CharismaOutPort
546 {
547   public:
548     CkOutPortMsg(const char *name) { _create(name); }
549     void emit(d *data)
550     {
551       // TODO: do message packing, and get the actual buffer size
552       CharismaOutPort::emitData((void*) data, sizeof(d));
553     }
554 };
555
556 template <class d>
557 class CkInPortMsg : public CharismaInPort
558 {
559   private:
560     CkCallback cb;
561     CkInPortMsg() {} // prevent illegal inports
562   public:
563     CkInPortMsg(const char *name, int ep,const CkChareID &id)
564     {
565       _create(name);
566       CkCallback _cb(ep,id);
567       cb = _cb;
568     }
569     CkInPortMsg(const char *name, int ep,int onPE,const CkGroupID &id)
570     {
571       _create(name);
572       CkCallback _cb(ep,onPE,id);
573       cb = _cb;
574     }
575     CkInPortMsg(const char *name, int ep,const CkArrayIndex &idx,
576                 const CkArrayID &id)
577     {
578       _create(name);
579       CkCallback _cb(ep,idx,id);
580       cb = _cb;
581     }
582     void send(void *data, int len)
583     {
584       send((d*) data);
585     }
586     void send(d *_d)
587     {
588       cb.send(_d);
589     }
590 };
591
592 class Charisma : public IrrGroup
593 {
594   public:
595     Charisma(void) { }
596     Charisma(CkMigrateMessage *m) : IrrGroup(m) { }
597 };
598
599 #endif