TLS keys leak fix;
Disables TLS copy constructor and operator, as they can lead to errors and reservation of too much keys in TLS storage; gather method was added to TLS to gather data from all threads;
This commit is contained in:
parent
9533982729
commit
aa485ccd75
@ -520,6 +520,7 @@ protected:
|
|||||||
TLSDataContainer();
|
TLSDataContainer();
|
||||||
virtual ~TLSDataContainer();
|
virtual ~TLSDataContainer();
|
||||||
|
|
||||||
|
void gatherData(std::vector<void*> &data) const;
|
||||||
#if OPENCV_ABI_COMPATIBILITY > 300
|
#if OPENCV_ABI_COMPATIBILITY > 300
|
||||||
void* getData() const;
|
void* getData() const;
|
||||||
void release();
|
void release();
|
||||||
@ -546,9 +547,20 @@ public:
|
|||||||
inline ~TLSData() { release(); } // Release key and delete associated data
|
inline ~TLSData() { release(); } // Release key and delete associated data
|
||||||
inline T* get() const { return (T*)getData(); } // Get data assosiated with key
|
inline T* get() const { return (T*)getData(); } // Get data assosiated with key
|
||||||
|
|
||||||
|
// Get data from all threads
|
||||||
|
inline void gather(std::vector<T*> &data) const
|
||||||
|
{
|
||||||
|
std::vector<void*> &dataVoid = reinterpret_cast<std::vector<void*>&>(data);
|
||||||
|
gatherData(dataVoid);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void* createDataInstance() const {return new T;} // Wrapper to allocate data by template
|
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
|
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
|
/** @brief Designed for command line parsing
|
||||||
|
@ -1034,7 +1034,7 @@ class TlsStorage
|
|||||||
public:
|
public:
|
||||||
TlsStorage()
|
TlsStorage()
|
||||||
{
|
{
|
||||||
tlsSlots = 0;
|
tlsSlots.reserve(32);
|
||||||
threads.reserve(32);
|
threads.reserve(32);
|
||||||
}
|
}
|
||||||
~TlsStorage()
|
~TlsStorage()
|
||||||
@ -1077,15 +1077,27 @@ public:
|
|||||||
size_t reserveSlot()
|
size_t reserveSlot()
|
||||||
{
|
{
|
||||||
AutoLock guard(mtxGlobalAccess);
|
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
|
// Release TLS storage index and pass assosiated data to caller
|
||||||
void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec)
|
void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec)
|
||||||
{
|
{
|
||||||
AutoLock guard(mtxGlobalAccess);
|
AutoLock guard(mtxGlobalAccess);
|
||||||
CV_Assert(tlsSlots > slotIdx);
|
CV_Assert(tlsSlots.size() > slotIdx);
|
||||||
|
|
||||||
for(size_t i = 0; i < threads.size(); i++)
|
for(size_t i = 0; i < threads.size(); i++)
|
||||||
{
|
{
|
||||||
@ -1096,15 +1108,14 @@ public:
|
|||||||
threads[i]->slots[slotIdx] = 0;
|
threads[i]->slots[slotIdx] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we removing last element, decriment slots size to save space
|
|
||||||
if(tlsSlots-1 == slotIdx)
|
tlsSlots[slotIdx] = 0;
|
||||||
tlsSlots--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get data by TLS storage index
|
// Get data by TLS storage index
|
||||||
void* getData(size_t slotIdx) const
|
void* getData(size_t slotIdx) const
|
||||||
{
|
{
|
||||||
CV_Assert(tlsSlots > slotIdx);
|
CV_Assert(tlsSlots.size() > slotIdx);
|
||||||
|
|
||||||
ThreadData* threadData = (ThreadData*)tls.GetData();
|
ThreadData* threadData = (ThreadData*)tls.GetData();
|
||||||
if(threadData && threadData->slots.size() > slotIdx)
|
if(threadData && threadData->slots.size() > slotIdx)
|
||||||
@ -1113,10 +1124,24 @@ public:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gather data from threads by TLS storage index
|
||||||
|
void gather(size_t slotIdx, std::vector<void*> &dataVec)
|
||||||
|
{
|
||||||
|
AutoLock guard(mtxGlobalAccess);
|
||||||
|
CV_Assert(tlsSlots.size() > slotIdx);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < threads.size(); i++)
|
||||||
|
{
|
||||||
|
std::vector<void*>& thread_slots = threads[i]->slots;
|
||||||
|
if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
|
||||||
|
dataVec.push_back(thread_slots[slotIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set data to storage index
|
// Set data to storage index
|
||||||
void setData(size_t slotIdx, void* pData)
|
void setData(size_t slotIdx, void* pData)
|
||||||
{
|
{
|
||||||
CV_Assert(pData != NULL);
|
CV_Assert(tlsSlots.size() > slotIdx && pData != NULL);
|
||||||
|
|
||||||
ThreadData* threadData = (ThreadData*)tls.GetData();
|
ThreadData* threadData = (ThreadData*)tls.GetData();
|
||||||
if(!threadData)
|
if(!threadData)
|
||||||
@ -1131,7 +1156,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(slotIdx >= threadData->slots.size())
|
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;
|
threadData->slots[slotIdx] = pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1139,7 +1168,7 @@ private:
|
|||||||
TlsAbstraction tls; // TLS abstraction layer instance
|
TlsAbstraction tls; // TLS abstraction layer instance
|
||||||
|
|
||||||
Mutex mtxGlobalAccess; // Shared objects operation guard
|
Mutex mtxGlobalAccess; // Shared objects operation guard
|
||||||
size_t tlsSlots; // TLS storage counter
|
std::vector<int> tlsSlots; // TLS keys state
|
||||||
std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
|
std::vector<ThreadData*> 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
|
CV_Assert(key_ == -1); // Key must be released in child object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TLSDataContainer::gatherData(std::vector<void*> &data) const
|
||||||
|
{
|
||||||
|
getTlsStorage().gather(key_, data);
|
||||||
|
}
|
||||||
|
|
||||||
void TLSDataContainer::release()
|
void TLSDataContainer::release()
|
||||||
{
|
{
|
||||||
std::vector<void*> data;
|
std::vector<void*> data;
|
||||||
|
Loading…
Reference in New Issue
Block a user