On Tue, Oct 6, 2015 at 7:43 PM, wm4 <[email protected]> wrote: > On Tue, 6 Oct 2015 12:41:13 +0200 > Hendrik Leppkes <[email protected]> wrote: > >> The emulation uses native InitOnce* APIs on Windows Vista+, and a >> lock-free/allocation-free approach using atomics and spinning for Windows XP. >> --- >> This is in preparation to use pthread_once for global static init functions, >> and eventually removing the global lock in avcodec_open2 >> >> compat/w32pthreads.h | 68 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 68 insertions(+) > > Somewhat related to this patch, we were discussing ways to deal with > w32thread_init(). > > Personally, I think we should not have to litter the code with > w32thread_init() calls. Nor should the user somehow have to make > sure that this function is somehow called implicitly, when calling > API functions which use threads. > > There are a few ways to handle this: > > 1. Don't handle it, but put it e.g. in avcodec_register_all(), and hope > the user calls it before calling other APIs which might require it. > 2. Call it from DllMain() only. This breaks static linking, or requires > special care if an application uses a statically linked libav. > 3. Make w32thread_init() thread-safe, and call it from all entrypoints > that need it, like pthread_cond_init() and pthread_once(). > > Choice 1. is pretty simple, but I think avcodec_register_all() should > eventually go away. And a lib should not require a global init function > in general. And there might be API in other sub-libs which require this > function to be called. It's also hard to guarantee that the API user > calls it in a safe way when no concurrent calls are possible. I think > this solution sucks. It's fragile and error-prone. > > Using a DllMain() is probably most elegant. It still needs to be put in > all the sub-libs. It breaks static linking, but nev says static linking > on Windows is insanity. Maybe that's true, but personally I think it's > not a good idea to silently break static linking. (Assuming it works > currently.) > > Choice 3. is my favorite. It could work like the XP-compatibility path > in pthread_once(). (In fact, pthread_once() can be reused for this > purpose.) Spinning is not a huge problem, because the protected code > only runs a bunch of GetProcAddress() call, and likely finishes very > quickly. Performance won't be affected much - it's only an additional > atomic operation in relatively rare calls like pthread_cond_init() > (pthread_once() will have to be avoided in performance-critical code > paths). This code would run on modern Windows releases too, but could > be disabled completely if compiling for Vista+ targets. > > Which way should we go? Suggestions and discussion welcome.
FWIW, i restructured my pthread_once emulation for (3), so the fallback spinning implementation can be used directly. See here: https://github.com/Nevcairiel/FFmpeg/commits/pthread_once It seems ok, i guess. Once the init is done, all it comes down to is one CAS call and a comparison of the result .. thats not much work. Both pthread_cond_init and pthread_once should only really be used in "init" type code, not in performance critical paths, so.. - Hendrik _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
