10 class CMessage_CkArgMsg
{
11 public: static int __idx
;
13 #define CK_ALIGN(val,to) (((val)+(to)-1)&~((to)-1))
16 #define UNUSED __attribute__ ((unused))
23 #include "ckbitvector.h"
25 #include "debug-charm.h"
30 #include <ckmessage.h>
36 CkpvExtern(size_t *, _offsets
);
40 //This is for passing a single Charm++ message via parameter marshalling
41 class CkMarshalledMessage
{
43 //Don't use these: only pass by reference
44 void operator=(const CkMarshalledMessage
&);
46 CkMarshalledMessage(void): msg(NULL
) {}
47 CkMarshalledMessage(CkMessage
*m
): msg(m
) {} //Takes ownership of message
48 CkMarshalledMessage(const CkMarshalledMessage
&);
49 ~CkMarshalledMessage() {if (msg
) CkFreeMsg(msg
);}
50 CkMessage
*getMessage(void) {void *ret
=msg
; msg
=NULL
; return (CkMessage
*)ret
;}
51 void pup(PUP::er
&p
) {CkPupMessage(p
,&msg
,1);}
53 PUPmarshall(CkMarshalledMessage
)
56 * CkEntryOptions describes the options associated
57 * with an entry method invocation, which include
58 * the message priority and queuing strategy.
59 * It is only used with parameter marshalling.
61 class CkEntryOptions
: public CkNoncopyable
{
62 int queueingtype
; //CK_QUEUEING type
63 int prioBits
; //Number of bits of priority to use
64 typedef unsigned int prio_t
; //Datatype used to represent priorities
65 prio_t
*prioPtr
; //Points to message priority values
66 prio_t prioStore
; //For short priorities, stores the priority value
67 CkGroupID depGroupID
; // group dependence
69 CkEntryOptions(void): queueingtype(CK_QUEUEING_FIFO
), prioBits(0),
70 prioPtr(NULL
), prioStore(0) { depGroupID
.setZero(); }
73 if ( prioPtr
!= NULL
&& queueingtype
!= CK_QUEUEING_IFIFO
&&
74 queueingtype
!= CK_QUEUEING_ILIFO
) {
80 inline CkEntryOptions
& setPriority(prio_t integerPrio
) {
81 queueingtype
=CK_QUEUEING_IFIFO
;
82 prioBits
=8*sizeof(integerPrio
);
84 prioStore
=integerPrio
;
87 inline CkEntryOptions
& setPriority(int prioBits_
,const prio_t
*prioPtr_
) {
88 if ( prioPtr
!= NULL
&& queueingtype
!= CK_QUEUEING_IFIFO
&&
89 queueingtype
!= CK_QUEUEING_ILIFO
) {
93 queueingtype
=CK_QUEUEING_BFIFO
;
95 int dataLength
= (prioBits
+ (sizeof(prio_t
)*8 - 1)) /
97 prioPtr
= new prio_t
[dataLength
];
98 memcpy((void *)prioPtr
, prioPtr_
, dataLength
*sizeof(unsigned int));
101 inline CkEntryOptions
& setPriority(const CkBitVector
&cbv
) {
102 if ( cbv
.data
!= NULL
) {
103 if ( prioPtr
!= NULL
&& queueingtype
!= CK_QUEUEING_IFIFO
&&
104 queueingtype
!= CK_QUEUEING_ILIFO
) {
108 queueingtype
=CK_QUEUEING_BFIFO
;
109 prioBits
=cbv
.usedBits
;
110 int dataLength
= (prioBits
+ (sizeof(prio_t
)*8 - 1)) /
112 prioPtr
= new prio_t
[dataLength
];
113 memcpy((void *)prioPtr
, cbv
.data
, dataLength
*sizeof(prio_t
));
115 queueingtype
=CK_QUEUEING_BFIFO
;
118 prioPtr
= new prio_t
[dataLength
];
124 inline CkEntryOptions
& setQueueing(int queueingtype_
) { queueingtype
=queueingtype_
; return *this; }
125 inline CkEntryOptions
& setGroupDepID(const CkGroupID
&gid
) { depGroupID
= gid
; return *this; }
127 ///These are used by CkAllocateMarshallMsg, below:
128 inline int getQueueing(void) const {return queueingtype
;}
129 inline int getPriorityBits(void) const {return prioBits
;}
130 inline const prio_t
*getPriorityPtr(void) const {return prioPtr
;}
131 inline const CkGroupID
getGroupDepID() const { return depGroupID
; }
134 #include "CkMarshall.decl.h"
135 //This is the message type marshalled parameters get packed into:
136 class CkMarshallMsg
: public CMessage_CkMarshallMsg
{
143 //A queue-of-messages, like CkMsgQ<CkReductionMsg>
145 class CkMsgQ
: public CkQ
<MSG
*> {
147 ~CkMsgQ() { //Delete the messages in the queue:
149 while (NULL
!=(m
=this->deq())) delete m
;
151 void pup(PUP::er
&p
) {
152 int l
=this->length();
154 for (int i
=0;i
<l
;i
++) {
156 if (!p
.isUnpacking()) m
=this->deq();
157 CkPupMessage(p
,(void **)&m
);
161 friend void operator|(PUP::er
&p
,CkMsgQ
<MSG
> &v
) {v
.pup(p
);}
166 #include "ckarrayindex.h"
168 #include "cksection.h"
170 #include "ckcallback.h"
172 /********************* Superclass of all Chares ******************/
173 #if CMK_MULTIPLE_DELETE
174 #define CHARM_INPLACE_NEW \
175 void *operator new(size_t, void *ptr) { return ptr; }; \
176 void operator delete(void*, void*) {}; \
177 void *operator new(size_t s) { return malloc(s); } \
178 void operator delete(void *ptr) { free(ptr); }
180 #define CHARM_INPLACE_NEW \
181 void *operator new(size_t, void *ptr) { return ptr; }; \
182 void *operator new(size_t s) { return malloc(s); } \
183 void operator delete(void *ptr) { free(ptr); }
186 // for object message queue
190 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
194 #define CHARE_MAGIC 0x201201
197 The base class of all parallel objects in Charm++,
198 including Array Elements, Groups, and NodeGroups.
202 CkChareID thishandle
;
203 #if CMK_OBJECT_QUEUE_AVAILABLE
204 CkObjectMsgQ objQ
; // object message queue
207 #if CMK_ERROR_CHECKING
210 #ifndef CMK_CHARE_USE_PTR
211 int chareIdx
; // index in the chare obj table (chare_objs)
213 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
214 ChareMlogData
*mlogData
;
216 Chare(CkMigrateMessage
*m
);
218 virtual ~Chare(); //<- needed for *any* child to have a virtual destructor
220 /// Pack/UnPack - tell the runtime how to serialize this class's
221 /// data for migration, checkpoint, etc.
222 virtual void pup(PUP::er
&p
);
223 /// Routine that runtime the runtime actually calls, to enable
224 /// more intelligence in generated code that overrides this. The
225 /// actual pup() method must remain virtual, so that this
226 /// continues to work for older code.
227 virtual void virtual_pup(PUP::er
&p
) { pup(p
); }
228 void parent_pup(PUP::er
&p
) {
230 CkAbort("Should never get here - only called in generated CBase code");
233 inline const CkChareID
&ckGetChareID(void) const {return thishandle
;}
234 inline void CkGetChareID(CkChareID
*dest
) const {*dest
=thishandle
;}
235 // object message queue
237 #if CMK_OBJECT_QUEUE_AVAILABLE
238 inline CkObjectMsgQ
&CkGetObjQueue() { return objQ
; }
241 /// Return the type of this chare, as present in _chareTable
242 virtual int ckGetChareType() const;
243 /// Return a strdup'd array containing this object's string name.
244 virtual char *ckDebugChareName(void);
245 /// Place into str a copy of the id of this object up to limit bytes, return
246 /// the number of bytes used for the id
247 virtual int ckDebugChareID(char *str
, int limit
);
248 virtual void ckDebugPup(PUP::er
&p
);
249 /// Called when a [threaded] charm entry method is created:
250 virtual void CkAddThreadListeners(CthThread tid
, void *msg
);
251 #if CMK_ERROR_CHECKING
252 inline void sanitycheck() {
253 if (magic
!= CHARE_MAGIC
)
254 CmiAbort("Charm++ Fatal Error> Chare magic number does not agree, possibly due to pup functions not calling parent class.");
259 //Superclass of all Groups that cannot participate in reductions.
260 // Undocumented: should only be used inside Charm++.
261 /*forward*/ class Group
;
262 class IrrGroup
: public Chare
{
266 IrrGroup(CkMigrateMessage
*m
): Chare(m
) { }
268 virtual ~IrrGroup(); //<- needed for *any* child to have a virtual destructor
270 virtual void pup(PUP::er
&p
);//<- pack/unpack routine
271 virtual void ckJustMigrated(void);
272 inline const CkGroupID
&ckGetGroupID(void) const {return thisgroup
;}
273 inline CkGroupID
CkGetGroupID(void) const {return thisgroup
;}
274 virtual int ckGetChareType() const;
275 virtual char *ckDebugChareName();
276 virtual int ckDebugChareID(char *, int);
278 // Silly run-time type information
279 virtual int isNodeGroup() { return 0; };
280 virtual bool isLocMgr(void){ return false; }
281 virtual bool isArrMgr(void){ return false; }
282 virtual bool isReductionMgr(void){ return false; }
283 static int isIrreducible(){ return 1;}
284 virtual void flushStates() {}
288 virtual void evacuate(){};
289 virtual void doneEvacuate(){};
290 virtual void CkAddThreadListeners(CthThread tid
, void *msg
);
293 // As described in http://www.gotw.ca/publications/mxc++-item-4.htm
294 template<typename D
, typename B
>
298 class Yes
{ No no
[3]; };
300 static Yes
Test( B
* ); // not defined
301 static No
Test( ... ); // not defined
303 static void Constraints(D
* p
) { B
* pb
= p
; pb
= p
; }
306 enum { Is
= sizeof(Test(static_cast<D
*>(0))) == sizeof(Yes
) };
308 IsDerivedFrom() { void(*p
)(D
*) = Constraints
; }
311 /// Base case for the infrastructure to recursively handle inheritance
312 /// through CBase_foo from anything that implements X::pup(). Chare
313 /// classes have generated specializations that call PUPs for their
314 /// parents, SDAG, etc. The default case is an explicit specialization
315 /// so that corner cases I haven't handled are more likely to produce
316 /// linker errors, rather than potentially running incorrectly.
318 /// The specialized templates are structs for reasons explained by
319 /// http://www.gotw.ca/publications/mill17.htm
321 template <typename T
, int automatic
>
322 struct recursive_pup_impl
{
323 void operator()(T
*obj
, PUP::er
&p
);
326 template <typename T
>
327 struct recursive_pup_impl
<T
, 1> {
328 void operator()(T
*obj
, PUP::er
&p
) {
335 template <typename T
>
336 struct recursive_pup_impl
<T
, 0> {
337 void operator()(T
*obj
, PUP::er
&p
) {
341 template <typename T
>
342 void recursive_pup(T
*obj
, PUP::er
&p
) {
343 recursive_pup_impl
<T
, IsDerivedFrom
<T
, CBase
>::Is
>()(obj
, p
);
346 // CBaseX::pup must be an empty override, so that the recursive PUPing
347 // doesn't call an implementation multiple times up the inheritance
348 // hierarchy, and old-style calls to CBase_foo::pup actually produce
349 // no-ops. We give the prototype for virtual_pup to avoid repetition.
350 #define CBASE_MEMBERS \
351 typedef typename CProxy_Derived::local_t local_t; \
352 typedef typename CProxy_Derived::index_t index_t; \
353 typedef typename CProxy_Derived::proxy_t proxy_t; \
354 typedef typename CProxy_Derived::element_t element_t; \
355 CProxy_Derived thisProxy; \
356 void pup(PUP::er &p) { (void)p; } \
357 inline void _sdag_pup(PUP::er &p) { (void)p; } \
358 void virtual_pup(PUP::er &p)
360 /*Templated implementation of CBase_* classes.*/
361 template <class Parent
,class CProxy_Derived
>
362 struct CBaseT1
: Parent
, virtual CBase
{
365 #if CMK_HAS_RVALUE_REFERENCES
366 template <typename
... Args
>
367 CBaseT1(Args
&&... args
) : Parent(std::forward
<Args
>(args
)...) { thisProxy
= this; }
369 template <typename
... Args
>
370 CBaseT1(Args
... args
) : Parent(args
...) { thisProxy
= this; }
373 void parent_pup(PUP::er
&p
) {
374 recursive_pup
<Parent
>(this, p
);
379 /*Templated version of above for multiple (at least duplicate) inheritance:*/
380 template <class Parent1
,class Parent2
,class CProxy_Derived
>
381 struct CBaseT2
: public Parent1
, public Parent2
, virtual CBase
{
384 CBaseT2(void) :Parent1(), Parent2()
385 { thisProxy
= (Parent1
*)this; }
386 CBaseT2(CkMigrateMessage
*m
) :Parent1(m
), Parent2(m
)
387 { thisProxy
= (Parent1
*)this; }
389 void parent_pup(PUP::er
&p
) {
390 recursive_pup
<Parent1
>(this, p
);
391 recursive_pup
<Parent2
>(this, p
);
395 //These overloads are needed to prevent ambiguity for multiple inheritance:
396 inline const CkChareID
&ckGetChareID(void) const
397 {return ((Parent1
*)this)->ckGetChareID();}
398 static int isIrreducible(){ return (Parent1::isIrreducible() && Parent2::isIrreducible());}
402 #define BASEN(n) CMK_CONCAT(CBaseT, n)
403 #define PARENTN(n) CMK_CONCAT(Parent,n)
406 BASEN(n)() : base(), PARENTN(n)() {} \
407 BASEN(n)(CkMigrateMessage *m) \
408 : base(m), PARENTN(n)(m) {} \
409 void parent_pup(PUP::er &p) { \
410 recursive_pup<base>(this, p); \
411 recursive_pup<PARENTN(n)>(this, p); \
413 static int isIrreducible() { \
414 return (base::isIrreducible() && PARENTN(n)::isIrreducible()); \
418 template <class Parent1
, class Parent2
, class Parent3
, class CProxy_Derived
>
419 struct CBaseT3
: public CBaseT2
<Parent1
, Parent2
, CProxy_Derived
>,
422 typedef CBaseT2
<Parent1
, Parent2
, CProxy_Derived
> base
;
426 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
427 class CProxy_Derived
>
428 struct CBaseT4
: public CBaseT3
<Parent1
, Parent2
, Parent3
,
432 typedef CBaseT3
<Parent1
, Parent2
, Parent3
, CProxy_Derived
> base
;
436 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
437 class Parent5
, class CProxy_Derived
>
438 struct CBaseT5
: public CBaseT4
<Parent1
, Parent2
, Parent3
,
439 Parent4
, CProxy_Derived
>,
442 typedef CBaseT4
<Parent1
, Parent2
, Parent3
, Parent4
, CProxy_Derived
> base
;
446 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
447 class Parent5
, class Parent6
, class CProxy_Derived
>
448 struct CBaseT6
: public CBaseT5
<Parent1
, Parent2
, Parent3
,
449 Parent4
, Parent5
, CProxy_Derived
>,
452 typedef CBaseT5
<Parent1
, Parent2
, Parent3
, Parent4
, Parent5
,
453 CProxy_Derived
> base
;
457 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
458 class Parent5
, class Parent6
, class Parent7
, class CProxy_Derived
>
459 struct CBaseT7
: public CBaseT6
<Parent1
, Parent2
, Parent3
,
460 Parent4
, Parent5
, Parent6
, CProxy_Derived
>,
463 typedef CBaseT6
<Parent1
, Parent2
, Parent3
, Parent4
, Parent5
,
464 Parent6
, CProxy_Derived
> base
;
468 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
469 class Parent5
, class Parent6
, class Parent7
, class Parent8
, class CProxy_Derived
>
470 struct CBaseT8
: public CBaseT7
<Parent1
, Parent2
, Parent3
,
471 Parent4
, Parent5
, Parent6
, Parent7
, CProxy_Derived
>,
474 typedef CBaseT7
<Parent1
, Parent2
, Parent3
, Parent4
, Parent5
, Parent6
, Parent7
, CProxy_Derived
> base
;
478 template <class Parent1
, class Parent2
, class Parent3
, class Parent4
,
479 class Parent5
, class Parent6
, class Parent7
, class Parent8
, class Parent9
, class CProxy_Derived
>
480 struct CBaseT9
: public CBaseT8
<Parent1
, Parent2
, Parent3
,
481 Parent4
, Parent5
, Parent6
, Parent7
, Parent8
, CProxy_Derived
>,
484 typedef CBaseT8
<Parent1
, Parent2
, Parent3
, Parent4
, Parent5
, Parent6
, Parent7
, Parent8
, CProxy_Derived
> base
;
492 /**************************** CkDelegateMgr **************************/
497 Per-proxy data storage for delegation. A CkDelegateMgr
498 inherits from this class and adds his per-proxy data.
499 This class is reference counted.
501 class CkDelegateData
: public CkNoncopyable
{
502 int refcount
; // reference count
504 CkDelegateData() :refcount(0) {}
505 virtual ~CkDelegateData();
507 //Child class constructor may have to set this.
508 inline void reset() {
512 /// Add a reference to this delegation data. Just increments the refcount.
513 /// Only CProxy should ever have to call this routine.
514 /// Actually now the delegate manager calls it.
515 inline void ref(void) {refcount
++;}
517 /// Remove our reference from this data. If the refcount
518 /// reaches 0, deletes the delegateData.
519 /// Only CProxy should ever have to call this routine.
520 /// Actually now the delegate manager calls it.
521 inline void unref(void) {
523 if (refcount
==0) delete this;
528 Message delegation support, where you send a message via
529 a proxy normally, but the message ends up routed via this
530 special delegateMgr group.
532 An "interface" class-- all delegated messages are routed via
533 this class. The default action is to deliver the message directly.
535 class CkDelegateMgr
: public IrrGroup
{
537 virtual ~CkDelegateMgr(); //<- so children can have virtual destructor
538 virtual void ChareSend(CkDelegateData
*pd
,int ep
,void *m
,const CkChareID
*c
,int onPE
);
540 virtual void GroupSend(CkDelegateData
*pd
,int ep
,void *m
,int onPE
,CkGroupID g
);
541 virtual void GroupBroadcast(CkDelegateData
*pd
,int ep
,void *m
,CkGroupID g
);
542 virtual void GroupSectionSend(CkDelegateData
*pd
,int ep
,void *m
,int nsid
,CkSectionID
*s
);
544 virtual void NodeGroupSend(CkDelegateData
*pd
,int ep
,void *m
,int onNode
,CkNodeGroupID g
);
545 virtual void NodeGroupBroadcast(CkDelegateData
*pd
,int ep
,void *m
,CkNodeGroupID g
);
546 virtual void NodeGroupSectionSend(CkDelegateData
*pd
,int ep
,void *m
,int nsid
,CkSectionID
*s
);
548 virtual void ArrayCreate(CkDelegateData
*pd
,int ep
,void *m
,const CkArrayIndex
&idx
,int onPE
,CkArrayID a
);
549 virtual void ArraySend(CkDelegateData
*pd
,int ep
,void *m
,const CkArrayIndex
&idx
,CkArrayID a
);
550 virtual void ArrayBroadcast(CkDelegateData
*pd
,int ep
,void *m
,CkArrayID a
);
551 virtual void ArraySectionSend(CkDelegateData
*pd
,int ep
,void *m
,int nsid
,CkSectionID
*s
,int opts
);
552 virtual void initDelegateMgr(CProxy
*proxy
) { (void)proxy
; }
553 virtual CkDelegateData
* ckCopyDelegateData(CkDelegateData
*data
) {
559 Management of per-proxy data: pup this delegate's data.
560 If p.isUnpacking, allocate and return a new set of delegate data.
561 Never delete (or unref) the data-- the proxy will do that itself
563 The default implementation just ignores this call.
565 A typical implementation that uses CkDelegateData might look like this:
567 myData *d=(myData *)pd;
568 if (p.isUnpacking()) d=new myData();
574 virtual CkDelegateData
*DelegatePointerPup(PUP::er
&p
,CkDelegateData
*pd
);
578 /**************************** Proxies **************************/
581 A proxy is a local handle to a remote object. This is the superclass
582 of all proxies: CProxy_Array, CProxy_Group, etc. inherit from this class.
584 Real proxies for user classes are generated by the .ci file translator charmxi
585 and put in the generated .decl.h headers.
589 CkGroupID delegatedGroupId
;
591 mutable CkDelegateMgr
*delegatedMgr
; // can be either a group or a nodegroup
592 CkDelegateData
*delegatedPtr
; // private data for use by delegatedMgr.
593 protected: //Never allocate CProxy's-- only subclass them.
594 CProxy() : isNodeGroup(0), delegatedMgr(0), delegatedPtr(0)
595 {delegatedGroupId
.setZero(); }
597 #define CK_DELCTOR_PARAM CkDelegateMgr *dTo,CkDelegateData *dPtr
598 #define CK_DELCTOR_ARGS dTo,dPtr
599 #define CK_DELCTOR_CALL ckDelegatedTo(),ckDelegatedPtr()
600 /// Delegation constructor: used when building
601 /// an element proxy from a collective proxy, like in "aProxy[i]".
602 CProxy(CK_DELCTOR_PARAM
)
606 if(delegatedMgr
!= NULL
&& dPtr
!= NULL
) {
607 delegatedPtr
= delegatedMgr
->ckCopyDelegateData(dPtr
);
608 delegatedGroupId
= delegatedMgr
->CkGetGroupID();
609 isNodeGroup
= delegatedMgr
->isNodeGroup();
613 /// Copy constructor. Only needed for delegated proxies.
614 CProxy(const CProxy
&src
);
615 /// Assignment operator. Only needed for delegated proxies.
616 CProxy
& operator=(const CProxy
&src
);
617 /// Destructor. Only needed for delegated proxies.
619 if (delegatedPtr
) delegatedPtr
->unref();
623 Delegation allows a class, called a CkDelegateMgr, to
624 intercept calls made to this proxy for further processing.
626 "ptr" is any delegator-specific data the CkDelegateMgr wants
627 to associate with this proxy: the pointer is owned by this
628 proxy, but will be copied and pupped by calling delegator routines.
630 This interface should only be used by library writers,
631 not ordinary user code.
633 void ckDelegate(CkDelegateMgr
*to
,CkDelegateData
*pd
=NULL
);
635 /// Remove delegation from this proxy.
636 void ckUndelegate(void);
638 /// Return true if this proxy is delegated.
639 int ckIsDelegated(void) const { return(delegatedMgr
!=NULL
);}
641 /// Return the delegator of this proxy, to which the proxies' messages
642 /// are actually sent.
643 inline CkDelegateMgr
*ckDelegatedTo(void) const {
645 // needed if proxy was defined before group creation
646 // (i.e. for delegated readonly proxies)
647 if (delegatedMgr
== NULL
&& !delegatedGroupId
.isZero()) {
649 delegatedMgr
=(CkDelegateMgr
*)CkLocalNodeBranch(delegatedGroupId
);
652 delegatedMgr
=(CkDelegateMgr
*)CkLocalBranch(delegatedGroupId
);
661 /// Return the delegator's local data associated with this proxy.
662 inline CkDelegateData
*ckDelegatedPtr(void) const {return delegatedPtr
;}
664 /// Return the groupID of our delegator.
665 /// Note that this can be a GroupID or a NodeGroupID, so be careful!
666 CkGroupID
ckDelegatedIdx(void) const {
667 if (delegatedMgr
) return delegatedMgr
->CkGetGroupID();
669 CkGroupID gid
; gid
.setZero();
674 /// Pup the data for this proxy. Only needed for delegated proxies.
675 void pup(PUP::er
&p
);
681 /*The base classes of each proxy type
683 class CProxy_Chare
: public CProxy
{
688 #if CMK_ERROR_CHECKING
689 _ck_cid
.onPE
=0; _ck_cid
.objPtr
=0;
692 #if CMK_ERROR_CHECKING
693 inline void ckCheck(void) const { //Make sure this proxy has a value
694 #ifdef CMK_CHARE_USE_PTR
695 if (_ck_cid
.objPtr
==0)
696 CkAbort("Error! This chare proxy has not been initialized!");
700 inline void ckCheck() const {}
702 CProxy_Chare(const CkChareID
&c
) : _ck_cid(c
) {}
703 CProxy_Chare(const Chare
*c
) : _ck_cid(c
->ckGetChareID()) {}
704 const CkChareID
&ckGetChareID(void) const {return _ck_cid
;}
705 operator const CkChareID
&(void) const {return ckGetChareID();}
706 void ckSetChareID(const CkChareID
&c
) {_ck_cid
=c
;}
707 void pup(PUP::er
&p
) {
710 //Copy the pointer as straight bytes
711 p((char *)&_ck_cid
.objPtr
,sizeof(_ck_cid
.objPtr
));
714 PUPmarshall(CProxy_Chare
)
716 /******************* Reduction Declarations ****************/
717 //Silly: need the type of a reduction client here so it can be used by proxies.
718 //A clientFn is called on PE 0 when all contributions
719 // have been received and reduced.
720 // param can be ignored, or used to pass any client-specific data you $
721 // dataSize gives the size (in bytes) of the data array
722 // data gives the reduced contributions--
723 // it will be disposed of after this procedure returns.
724 typedef void (*CkReductionClientFn
)(void *param
,int dataSize
,void *data
);
726 /// Tiny utility class used by CkReductionClientAdaptor--
727 /// lets us keep backward compatability with the old C-style interface.
728 class CkReductionClientBundle
: public CkCallback
{
729 CkReductionClientFn fn
;
732 static void callbackCfn(void *thisPtr
,void *reductionMsg
);
733 CkReductionClientBundle(): fn(NULL
), param(NULL
) {}
734 CkReductionClientBundle(CkReductionClientFn fn_
,void *param_
);
736 PUPbytes(CkReductionClientBundle
)
738 #define CK_REDUCTION_CLIENT_DECL \
739 void setReductionClient(CkReductionClientFn fn,void *param=NULL) const\
740 { ckSetReductionClient(fn,param); } \
741 void ckSetReductionClient(CkReductionClientFn fn,void *param=NULL) const \
742 { ckSetReductionClient(new CkReductionClientBundle(fn,param)); } \
743 void ckSetReductionClient(CkCallback *cb) const;\
745 #define CK_REDUCTION_CLIENT_DEF(className,mgr) \
746 void className::ckSetReductionClient(CkCallback *cb) const \
747 { (mgr)->ckSetReductionClient(cb); }\
750 class CProxy_NodeGroup;
751 class CProxy_CkArrayReductionMgr
;
752 class CProxy_Group
: public CProxy
{
758 #if CMK_ERROR_CHECKING
761 //CkPrintf(" In CProxy_Group Constructor\n");
763 CProxy_Group(CkGroupID g
)
764 :CProxy(),_ck_gid(g
) {
765 //CkPrintf(" In CProxy_Group Constructor\n");
767 CProxy_Group(CkGroupID g
,CK_DELCTOR_PARAM
)
768 :CProxy(CK_DELCTOR_ARGS
),_ck_gid(g
) {
769 //CkPrintf(" In CProxy_Group Constructor\n");
771 CProxy_Group(const IrrGroup
*g
)
772 :CProxy(), _ck_gid(g
->ckGetGroupID()) {
773 //CkPrintf(" In CProxy_Group Constructor\n");
775 /* CProxy_Group(const NodeGroup *g) //<- for compatability with NodeGroups
776 :CProxy(), _ck_gid(g->ckGetGroupID()) {}*/
778 #if CMK_ERROR_CHECKING
779 inline void ckCheck(void) const { //Make sure this proxy has a value
780 if (_ck_gid
.isZero())
781 CkAbort("Error! This group proxy has not been initialized!");
784 inline void ckCheck() const {}
787 CkChareID
ckGetChareID(void) const {
790 ret
.objPtr
=CkLocalBranch(_ck_gid
);
793 CkGroupID
ckGetGroupID(void) const {return _ck_gid
;}
794 operator CkGroupID () const {return ckGetGroupID();}
795 void ckSetGroupID(CkGroupID g
) {_ck_gid
=g
;}
796 void pup(PUP::er
&p
) {
800 CK_REDUCTION_CLIENT_DECL
802 PUPmarshall(CProxy_Group
)
804 class CProxyElement_Group
: public CProxy_Group
{
808 CProxyElement_Group() { }
809 CProxyElement_Group(CkGroupID g
,int onPE
)
810 : CProxy_Group(g
),_onPE(onPE
) {}
811 CProxyElement_Group(CkGroupID g
,int onPE
,CK_DELCTOR_PARAM
)
812 : CProxy_Group(g
,CK_DELCTOR_ARGS
),_onPE(onPE
) {}
813 CProxyElement_Group(const IrrGroup
*g
)
814 :CProxy_Group(g
), _onPE(CkMyPe()) {}
815 /*CProxyElement_Group(const NodeGroup *g) //<- for compatability with NodeGroups
816 :CProxy_Group(g), _onPE(CkMyPe()) {}*/
818 int ckGetGroupPe(void) const {return _onPE
;}
819 void pup(PUP::er
&p
) {
820 CProxy_Group::pup(p
);
824 PUPmarshall(CProxyElement_Group
)
826 class CProxySection_Group
: public CProxy_Group
{
831 CProxySection_Group() { }
832 CProxySection_Group(const CkGroupID
&gid
, const int *elems
, const int nElems
)
833 :CProxy_Group(gid
), _nsid(1) { _sid
= new CkSectionID(gid
, elems
, nElems
); }
834 CProxySection_Group(const CkGroupID
&gid
, const int *elems
, const int nElems
,CK_DELCTOR_PARAM
)
835 :CProxy_Group(gid
,CK_DELCTOR_ARGS
), _nsid(1) { _sid
= new CkSectionID(gid
, elems
, nElems
); }
836 CProxySection_Group(const CProxySection_Group
&cs
)
837 :CProxy_Group(cs
.ckGetGroupID()), _nsid(cs
._nsid
) {
838 if (_nsid
== 1) _sid
= new CkSectionID(cs
.ckGetGroupID(), cs
.ckGetElements(), cs
.ckGetNumElements());
839 else if (_nsid
> 1) {
840 _sid
= new CkSectionID
[_nsid
];
841 for (int i
=0; i
<_nsid
; ++i
) _sid
[i
] = cs
._sid
[i
];
844 CProxySection_Group(const CProxySection_Group
&cs
,CK_DELCTOR_PARAM
)
845 :CProxy_Group(cs
.ckGetGroupID(),CK_DELCTOR_ARGS
), _nsid(cs
._nsid
) {
846 if (_nsid
== 1) _sid
= new CkSectionID(cs
.ckGetGroupID(), cs
.ckGetElements(), cs
.ckGetNumElements());
847 else if (_nsid
> 1) {
848 _sid
= new CkSectionID
[_nsid
];
849 for (int i
=0; i
<_nsid
; ++i
) _sid
[i
] = cs
._sid
[i
];
852 CProxySection_Group(const IrrGroup
*g
)
853 :CProxy_Group(g
), _nsid(0) {}
854 CProxySection_Group(const int n
, const CkGroupID
*gid
, int const * const *elems
, const int *nElems
)
855 :CProxy_Group(gid
[0]), _nsid(n
) {
856 _sid
= new CkSectionID
[n
];
857 for (int i
=0; i
<n
; ++i
) _sid
[i
] = CkSectionID(gid
[i
], elems
[i
], nElems
[i
]);
859 CProxySection_Group(const int n
, const CkGroupID
*gid
, int const * const *elems
, const int *nElems
,CK_DELCTOR_PARAM
)
860 :CProxy_Group(gid
[0],CK_DELCTOR_ARGS
), _nsid(n
) {
861 _sid
= new CkSectionID
[n
];
862 for (int i
=0; i
<n
; ++i
) _sid
[i
] = CkSectionID(gid
[i
], elems
[i
], nElems
[i
]);
865 ~CProxySection_Group() {
866 if (_nsid
== 1) delete _sid
;
867 else if (_nsid
> 1) delete[] _sid
;
870 CProxySection_Group
&operator=(const CProxySection_Group
&cs
) {
871 CProxy_Group::operator=(cs
);
873 if (_nsid
== 1) _sid
= new CkSectionID(*cs
._sid
);
874 else if (_nsid
> 1) {
875 _sid
= new CkSectionID
[_nsid
];
876 for (int i
=0; i
<_nsid
; ++i
) _sid
[i
] = cs
._sid
[i
];
881 //void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
883 inline int ckGetNumSections() const {return _nsid
;}
884 inline CkSectionInfo
&ckGetSectionInfo() {return _sid
[0]._cookie
;}
885 inline CkSectionID
*ckGetSectionIDs() {return _sid
; }
886 inline CkSectionID
&ckGetSectionID() {return _sid
[0]; }
887 inline CkSectionID
&ckGetSectionID(int i
) {return _sid
[i
]; }
888 inline CkGroupID
ckGetGroupIDn(int i
) const {return (CkGroupID
)_sid
[i
]._cookie
.info
.aid
;}
889 inline int *ckGetElements() const {return _sid
[0].pelist
;}
890 inline int *ckGetElements(int i
) const {return _sid
[i
].pelist
;}
891 inline int ckGetNumElements() const { return _sid
[0].npes
; }
892 inline int ckGetNumElements(int i
) const { return _sid
[i
].npes
; }
893 void pup(PUP::er
&p
) {
894 CProxy_Group::pup(p
);
896 if (p
.isUnpacking()) {
897 if (_nsid
== 1) _sid
= new CkSectionID
;
898 else if (_nsid
> 1) _sid
= new CkSectionID
[_nsid
];
901 for (int i
=0; i
<_nsid
; ++i
) p
| _sid
[i
];
904 PUPmarshall(CProxySection_Group
)
906 /* These classes exist to provide chare indices for the basic
908 class CkIndex_Chare
{ public:
909 static int __idx
;//Fake chare index for registration
911 class CkIndex_ArrayBase
{ public:
912 static int __idx
;//Fake chare index for registration
914 class CkIndex_Group
{ public:
915 static int __idx
;//Fake chare index for registration
918 typedef CkIndex_Group CkIndex_NodeGroup
;
919 typedef CkIndex_Group CkIndex_IrrGroup
;
922 //typedef CProxy_Group CProxy_NodeGroup;
923 class CProxy_NodeGroup
: public CProxy
{
929 #if CMK_ERROR_CHECKING
932 //CkPrintf("In CProxy_NodeGroup0 Constructor %d\n",CkLocalNodeBranch(_ck_gid));
934 CProxy_NodeGroup(CkGroupID g
)
935 :CProxy(),_ck_gid(g
) {/*CkPrintf("In CProxy_NodeGroup1 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
936 CProxy_NodeGroup(CkGroupID g
,CK_DELCTOR_PARAM
)
937 :CProxy(CK_DELCTOR_ARGS
),_ck_gid(g
) {/*CkPrintf("In CProxy_NodeGroup2 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
938 CProxy_NodeGroup(const IrrGroup
*g
)
939 :CProxy(), _ck_gid(g
->ckGetGroupID()) {/*CkPrintf("In CProxy_NodeGroup3 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
940 /* CProxy_Group(const NodeGroup *g) //<- for compatability with NodeGroups
941 :CProxy(), _ck_gid(g->ckGetGroupID()) {}*/
943 #if CMK_ERROR_CHECKING
944 inline void ckCheck(void) const { //Make sure this proxy has a value
945 if (_ck_gid
.isZero())
946 CkAbort("Error! This group proxy has not been initialized!");
949 inline void ckCheck() const {}
952 CkChareID
ckGetChareID(void) const {
955 ret
.objPtr
=CkLocalBranch(_ck_gid
);
958 CkGroupID
ckGetGroupID(void) const {return _ck_gid
;}
959 operator CkGroupID () const {return ckGetGroupID();}
960 void ckSetGroupID(CkGroupID g
) {_ck_gid
=g
;}
961 void pup(PUP::er
&p
) {
965 CK_REDUCTION_CLIENT_DECL
969 typedef CProxy_Group CProxy_IrrGroup
;
970 typedef CProxyElement_Group CProxyElement_NodeGroup
;
971 typedef CProxyElement_Group CProxyElement_IrrGroup
;
972 typedef CProxySection_Group CProxySection_NodeGroup
;
973 typedef CProxySection_Group CProxySection_IrrGroup
;
976 //(CProxy_ArrayBase is defined in ckarray.h)
978 //Defines the actual "Group"
979 #include "ckreduction.h"
983 void *operator new(size_t s
) { return CkAllocMsg(0,(int)s
,0); }
984 void operator delete(void* ptr
) { CkFreeMsg(ptr
); }
985 static void *alloc(int, size_t s
, int*, int) {
986 return CkAllocMsg(0,(int)s
,0);
988 static void *pack(CkQdMsg
*m
) { return (void*) m
; }
989 static CkQdMsg
*unpack(void *buf
) { return (CkQdMsg
*) buf
; }
990 /// This is used to display message contents in the debugger.
991 static void ckDebugPup(PUP::er
&p
,void *msg
) {
1001 CkThrCallArg(void *m
, void *o
) : msg(m
), obj(o
) {}
1004 extern void CkStartQD(const CkCallback
& cb
);
1005 #define CkExitAfterQuiescence() CkStartQD(CkCallback(CkCallback::ckExit))
1008 #if !CMK_MACHINE_PROGRESS_DEFINED
1009 #define CkNetworkProgress()
1010 #define CkNetworkProgressAfter(p)
1013 void CmiMachineProgressImpl();
1015 #define CkNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1016 if(CpvAccess(networkProgressCount) >= networkProgressPeriod) \
1017 if (LBDatabaseObj()->getLBDB()->StatsOn() == 0) { \
1018 CmiMachineProgressImpl(); \
1019 CpvAccess(networkProgressCount) = 0; \
1023 #define CkNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1024 if(CpvAccess(networkProgressCount) >= p) \
1025 if (LBDatabaseObj()->getLBDB()->StatsOn() == 0) { \
1026 CmiMachineProgressImpl(); \
1027 CpvAccess(networkProgressCount) = 0; \
1034 #if defined(_FAULT_MLOG_)
1035 #include "ckmessagelogging.h"
1037 #if defined(_FAULT_CAUSAL_)
1038 #include "ckcausalmlog.h"
1041 #include "ckmemcheckpoint.h"
1042 #include "readonly.h"
1043 #include "ckarray.h"
1044 #include "ckstream.h"
1045 #include "ckfutures.h"
1049 #include "ckcheckpoint.h"
1050 #include "ckevacuation.h"
1051 #include "ckarrayreductionmgr.h"
1053 #include "envelope.h"
1054 #include "pathHistory.h"
1061 CkMarshallMsg
*CkAllocateMarshallMsgNoninline(int size
,const CkEntryOptions
*opts
);
1062 inline CkMarshallMsg
*CkAllocateMarshallMsg(int size
,const CkEntryOptions
*opts
=NULL
)
1065 CkMarshallMsg
*newMemory
= new (size
,0)CkMarshallMsg
;
1066 setMemoryTypeMessage(UsrToEnv(newMemory
));
1069 else return CkAllocateMarshallMsgNoninline(size
,opts
);
1078 template <typename T
>
1079 inline T
*CkAllocateMarshallMsgT(int size
,const CkEntryOptions
*opts
)
1082 if (opts
!=NULL
) priobits
= opts
->getPriorityBits();
1083 //Allocate the message
1084 T
*m
=new (size
,priobits
)T
;
1085 //Copy the user's priority data into the message
1086 envelope
*env
=UsrToEnv(m
);
1087 setMemoryTypeMessage(env
);
1089 CmiMemcpy(env
->getPrioPtr(),opts
->getPriorityPtr(),env
->getPrioBytes());
1090 //Set the message's queueing type
1091 env
->setQueueing((unsigned char)opts
->getQueueing());
1100 /************************** Debugging Utilities **************/
1102 CkpvExtern(DebugEntryTable
, _debugEntryTable
);
1104 //For debugging: convert given index to a string (NOT threadsafe)
1105 static const char *idx2str(const CkArrayIndex
&ind
) {
1106 static char retBuf
[80];
1108 if (ind
.dimension
<= 3) {
1109 for (int i
=0;i
<ind
.nInts
;i
++) {
1110 if (i
>0) strcat(retBuf
,";");
1111 sprintf(&retBuf
[strlen(retBuf
)],"%d",ind
.data()[i
]);
1114 const short int *idx
= (const short int*)ind
.data();
1115 for (int i
=0;i
<ind
.dimension
;i
++) {
1116 if (i
>0) strcat(retBuf
,";");
1117 sprintf(&retBuf
[strlen(retBuf
)],"%hd",idx
[i
]);
1123 static const char *idx2str(const ArrayElement
*el
) UNUSED
;
1124 static const char *idx2str(const ArrayElement
* el
) {
1125 return idx2str(el
->thisIndexMax
);
1130 class CkConditional
{
1133 CkConditional() : refcount(1) { }
1134 virtual ~CkConditional() { }
1136 void* operator new(size_t s) {
1141 //CkPrintf("CkConditional::delete %d\n",refcount);
1142 if (--refcount
== 0) {
1143 //((CkConditional*)p)->~CkConditional();
1147 void copyreference(void) {