Learn » Tutorial » Learning about callbacks

// Forward declaration for the active message handler
static void getCallbackHandler(Callback<int> cb);

// An active message handler used as the target for a callback
static void callbackHandler(int data) {
  NodeType const cur_node = ::vt::theContext()->getNode();
  ::fmt::print("{}: triggering active message callback: {}\n", cur_node, data);
}

// An active message handler used as the target for a callback
static void callbackBcastHandler(int data) {
  NodeType const cur_node = ::vt::theContext()->getNode();
  ::fmt::print(
    "{}: triggering active message callback bcast: {}\n", cur_node, data
  );
}

// Tutorial code to demonstrate using a callback
static inline void activeMessageCallback() {
  NodeType const this_node = ::vt::theContext()->getNode();
  NodeType const num_nodes = ::vt::theContext()->getNumNodes();
  (void)num_nodes;  // don't warn about unused variable

  /*
   * Callbacks allow one to generalize the notion of an endpoint with a abstract
   * interface the callee can use without changing code. A callback can trigger
   * a lambda, handler on a node, handler broadcast, handler/lambda with a
   * context, message send of virtual context collection (element or broadcast)
   */

  if (this_node == 0) {
    // Node sending the callback message to, which shall invoke the callback
    NodeType const to_node = 1;
    // Node that we want to callback to execute on
    NodeType const cb_node = 0;

    // Example of active message handler callback with send node
    {
      auto cb = ::vt::theCB()->makeSend<callbackHandler>(cb_node);
      ::vt::theMsg()->send<getCallbackHandler>(Node{to_node}, cb);
    }

    // Example of active message handler callback with broadcast
    {
      auto cb = ::vt::theCB()->makeBcast<callbackBcastHandler>();
      ::vt::theMsg()->send<getCallbackHandler>(Node{to_node}, cb);
    }
  }
}

// Message handler for to receive callback and invoke it
static void getCallbackHandler(Callback<int> cb) {
  auto const cur_node = ::vt::theContext()->getNode();
  ::fmt::print("getCallbackHandler: triggered on node={}\n", cur_node);

  // Send the callback a message
  cb.send(29 + cur_node);
}