diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index dcb625b3d..7e89dc28e 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -520,6 +520,7 @@ protected: TLSDataContainer(); virtual ~TLSDataContainer(); + void gatherData(std::vector &data) const; #if OPENCV_ABI_COMPATIBILITY > 300 void* getData() const; void release(); @@ -546,9 +547,20 @@ public: inline ~TLSData() { release(); } // Release key and delete associated data inline T* get() const { return (T*)getData(); } // Get data assosiated with key + // Get data from all threads + inline void gather(std::vector &data) const + { + std::vector &dataVoid = reinterpret_cast&>(data); + gatherData(dataVoid); + } + private: virtual void* createDataInstance() const {return new T;} // Wrapper to allocate data by template virtual void deleteDataInstance(void* pData) const {delete (T*)pData;} // Wrapper to release data by template + + // Disable TLS copy operations + TLSData(TLSData &) {}; + TLSData& operator =(const TLSData &) {return *this;}; }; /** @brief Designed for command line parsing diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 743341daf..337414918 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1034,7 +1034,7 @@ class TlsStorage public: TlsStorage() { - tlsSlots = 0; + tlsSlots.reserve(32); threads.reserve(32); } ~TlsStorage() @@ -1077,15 +1077,27 @@ public: size_t reserveSlot() { AutoLock guard(mtxGlobalAccess); - tlsSlots++; - return (tlsSlots-1); + + // Find unused slots + for(size_t slot = 0; slot < tlsSlots.size(); slot++) + { + if(!tlsSlots[slot]) + { + tlsSlots[slot] = 1; + return slot; + } + } + + // Create new slot + tlsSlots.push_back(1); + return (tlsSlots.size()-1); } // Release TLS storage index and pass assosiated data to caller void releaseSlot(size_t slotIdx, std::vector &dataVec) { AutoLock guard(mtxGlobalAccess); - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); for(size_t i = 0; i < threads.size(); i++) { @@ -1096,15 +1108,14 @@ public: threads[i]->slots[slotIdx] = 0; } } - // If we removing last element, decriment slots size to save space - if(tlsSlots-1 == slotIdx) - tlsSlots--; + + tlsSlots[slotIdx] = 0; } // Get data by TLS storage index void* getData(size_t slotIdx) const { - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); ThreadData* threadData = (ThreadData*)tls.GetData(); if(threadData && threadData->slots.size() > slotIdx) @@ -1113,10 +1124,24 @@ public: return NULL; } + // Gather data from threads by TLS storage index + void gather(size_t slotIdx, std::vector &dataVec) + { + AutoLock guard(mtxGlobalAccess); + CV_Assert(tlsSlots.size() > slotIdx); + + for(size_t i = 0; i < threads.size(); i++) + { + std::vector& thread_slots = threads[i]->slots; + if (thread_slots.size() > slotIdx && thread_slots[slotIdx]) + dataVec.push_back(thread_slots[slotIdx]); + } + } + // Set data to storage index void setData(size_t slotIdx, void* pData) { - CV_Assert(pData != NULL); + CV_Assert(tlsSlots.size() > slotIdx && pData != NULL); ThreadData* threadData = (ThreadData*)tls.GetData(); if(!threadData) @@ -1131,7 +1156,11 @@ public: } if(slotIdx >= threadData->slots.size()) - threadData->slots.resize(slotIdx+1); + { + AutoLock guard(mtxGlobalAccess); + while(slotIdx >= threadData->slots.size()) + threadData->slots.push_back(NULL); + } threadData->slots[slotIdx] = pData; } @@ -1139,7 +1168,7 @@ private: TlsAbstraction tls; // TLS abstraction layer instance Mutex mtxGlobalAccess; // Shared objects operation guard - size_t tlsSlots; // TLS storage counter + std::vector tlsSlots; // TLS keys state std::vector threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup }; @@ -1159,6 +1188,11 @@ TLSDataContainer::~TLSDataContainer() CV_Assert(key_ == -1); // Key must be released in child object } +void TLSDataContainer::gatherData(std::vector &data) const +{ + getTlsStorage().gather(key_, data); +} + void TLSDataContainer::release() { std::vector data;