AMDG On 01/24/2018 07:21 AM, Jean-Louis Leroy via Boost wrote:
<snip>
Can't you just rearrange it to: ... struct _YOMM2_SPEC { static RETURN_T body ARGS; }; ... register_spec<> init(); }} inline RETURN_T _YOMM2_NS::_YOMM2_SPEC::body ARGS
This wouldn't work as is, because _YOMM2_NS generates a new namespace name each time it is called (using __COUNTER__) but I found out about BOOST_PP_SUB and changed _YOMM2_NS so it can re-generate a previous namespace. So now YOMM2_END is gone.
A better way is to define an implementation macro that takes the namespace as a parameter, and then force __COUNTER__ to be expanded once by the outer macro. (BOOST_PP_SUB has a pretty low upper maximum.)
<snip>
- update_methods looks like it's totally thread-unsafe. You can probably get away with this if you only call it at the beginning of main, but it seems quite dangerous if you load or unload shared libraries.
That's a complex question.
For starters, is dlopen thread safe? GNU dlopen is explicitly documented as "MT-Safe", but this SunOS page https://docs.oracle.com/cd/E26502_01/html/E26507/chapter3-7.html does not say anything on the subject. And then there are bug reports circulating about dlopen in multi-threadec context.
And what of dlclose? Better make sure that a thread does not call dlclose while another is still executing the library's code. Or that each thread that uses the library calls dlopen itself (and increments the library's ref count).
That's no different from normal functions. My opinion is that dlopen/dlclose should be exactly as safe for multimethods as they are for normal functions.
In the light of this, I have so far left it to "the application" to manage its calls to dlopen, dlclose and update_methods.
But this is just the beginning. Adding a mutex to serialize calls to update_method (and the static ctors and dtors that are generated by the macros) is not enough, because a thread may be executing the method dispatch code while update_methods is running. I would need a read/write mutex, with the dispatch code acquiring a read lock until it has fetched the pointer to the appropriate function. But that would be too penalizing.
It might be better to assume that rebuilding the tables is rare. Then you can build a completely new table and swap it in atomically. Assumptions required for validity: - No call that would match any new overload is made until after update_methods returns. - All calls into the dll have completed before it is unloaded.
I wonder if Pirkelbauer, Solodkyy and Stroustrup addressed this problem when they worked on open methods. Their paper mentions dynamic loading but it doesn't say much except that it's important to support it. I'll ask Solodkyy - we exchanged emails in the past.
In Christ, Steven Watanabe