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

Reply via email to