gwaldron / osgearth

3D Maps for OpenSceneGraph / C++14
https://www.pelicanmapping.com/home-1/opensource
Other
1.51k stars 779 forks source link

Gate deadlock #2540

Closed ghlk12345 closed 4 months ago

ghlk12345 commented 5 months ago

osgEarth Version (required): master

need bug fix file: Threading. If we request uri resource in one thread, then node reader implement use the same uri path construct URI in the same thread, the new URI's doRead func construct gatelock will be deadlock。for example, the ReaderWriterGLTF read a B3DM file.

I have a solution

template<typename T>
class Gate
{
public:
    Gate() { }

    inline void lock(const T& key) {
        std::unique_lock<std::mutex> lock(_m);
        for (;;) {
            auto i = _keys.emplace(key, std::this_thread::get_id());
            if (i.second == true || i.first->second == std::this_thread::get_id()) // insert successful or same thread call
                return;
            _unlocked.wait(lock);
        }
    }

    inline void unlock(const T& key) {
        std::unique_lock<std::mutex> lock(_m);
        _keys.erase(key);
        _unlocked.notify_all();
    }

private:
    std::mutex _m;
    std::condition_variable_any _unlocked;
    std::unordered_map<T, std::thread::id> _keys;
};
gwaldron commented 5 months ago

Where are you seeing this happen? Seems like this would only happen if you try to load the same file recursively...?

ghlk12345 commented 5 months ago

Where are you seeing this happen? Seems like this would only happen if you try to load the same file recursively...?

OSGEarth have some situation to make it happen. Forexample, the 3dtiles's layer read layer's json file , then it will use URI read all things when layer open, include b3dm file. Then it will read b3dm file recursive, the first by 3dtiles layer, the second by gltf plugin