MultiSubscriber Context::subscribe()

in Cthulhu/include/cthulhu/ContextImpl.h [313:376]


MultiSubscriber Context::subscribe(
    const std::array<StreamID, N>& streamIDs,
    const std::function<void(const T&...)>& callback,
    const std::function<bool(const U&...)>& configCallback,
    MultiSubscriberOptions options) const {
  // Create Aligner
  auto aligner = details::alignerFromOptions(options.alignerType, std::move(options.alignerPtr));

  // Get Types and Validate
  std::array<uint32_t, N> types;
  details::SampleTypesStatic<T...>::template getTypes<0>(types);
  std::array<bool, N> basicStreams;
  for (unsigned long i = 0; i < N; ++i) {
    auto type = Framework::instance().typeRegistry()->findTypeID(types[i]);
    if (!type) {
      auto str = "Attempted to lookup unregistered typeID: " + std::to_string(types[i]);
      XR_LOGCE("Cthulhu", "{}", str);
      throw std::runtime_error(str);
    }
    basicStreams[i] = type->isBasic();
  }

  // Create Callbacks and Register in Aligner
  std::function<void(const std::vector<StreamSample>&, const T&...)> callbackAppended =
      [callback](const std::vector<StreamSample>&, const T&... args) -> void { callback(args...); };
  AlignerSampleCallback cb = details::generateAlignerCallback<0>(callbackAppended);
  aligner->setCallback(cb);
  if (configCallback != nullptr) {
    std::function<bool(const std::vector<StreamConfig>&, const U&...)> configCallbackAppended =
        [configCallback](const std::vector<StreamConfig>&, const U&... args) -> bool {
      return configCallback(args...);
    };
    AlignerConfigCallback ccb =
        details::generateAlignerConfigCallback<0>(configCallbackAppended, basicStreams);
    aligner->setConfigCallback(ccb);
  }

  // Get Streams from Registry and Load in Aligner
  std::vector<StreamIDView> streamIDsVec;
  streamIDsVec.reserve(N);
  for (unsigned long i = 0; i < N; i++) {
    StreamID streamID = applyNamespace(streamIDs[i]);
    auto type = Framework::instance().typeRegistry()->findTypeID(types[i]);
    StreamDescription desc{streamID, types[i]};
    auto si = Framework::instance().streamRegistry()->registerStream(desc);
    if (types[i] != si->description().type()) {
      // Type mismatch detected
      XR_LOGCW("Cthulhu", "Type mismatch detected [{}, {}]", types[i], si->description().type());
      return MultiSubscriber(streamIDsVec);
    }
    streamIDsVec.push_back(StreamIDView(si->description().id()));
    aligner->registerConsumer(si, i);
  }
  aligner->finalize();

  // Return Node
  if (ctx_ == nullptr) {
    const auto err = "Attempted to register multi subscriber against null context";
    XR_LOGCE("Cthulhu", "{}", err);
    throw std::runtime_error(err);
  }
  ctx_->registerSubscriber(streamIDsVec);
  return MultiSubscriber(streamIDsVec, std::move(aligner));
};