kulst commented on PR #627: URL: https://github.com/apache/celix/pull/627#issuecomment-2076589287
I wanted to give a little update on my progress :) I was able to get your POC running with the latest master branch. Only some small changes were necessary. However there were some error messages I could track down to filter compilation. In `celix_version_parse` "Invalid version component" gets logged. I do not know if this is intentional. I also made some progress towards the API and wanted to share my thoughts. I heavily thought about the I think most important invariant. `celix_bundle_context_t` (and all other framework objects) must not be used when the Bundle is stopped. From my point of view this means that the activator must invalidate all Framework objects that are floating around. **POC approach using Weak and Arc** In the POC I think this was tried to achieve by using `std::sync::Weak` pointers. However I am not sure if this is entirely sound. For example when building the Servicetracker we upgrade the `Weak` to an `Arc`. What happens if this is done in another thread and immediately after upgrading the `Weak` and before actually tracking the service the bundle gets stopped and destroyed. I think we would have a use after free situation here. **Approach using Arc<Mutex<Option<T>>>** So I thought about a solution having two types both storing `Arc<Mutex<Option<*mut celix_bundle_context>>>`. One type is private to the library and invalidates each `celix_bundle_context_t` simply by taking it out of the `Option` when the bundle gets stopped. The other type is public with a private implementation and uses the stored `celix_bundle_context_t` as long as it is available. With this solution the whole API of the `PublicCelixBundleContext` would always return a `Result<T,E>`. Also for each access there is additional locking necessary because of the `Mutex`. Then I thought about using lifetimes. The problem with lifetimes is that they need a scope where the Owner lifes. But we have two (four) functions that are called after each other from the framework. The compiler does not know that these are called one after another. Also we convert the `Activator` to a raw pointer. There do no lifetimes exist for raw pointers. So what can we do about it? **First lifetime approach: Static services** The framework provides the `celix_bundle_context_t` in each of the four functions. We could now create a `BundleContext` in the start function from it and store it in the activator. The library user could now get a `&BundleContext`. During the start function the user could register services, track services and so on with it. This can be also stored in the activator. However he can not create a new thread with it that outlives the start function. This is because the `&BundleContext` has a non-static lifetime. In the stop function the user simply takes its user data from the activator and undos what he did in the start function. Overall this can only be used for static handling of services. **Second lifetime approach: Spawn a thread** My second approach is to just spawn a thread in the start function and join it in the stop function. By this we get a scope that lifes from start to stop. We send the created `BundleContext` into the thread but also here we only provide the user a `&BundleContext`. Also here the user can not spawn thread that outlive the scope. But as the scope is from start to stop it is possible to create threads that also live as long. In the stop function we signal the thread that it must stop and join it. The user is responsible to make sure the thread stops. With this approach we do not need to store user data in the activator. We simply put a `JoinHandle` there to join it and the `Sender` to signal the thread it must stop. Overall this method is suited for static services but dynamic services as well. In the following repository I show how I think this could look like: https://github.com/kulst/celix_rust_test I hope I was able to make everything clear to you. I would be glad to get some feedback, to know if I am on the right way. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@celix.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org