void ServiceDependency::setupCallbacks()

in libs/framework/include/celix/dm/ServiceDependency_Impl.h [486:559]


void ServiceDependency<T,I>::setupCallbacks() {
    int(*cset)(void*, void *, const celix_properties_t*) {nullptr};
    int(*cadd)(void*, void *, const celix_properties_t*) {nullptr};
    int(*crem)(void*, void *, const celix_properties_t*) {nullptr};

    if (setFp || setFpUsingSharedPtr) {
        cset = [](void* handle, void* rawSvc, const celix_properties_t* rawProps) -> int {
            int rc = 0;
            auto dep = (ServiceDependency<T,I>*) handle;
            if (dep->setFp) {
                rc = dep->invokeCallback(dep->setFp, rawProps, rawSvc);
            }
            if (dep->setFpUsingSharedPtr) {
                auto svcId = dep->setService.second ? dep->setService.second->getAsLong(celix::SERVICE_ID, -1) : -1;
                std::weak_ptr<I> replacedSvc = dep->setService.first;
                std::weak_ptr<const celix::Properties> replacedProps = dep->setService.second;
                auto svc = std::shared_ptr<I>{static_cast<I*>(rawSvc), [](I*){/*nop*/}};
                auto props = rawProps ? std::make_shared<const celix::Properties>(celix::Properties::wrap(rawProps)) : nullptr;
                dep->setService = std::make_pair(std::move(svc), std::move(props));
                dep->setFpUsingSharedPtr(dep->setService.first, dep->setService.second);
                dep->waitForExpired(replacedSvc, svcId, "service pointer");
                dep->waitForExpired(replacedProps, svcId, "service properties");
            }
            return rc;
        };
    }
    if (addFp || addFpUsingSharedPtr) {
        cadd = [](void* handle, void *rawSvc, const celix_properties_t* rawProps) -> int {
            int rc = 0;
            auto dep = (ServiceDependency<T,I>*) handle;
            if (dep->addFp) {
                rc = dep->invokeCallback(dep->addFp, rawProps, rawSvc);
            }
            if (dep->addFpUsingSharedPtr) {
                auto props = std::make_shared<const celix::Properties>(celix::Properties::wrap(rawProps));
                auto svc = std::shared_ptr<I>{static_cast<I*>(rawSvc), [](I*){/*nop*/}};
                auto svcId = props->getAsLong(celix::SERVICE_ID, -1);
                dep->addFpUsingSharedPtr(svc, props);
                dep->addedServices.template emplace(svcId, std::make_pair(std::move(svc), std::move(props)));
            }
            return rc;
        };
    }
    if (removeFp || removeFpUsingSharedPtr) {
        crem = [](void* handle, void *rawSvc, const celix_properties_t* rawProps) -> int {
            int rc = 0;
            auto dep = (ServiceDependency<T,I>*) handle;
            if (dep->removeFp) {
                rc = dep->invokeCallback(dep->removeFp, rawProps, rawSvc);
            }
            if (dep->removeFpUsingSharedPtr) {
                auto svcId = celix_properties_getAsLong(rawProps, celix::SERVICE_ID, -1);
                auto it = dep->addedServices.find(svcId);
                if (it != dep->addedServices.end()) {
                    std::weak_ptr<I> removedSvc = it->second.first;
                    std::weak_ptr<const celix::Properties> removedProps = it->second.second;
                    dep->removeFpUsingSharedPtr(it->second.first, it->second.second);
                    dep->addedServices.erase(it);
                    dep->template waitForExpired(removedSvc, svcId, "service pointer");
                    dep->template waitForExpired(removedProps, svcId, "service properties");
                }
            }
            return rc;
        };
    }

    celix_dmServiceDependency_setCallbackHandle(this->cServiceDependency(), this);
    celix_dm_service_dependency_callback_options_t opts;
    std::memset(&opts, 0, sizeof(opts));
    opts.setWithProps = cset;
    opts.addWithProps = cadd;
    opts.removeWithProps = crem;
    celix_dmServiceDependency_setCallbacksWithOptions(this->cServiceDependency(), &opts);
}