| 111 | } |
| 112 | |
| 113 | object get( const object &key ) |
| 114 | { |
| 115 | // we must hold the GIL when entering LRUCache<object, object>::get() |
| 116 | // or any other of our base class' methods, because they manipulate |
| 117 | // boost::python::objects, which in turn use the python api. in addition, |
| 118 | // LRUCacheGetter enters python, giving us another reason to need the |
| 119 | // GIL. things are complicated slightly by the fact that the python code |
| 120 | // executed by LRUCacheGetter may release the GIL, either explicitly or |
| 121 | // because the interpreter does that from time to time anyway. this can |
| 122 | // allow another thread to make a call to get(), potentially with the same |
| 123 | // key as was passed to the current call. this would lead to deadlock - |
| 124 | // the first call doing the caching waits for the GIL to continue, |
| 125 | // and the second call holds the GIL and waits for the caching to be |
| 126 | // complete. |
| 127 | // |
| 128 | // the code below avoids this, by ensuring only one thread can be in |
| 129 | // LRUCache<object, object>::get(), at any given time, and by releasing |
| 130 | // the GIL while it waits for m_getMutex. this allows the first thread |
| 131 | // to finish caching (because it can reacquire the GIL), at which point |
| 132 | // it will release m_getMutex, allowing the second thread to go about |
| 133 | // its business. |
| 134 | // |
| 135 | // while this serialisation may seem inefficient, it's less of a big |
| 136 | // deal because all python execution is serialised anyway. |
| 137 | // |
| 138 | // see test/IECore/LRUCache.py, in particular testYieldGILInGetter(). |
| 139 | |
| 140 | std::unique_lock<Mutex> lock( m_getMutex, std::defer_lock ); |
| 141 | { |
| 142 | IECorePython::ScopedGILRelease gilRelease; |
| 143 | lock.lock(); |
| 144 | } |
| 145 | return LRUCache<object, object>::get( key ); |
| 146 | } |
| 147 | |
| 148 | private : |
| 149 |
no test coverage detected