-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multi-Threading support for Corrade::PluginManager? #65
Comments
... my current workaround: duplicate the logic from (The duplication is required since Not ideal, but works for me. |
The global storage is needed for static plugins -- at app startup these need to be "registered" so any plugin manager instance can see them. This is done before After that, there's definitely a bunch of problems -- when the manager gets instantiated, it "steals" static plugins from the global storage and then adds dynamic plugins to the global storage as well. This is needed in order to properly support inter-plugin dependencies, in particular plugins with different interface can depend on each other and there needs to be some manager responsible for loading them. This part could be done thread-local without problems, I think -- providing that Windows' For "stealing" static plugins from the non-thread-local storage -- these would be all just reads, so I don't see a problem there.
It's definitely not out of scope, no -- and reimplementing all that on your side sounds too much like a nuclear solution to me :D I'll see what I can do in the next weeks. |
I couldn't find an explicit mention that the calls are thread-safe, but there are unofficial statements that they are: |
Soo... I finally had a chance to look at this. One part of this is solved in ddd57b1 and 491ff17 (Aug 31), where the static plugin registration is made allocation-less and thus practically failproof, and the global plugin storage file-local. The static plugin registration data is only being read from after, so there won't be no data races. With that in place, the only remaining thing to do (as far as I thought) was slapping
Looking at man pages, |
I found some people reporting thread safety problems in glibc with For example: http://lua-users.org/lists/lua-l/2015-04/msg00010.html This looks like an interesting problem. I'd have time on the weekend to look at it - if you don't solve it sooner ;-) Could you share your test case? |
One further note about the pthread theory: since you are already testing with multiple threads (probably using |
Here's the whole thing: https://github.com/mosra/corrade/compare/pluginmanager-threadlocal . I'm kinda inclined to merge it as-is, unless you come up with a better solution :) CI passes because I added Additionally -- since you have a real use case for this, could you give this branch a spin in your project (with manager instances being used in multiple threads)? I think this is all you need, but ... one never knows for sure :) |
At first glance, https://github.com/bminor/glibc/blob/5a82c74822d3272df2f5929133680478c0cfb4bd/elf/dl-open.c#L541 As expected, the logic is quite complex, so I'll have to dig deeper. |
Ok, I think there is no problem in https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual#non-instrumented-code So basically you'd have to compile I'll test your branch in my setup next. |
Everything seems to work from in my setup. I also tested with TSAN and it didn't find any issues. Quick related question: I'm currently assuming that the Probably preprocessing my image dataset and converting everything to some GPU-friendly image format would be the best solution, but I was hoping to avoid that ;-) |
Maybe you could use |
@williamjcm Thanks for the suggestion - could you explain what So probably I would need some sort of reference counting system where the main thread can signal that it is done with an image - and the loader thread can destroy the ImageData and Importer instances. I guess there is no other way. [Also, the image dataset is way too big to be able to hold everything in memory, so I need to load/use/unload it file-by-file, as fast as possible.] Anyway, my question probably belongs somewhere else than in this issue ;-) |
Do you do any processing on the images before uploading them to the GPU ? If not, that's how the workflow would basically look like:
However, I can't give code examples, because I work on proprietary software, and even if I could share code, I only load stuff synchronously. So, the best advice I can give is to check the docs for ResourceManager and AbstractResourceLoader. 😅 |
Right, that was my suspicion too. Yes, I think the suppression list is more practical. Will add an explanatory comment there and put this to master.
This is explicitly disallowed -- not so much because some custom deleter could be non-thread-safe, but rather because unloading a plugin would mean the deleter is a dangling pointer (dangling function pointers? fun!). It's only documented for plugin implementers right now, but I think it makes sense to document that for plugin users (and add sanity asserts to all the
In short, transferring ownership of the In a not-so-distant future I'll be looking back at zero-copy importers (mosra/magnum#240), those will add a dependency between a memory blob the assets are imported from and the |
Thanks @mosra, that clears everything up and makes my design much simpler 👍 |
This is now in master as d6e0ef0, and on magnum side the data dependencies were clarified (and deleters checked) in mosra/magnum@84fc685. I guess that's all to be done here, right? :) |
From my side yes ;) Thanks for following up on this! |
Use case: I want to load textures using the
Magnum::Trade
subsystem in a background thread. Basically, I have to load one texture per rendered frame, that's why I would like to minimize/hide I/O and decoding time.Problem: I can't find a clean solution. Separate
Corrade::PluginManager::Manager
instances do not work, since they act upon a global, staticGlobalPluginStorage
without locking. The handyAnyImageImporter
plugin even loads other plugins at runtime, which further complicates things.Do you think it might be feasible to either introduce some locking on the global plugin storage or to completely decouple the
Manager
instances, i.e. remove any global state?At least under Linux
dlopen()
anddlclose()
seem to be robust against multiple calls, even from separate threads as they do locking and refcounting internally. I haven't looked at other platforms yet...I can also understand if you say this is out of scope for
Corrade
. Probably I'd have to use a separate image loading library then...The text was updated successfully, but these errors were encountered: