Hi,

I hesitated to reply at first, but I think it could still be helpful. I am not up-to-date regarding the current MITK development and its usage of CppMicroServices, so what I provide below might be outdated. Also, I am writing all of this from the top of my head relying on memories which are five years old by now.

MITK-devs, please correct me if I am wrong.

Every MITK "Module" is a CppMicroServices "Module". Note that "Module" in the CppMicroServices context is a legacy term which is been replaced by "Bundle" in newer versions.

A MITK module can register 0 or more services. It doesn't make sense to view a MITK module as a service (also the other way around doesn't make sense), unless you (in your own design) always register a service with a MITK module context and view them as conceptually equal. A module is a library (shared or static) which can consume and publish services (it can also provide other static resources like files, icons, etc.).

MITK (and CppMicroservices) Modules don't require an activator (I think). An activator allows you to register services at module load time, but you could do so from any place in your module later, by acquiring a module context with GetModuleContext().

You can view us::ModuleRegistry::GetModule(1) as a "hack" to get hold of the CppMicroServices module itself, which is always present. And yes, 1 should always be the CppMicroServices module.

The module ID is assigned on module load time, if I remember correctly. So it depends on the order of the shared libraries being loaded. Code using module 1's context to register or consumer services either does not have a module context itself (because it does not belong to a module), has a very special reasong to use the CppMicroServices module context, or is just doing it wrong.

The CppMicroServices module is loaded first by virtue of library dependencies. The dynamic loader of the OS takes care of that, because every other module has a dependency on the CppMicroservices library. On the other hand, I think I remember that MITK uses a special way to eagerly load the CppMicroServices module, because it might not have a hard dependency on any module right after startup.

Contexts:

- There is one context for each module loaded in the current process. An executable itself can be a module.

- The framework is the CppMicroServices environment. I think this is used in a rather loose sense

- It is possible to get the module context for any module loaded in the current processes. You have seen an example via us::ModuleRegistry::GetModule(1). This can be used to e.g. register a service "on behalf" of another module, which meaning making useĀ  of its module context outside of the module's code. It's not a common use case but enables certain patterns.

- The only code from modules executed by the CppMicroServices "framework" are the ModuleActivator Load and Unload functions. This happens during static initialization of the module, which itself happens by the dynamic loader, which to the best of my knowledge sequences all its actions in one thread. What modules themselves do, is up to them.

- As a module is basically a shared library with a module context given my the CppMicroServices framework, it doesn't make much sense to speak of instances. You can register multiple instances of the same service though.

ServiceTracker:

- Services are dynamic objects and can come and go during the lifetime of a process. A ServiceTracker simplifies the overhead which comes with the dynamic nature of services. You don't need to listen on service events yourself and you can use filters to filter on service properties.

- "service modified" is called when the properties a service was registered with are modified. The allow you to attach meta-information to service instances and later decide which service of many (potentially of the same type) is better suited for that particular consumer of a service.


Cheers,

Sascha


On 1/7/21 6:38 PM, Alex Melville wrote:
Hello,

I spent some time reading through the documentation on the CppMicroServices module, but a few things are still not clear to me,

General:
Note: By "MITK Module" I mean code that resides in the Modules/ folder of a MITK application, and is created by MITK_CREATE_MODULE(...). By CppMicroServices Module I mean what you would access via us::ModuleRegistry::GetModule(.... - Can I assume that the CppMicroServices "Module" is the same as MITK "Module"? Or are these two different concepts that share the same name? - Is every MITK module always a service? In my application I have one module that seems to not be a service. It has no activator code, and seems to be just an ordinary dll with header and cpp files.
- Is every service a MITK module?

GetModule(1):
- In my code I see us::ModuleRegistry::GetModule(1)->GetModuleContext(); occasionally, I have checked which module GetModule(1) returns and it appears to be CppMicroServices.
- Can I rely on Module 1 to always be CppMicroServices?
- What determines the ID of this module?

I would guess that code like this is getting some "global context" that MITK resides in, is this correct? The code then goes on to register additional services in that context. - If my guess is correct, is there a cleaner way to accomplish this, or is this the recommended method?

Also, if the CppMicroServices module is a MITK module and also a manager of MITK modules, wouldn't that be a chicken and the egg situation? How is it itself loaded before the microservices microservice is loaded? I'm a bit curious to hear how this is managed.

Contexts:
- How many contexts are there? Exactly one on the entire PC, one per application / executable, or is there an unlimited number of contexts? - The documentation says "A module's execution context within the framework" -- what is the "framework"? Is this referring to some other class that exists as an instance that's created at some point when an MITK application starts up? - The documentation for the module context says it "can be used by the caller to act on behalf of this module", what does that mean? To me it implies that there is some global state linking modules together, or that modules are running on separate thread(s) from each other, but I have not seen this in the modules I've used, does anyone have an example of this? - Why would a caller need to act on behalf of a module, beyond the publicly available functions that the module's classes expose? Maybe our application is not making full use of this feature, because it seems like primarily we just create instances of objects from modules and use them like standard C++ objects, it sounds like there's some kind of hidden "module state" feature that I'm not aware of.
- Is it possible to start more than one instance of a module or service?

usServiceTracker:
- What exactly is being tracked on the service by this class? Is this tracker class just here to manage the lifetime of an interface to a service? - There appears to be a "service modified" event, but what does it mean to "modify" a service? Is this event fired when any data managed by a service changes, or does this event get fired for "higher level" events like a service getting stopped or started?

Thanks,

- Alex


_______________________________________________
mitk-users mailing list
mitk-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mitk-users
_______________________________________________
mitk-users mailing list
mitk-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mitk-users

Reply via email to