Closed fran6co closed 1 month ago
@fran6co Does external services work for you? It allows you to declare services, but the container will let you set the instance for it.
If different parts of your application needs a different pipeline, then would external services + container forking works for your use case?
Not really, because I have multiple services with the same type but that belong to different sources in the pipeline. If I could add a runtime map based on a string then each could query for the correct one. I was thinking a way to add the std::hash of a runtime variable to the type is hash used to store the service
You can create many services for the same type like this:
// Three mappings for type dep
struct dependency1_service : kgr::single_service<dep> {};
struct dependency2_service : kgr::single_service<dep> {};
struct dependency3_service : kgr::single_service<dep> {};
Then use the right dependency at the right parts:
struct pipeline_part1_service : kgr::single_service<part1, kgr::dependency<dependency1_service>> {};
struct pipeline_part2_service : kgr::single_service<part2, kgr::dependency<dependency2_service>> {};
struct pipeline_part3_service : kgr::single_service<part3, kgr::dependency<dependency3_service>> {};
If you have a known amount of parts (or types of part) it should work. This is really because you can create multiple service type for one type, then use those services as dependency to others.
If on the other hand you have a unknown or a dynamic amount of parts, where the amount of types are unknown at any point except runtime, you could create your own runtime mapping with strings and hash, then pass that container to a custom service definition that picks the right one when building your service. It's quite a bit more involved though.
Yeah, the problem is that the pipeline is dynamically constructed so I can't do that. What we have now is a std::map container with the services as a poor man's id and I wanted to replace it with kangaru. I was hoping for an easy way to achieve this
If you don't load pipepile parts from dynamic libraires you should be able to create as much services for a type as the amount of types that needs it. I don't think assembling the pipeline at runtime blocks that. Maybe you can provide me a short code snippet that reproduced what you're trying to do?
It's very simplified, but it would be something like this. Have some mapped_ variants that take something that can be std::hash.
struct CameraService : kgr::shared_service<Camera> {};
kgr::container container;
for (const auto& [sourceId, source] : sources) {
auto camera = container.mapped_shared_service<CameraService>(sourceId, other_args_to_init_camera);
// Wire the camera to pipeline to pass images to it
}
// .... do other things
// Start the cameras
for (const auto& [sourceId, source] : sources) {
container.mapped_invoke(sourceId, [](std::shared_ptr<Camera> camera){
camera->start();
});
}
You can achieve this example code with a forked container in a map:
std::unordered_map<std::string, kgr::container> mapped;
for (const auto& [sourceId, source] : sources) {
auto fork = container.fork();
container.emplace<CameraService>(other_args_to_init_camera);
mapped.emplace_or_assign(sourceId, std::move(fork));
// Wire the camera to pipeline to pass images to it
}
// .... do other things
// Start the cameras
for (const auto& [sourceId, source] : sources) {
mapped.at(sourceId).invoke([](std::shared_ptr<Camera> camera) {
camera->start();
});
}
Unless this code don't represent what you're trying to do well enough, it should be achieving what you're looking for.
That might work, I didn't think about forking containers. Thanks
Let me know how it goes! If it works well enough for your needs, feel free to close the issue after you verified that it work 😄
It's useful to map services using runtime values, for example I have an application that creates media pipelines and each pipeline can be created at runtime and each has their own services. Mapping right now is done via templating, allowing to use strings or some other values that can be hashed would allow for this.