Skip to content

Commit

Permalink
Add options to CkCallback::send and fix demand-creation (#3603)
Browse files Browse the repository at this point in the history
* Enable passing options to `CkCallback::send`

* Fix demand-creation for `CkCallback::send`

* Remove C++11 from Charmxi, remove pointer, update docs

* Fix erroneous doc label?

* Add include for `stdint`

* drop storage qualifier 🙄

* Update charm.h
  • Loading branch information
jszaday committed May 6, 2022
1 parent cb4d760 commit 4fd8c4b
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 34 deletions.
8 changes: 5 additions & 3 deletions doc/charm++/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2029,7 +2029,7 @@ the runtime will not “commit” to this branch until the second arrives.
If another dependency fully matches, the partial match will be ignored
and can be used to trigger another ``when`` later in the execution.

.. code-block:: c++
.. code-block:: text

case {
when a() { }
Expand Down Expand Up @@ -5666,12 +5666,14 @@ then invokes it to return a result may have the following interface:
cb.send(msg);
}

A CkCallback will accept any message type, or even NULL. The message is
A *CkCallback* will accept any message type, even *nullptr*. The message is
immediately sent to the user’s client function or entry point. A library
which returns its result through a callback should have a clearly
documented return message type. The type of the message returned by the
library must be the same as the type accepted by the entry method
specified in the callback.
specified in the callback. Note that message flag(s) may be passed as an
optional argument to “send;” for example, :code:`send(_, CK_MSG_EXPEDITED)`
will send a message with expediency.

As an alternative to “send”, the callback can be used in a *contribute*
collective operation. This will internally invoke the “send” method on
Expand Down
10 changes: 10 additions & 0 deletions src/ck-core/charm.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ typedef enum{
TypeArray
} ChareType;

// What to do if an entry method is invoked on
// an array element that does not (yet) exist:
typedef enum{
CkArray_IfNotThere_buffer = 0, // Wait for it to be created
CkArray_IfNotThere_createhere = 1, // Make it on sending Pe
CkArray_IfNotThere_createhome = 2 // Make it on (a) home Pe
} CkArray_IfNotThere;

/** A "call function" to invoke a method on an object. See EntryInfo */
typedef void (*CkCallFnPtr) (void *msg, void *obj);
/** Register this entry point, with this call function and flags.
Expand All @@ -215,6 +223,8 @@ extern void CkRegisterMigCtor(int chareIndex, int ctorEpIndex);
extern void CkRegisterGroupIrr(int chareIndex,int isIrr);
/** Register the chare baseIdx as a base class of the chare derivedIdx. */
extern void CkRegisterBase(int derivedIdx, int baseIdx);
/** Sets the ifNotThere policy of an EP **/
extern void CkRegisterIfNotThere(int epIdx, CkArray_IfNotThere policy);
#if CMK_CHARM4PY
extern void CkRegisterMainChareExt(const char *s, int numEntryMethods, int *chareIdx, int *startEpIdx);
extern void CkRegisterGroupExt(const char *s, int numEntryMethods, int *chareIdx, int *startEpIdx);
Expand Down
4 changes: 2 additions & 2 deletions src/ck-core/ckarray.C
Original file line number Diff line number Diff line change
Expand Up @@ -1234,12 +1234,12 @@ void CProxySection_ArrayBase::ckSend(CkArrayMessage* msg, int ep, int opts)
}
}

void CkSetMsgArrayIfNotThere(void* msg)
void CkSetMsgArrayIfNotThere(void* msg, CkArray_IfNotThere policy)
{
envelope* env = UsrToEnv((void*)msg);
env->setMsgtype(ForArrayEltMsg);
CkArrayMessage* m = (CkArrayMessage*)msg;
m->array_setIfNotThere(CkArray_IfNotThere_buffer);
m->array_setIfNotThere(policy);
}

void CkSendMsgArray(int entryIndex, void* msg, CkArrayID aID, const CkArrayIndex& idx,
Expand Down
2 changes: 1 addition & 1 deletion src/ck-core/ckarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class CProxySection_ArrayBase : public CProxy_ArrayBase
};

// Simple C-like API:
void CkSetMsgArrayIfNotThere(void* msg);
void CkSetMsgArrayIfNotThere(void* msg, CkArray_IfNotThere policy = CkArray_IfNotThere_buffer);
void CkSendMsgArray(int entryIndex, void* msg, CkArrayID aID, const CkArrayIndex& idx,
int opts = 0);
void CkSendMsgArrayInline(int entryIndex, void* msg, CkArrayID aID,
Expand Down
40 changes: 22 additions & 18 deletions src/ck-core/ckcallback.C
Original file line number Diff line number Diff line change
Expand Up @@ -317,19 +317,24 @@ void CkCallback::send(int length,const void *data) const
It takes the given message and handles it appropriately.
After the send(), this callback is finished and cannot be reused.
*/
void CkCallback::send(void *msg) const
void CkCallback::send(void *msg,int opts) const
{
// Variable is set with CK_MSG_IMMEDIATE when callback is pointing to an
// immediate entry method
int opts = 0;

#if CMK_CHARM4PY
if (isExtCallback) { // callback target is external
CkCallbackSendExt(*this, msg);
return;
}
#endif

// lookup an entry method's flags in table
auto ep = this->epIndex();
auto* entry = (ep >= 0) ? _entryTable[ep] : nullptr;
auto policy = CkArray_IfNotThere_buffer;
if (entry) {
policy = entry->ifNotThere;
opts |= (entry->isImmediate * CK_MSG_IMMEDIATE);
}

switch(type) {
case CkCallback::sendFuture:
CkSendToFuture(d.future.fut, msg);
Expand Down Expand Up @@ -367,69 +372,68 @@ void CkCallback::send(void *msg) const
case sendChare: //Send message to a chare
if (!msg) msg=CkAllocSysMsg();
if (d.chare.hasRefnum) CkSetRefNum(msg, d.chare.refnum);
CkSendMsg(d.chare.ep, msg, &d.chare.id);
CkSendMsg(d.chare.ep, msg, &d.chare.id, opts);
break;
case isendChare: //inline send-to-chare
if (!msg) msg=CkAllocSysMsg();
if (d.chare.hasRefnum) CkSetRefNum(msg, d.chare.refnum);
CkSendMsgInline(d.chare.ep, msg, &d.chare.id);
CkSendMsgInline(d.chare.ep, msg, &d.chare.id, opts);
break;
case sendGroup: //Send message to a group element
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
CkSendMsgBranch(d.group.ep, msg, d.group.onPE, d.group.id);
CkSendMsgBranch(d.group.ep, msg, d.group.onPE, d.group.id, opts);
break;
case sendNodeGroup: //Send message to a group element
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
if (_entryTable[d.group.ep]->isImmediate) opts = CK_MSG_IMMEDIATE;
CkSendMsgNodeBranch(d.group.ep, msg, d.group.onPE, d.group.id, opts);
break;
case isendGroup: //inline send-to-group element
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
CkSendMsgBranchInline(d.group.ep, msg, d.group.onPE, d.group.id);
CkSendMsgBranchInline(d.group.ep, msg, d.group.onPE, d.group.id, opts);
break;
case isendNodeGroup: //inline send-to-group element
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
if (_entryTable[d.group.ep]->isImmediate) opts = CK_MSG_IMMEDIATE;
CkSendMsgNodeBranchInline(d.group.ep, msg, d.group.onPE, d.group.id, opts);
break;
case sendArray: //Send message to an array element
if (!msg) msg=CkAllocSysMsg();
if (d.array.hasRefnum) CkSetRefNum(msg, d.array.refnum);
CkSetMsgArrayIfNotThere(msg);
CkSendMsgArray(d.array.ep, msg, d.array.id, d.array.idx.asChild());
CkSetMsgArrayIfNotThere(msg, policy);
CkSendMsgArray(d.array.ep, msg, d.array.id, d.array.idx.asChild(), opts);
break;
case isendArray: //inline send-to-array element
if (!msg) msg=CkAllocSysMsg();
if (d.array.hasRefnum) CkSetRefNum(msg, d.array.refnum);
CkSendMsgArrayInline(d.array.ep, msg, d.array.id, d.array.idx.asChild());
CkSetMsgArrayIfNotThere(msg, policy);
CkSendMsgArrayInline(d.array.ep, msg, d.array.id, d.array.idx.asChild(), opts);
break;
case bcastGroup:
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
CkBroadcastMsgBranch(d.group.ep, msg, d.group.id);
CkBroadcastMsgBranch(d.group.ep, msg, d.group.id, opts);
break;
case bcastNodeGroup:
if (!msg) msg=CkAllocSysMsg();
if (d.group.hasRefnum) CkSetRefNum(msg, d.group.refnum);
if (_entryTable[d.group.ep]->isImmediate) opts = CK_MSG_IMMEDIATE;
CkBroadcastMsgNodeBranch(d.group.ep, msg, d.group.id, opts);
break;
case bcastArray:
if (!msg) msg=CkAllocSysMsg();
if (d.array.hasRefnum) CkSetRefNum(msg, d.array.refnum);
CkBroadcastMsgArray(d.array.ep, msg, d.array.id);
CkSetMsgArrayIfNotThere(msg, policy);
CkBroadcastMsgArray(d.array.ep, msg, d.array.id, opts);
break;
#if !CMK_CHARM4PY
case bcastSection: {
if(!msg)msg=CkAllocSysMsg();
if (d.section.hasRefnum) CkSetRefNum(msg, d.section.refnum);
CkSectionInfo sinfo(d.section.sinfo);
CkSectionID secID(sinfo, d.section._elems, d.section._nElems, d.section.pelist, d.section.npes);
CkBroadcastMsgSection(d.section.ep, msg, secID);
CkBroadcastMsgSection(d.section.ep, msg, secID, opts);
break;
}
#endif
Expand Down
24 changes: 23 additions & 1 deletion src/ck-core/ckcallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ class CkCallback {
* It takes the given message and handles it appropriately.
* After the send(), this callback is finished and cannot be reused.
*/
void send(void *msg=NULL) const;
void send(void *msg=NULL,int opts=0) const;

/**
* Send this data, formatted as a CkDataMsg, back to the caller.
Expand Down Expand Up @@ -534,6 +534,28 @@ class CkCallback {
CkAbort("Tried to set a refnum on a callback not directed at an entry method");
}
}

// returns target EP's index (if one exists)
int epIndex(void) const {
switch (type) {
case isendChare:
case sendChare:
return d.chare.ep;
case isendGroup:
case sendGroup:
case isendNodeGroup:
case sendNodeGroup:
case bcastNodeGroup:
case bcastGroup:
return d.group.ep;
case isendArray:
case sendArray:
case bcastArray:
return d.array.ep;
default:
return -1;
}
}
};
//PUPbytes(CkCallback) //FIXME: write a real pup routine

Expand Down
8 changes: 0 additions & 8 deletions src/ck-core/cklocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,6 @@ class CkArrayMessage : public CkMessage
// Forward declarations
class CkArray;
class ArrayElement;
// What to do if an entry method is invoked on
// an array element that does not (yet) exist:
typedef enum : uint8_t
{
CkArray_IfNotThere_buffer = 0, // Wait for it to be created
CkArray_IfNotThere_createhere = 1, // Make it on sending Pe
CkArray_IfNotThere_createhome = 2 // Make it on (a) home Pe
} CkArray_IfNotThere;

/// How to do a message delivery:
typedef enum : uint8_t
Expand Down
6 changes: 6 additions & 0 deletions src/ck-core/register.C
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ void CkRegisterMainChareExt(const char *s, int numEntryMethods, int *chareIdx, i
}
#endif

void CkRegisterIfNotThere(int epIdx, CkArray_IfNotThere policy) {
if ((epIdx >= 0) && (!__registerDone || CMK_CHARM4PY)) {
_entryTable[epIdx]->ifNotThere = policy;
}
}

void CkRegisterBase(int derivedIdx, int baseIdx)
{
if (baseIdx!=-1)
Expand Down
5 changes: 4 additions & 1 deletion src/ck-core/register.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,17 @@ class EntryInfo {
/// Human-readable name of entry method, including parameters.
const char *name;

/// Policy for demand-creation entry methods
CkArray_IfNotThere ifNotThere;

EntryInfo(const char *n, CkCallFnPtr c, int m, int ci, bool ownsN=false) :
call(c), msgIdx(m), chareIdx(ci),
marshallUnpack(0)
#if CMK_CHARMDEBUG
,messagePup(0)
#endif
,traceEnabled(true), noKeep(false), isImmediate(false), isInline(false), inCharm(false), appWork(false),
ownsName(ownsN), name(n)
ownsName(ownsN), name(n), ifNotThere(CkArray_IfNotThere_buffer)
{
if (ownsName) initName(n);
#if CMK_CHARMDEBUG
Expand Down
13 changes: 13 additions & 0 deletions src/xlat-i/xi-Entry.C
Original file line number Diff line number Diff line change
Expand Up @@ -2459,6 +2459,19 @@ void Entry::genReg(XStr& str) {
str << " // REG: " << *this;
str << " " << epIdx(0) << ";\n";
if (isReductionTarget()) str << " " << epIdx(0, true) << ";\n";

const char* ifNot = nullptr;
if (isCreateHere()) ifNot = "CkArray_IfNotThere_createhere";
else if (isCreateHome()) ifNot = "CkArray_IfNotThere_createhome";

if (ifNot) {
str << " " << "CkRegisterIfNotThere(" << epIdx(0) << ", " << ifNot << ");\n";
if (isReductionTarget()) {
str << " " << "CkRegisterIfNotThere(" << epIdx(0, true)
<< ", " << ifNot << ");\n";
}
}

if (isConstructor()) {
if (container->isMainChare() && !isMigrationConstructor())
str << " CkRegisterMainChare(__idx, " << epIdx(0) << ");\n";
Expand Down

0 comments on commit 4fd8c4b

Please sign in to comment.