On Wed, Jul 30, 2014 at 2:02 PM, Klaim - Joël Lamotte
On Wed, Jul 30, 2014 at 11:27 AM, Rob Stewart
wrote: I was suggesting weak_ptr (wrapped inside something that looks like a std::function<>) so that the user decides if or not he wants to check if the library is still loaded before using the function. But personally I wouldn't.
I'm still at a loss to understand what you'd actually want get_symbol() to return to solve your use cases.
If the returned object holds a shared_ptr to the library, the library can't be unloaded until all such objects have been destroyed or until they are told to release their ref count. That is safer, however. Holding a weak_ptr instead implies a runtime check on each invocation, but doesn't prevent unloading the library. However, you've said you wouldn't use the weak_ptr, so I'm missing something.
Very sorry, I was not clear at all and I also mixed up details about the get_symbol() return type (it's not a callable but the call result, I mixed up this part).
Let me try again:
In most use cases I had, the lifetime of a plugin was necessarily separate from it's usage: I would have a way to say that the plugin must be unloaded and that would invalidate all code trying to use it. This is because unloading-the-plugin-event is then propagated through the users systems and they have to do the cleaning work (that is, destroy all accesses to the plugin). Once the plugin is unloaded, in my use cases, we want it to not be usable at all anymore, explicitly. And we want the whole application to fail early if access to the unloaded plugin is tried.
Therefore, I agree that get_symbol() should return a smart pointer, but containing a weak_ptr instead of a shared_ptr, so that the symbol lifetimes don't force the plugin to still be loaded when we wanted it not to. Once the plugin is unloaded (the shared_ptr to it is destroyed), when the returned smart pointer is accessed, the weak_ptr would test locking and would, by default, throw an exception. Personally I would prefer the default behaviour in this case to be overwriteable, so that I can for example just log and call terminate(), then change this behaviour in the shiped product.
In some specific cases I would want to test if the symbol is valid before using it (but in most cases I had, I don't want to because it should fail at this point - it's what I meant by "but personally I wouldn't").
Centralization or not of the plugins lifetime is let to the user, this part was more noise than argument. The user can or not share the plugin lifetime between different systems, but I disagree that returns of the symbols should force the lifetime of the plugin to be longer than necessary.
Am I more clear?
Maybe two different get_symbol() functions could return either a "safe" (managing a shared_ptr to the plugin) or "unsafe" (managing a weak_ptr to the plugin and throwing an exception by default when it's not available and we try to use the data) smart pointer? Maybe that way our different use cases would be all solved.
I think you can achieve any behavior you described with the interface Peter suggested, can't you? // p1 locks lib from being unloaded shared_ptr< foo > p1 = get_symbol< foo >(lib, "foo"); // p2 does not lock lib from being unloaded and is testable weak_ptr< foo > p2 = get_symbol< foo >(lib, "foo"); // p3 does not lock lib from being unloaded and crashes if used after lib is unloaded foo* p3 = get_symbol< foo >(lib, "foo").get(); Personally, I'd prefer get_symbol to return something immediately usable, i.e. shared_ptr. I'd also like to emphasize that it should return a pointer and not a function since the symbol may be data. Just my 2 cents.