/////////////////////////// Synchronization Primitives ///////////////////////////////
-class CV_EXPORTS Mutex
-{
-public:
- Mutex();
- ~Mutex();
- Mutex(const Mutex& m);
- Mutex& operator = (const Mutex& m);
-
- void lock();
- bool trylock();
- void unlock();
-
- struct Impl;
-protected:
- Impl* impl;
-};
-
-class CV_EXPORTS AutoLock
-{
-public:
- AutoLock(Mutex& m) : mutex(&m) { mutex->lock(); }
- ~AutoLock() { mutex->unlock(); }
-protected:
- Mutex* mutex;
-private:
- AutoLock(const AutoLock&);
- AutoLock& operator = (const AutoLock&);
-};
+#if !defined(_M_CEE)
+typedef std::recursive_mutex Mutex;
+typedef std::lock_guard<cv::Mutex> AutoLock;
+#endif
- // TLS interface
- class CV_EXPORTS TLSDataContainer
- {
- protected:
- TLSDataContainer();
- virtual ~TLSDataContainer();
-
- void gatherData(std::vector<void*> &data) const;
- void* getData() const;
- void release();
-
- private:
- virtual void* createDataInstance() const = 0;
- virtual void deleteDataInstance(void* pData) const = 0;
-
- int key_;
-
- public:
- void cleanup(); //! Release created TLS data container objects. It is similar to release() call, but it keeps TLS container valid.
- };
-
- // Main TLS data class
- template <typename T>
- class TLSData : protected TLSDataContainer
- {
- public:
- inline TLSData() {}
- inline ~TLSData() { release(); } // Release key and delete associated data
- inline T* get() const { return (T*)getData(); } // Get data associated with key
- inline T& getRef() const { T* ptr = (T*)getData(); CV_Assert(ptr); return *ptr; } // Get data associated 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);
- }
-
- inline void cleanup() { TLSDataContainer::cleanup(); }
-
- private:
- virtual void* createDataInstance() const CV_OVERRIDE {return new T;} // Wrapper to allocate data by template
- virtual void deleteDataInstance(void* pData) const CV_OVERRIDE {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
} //namespace cv
-#ifndef DISABLE_OPENCV_24_COMPATIBILITY
-#include "opencv2/core/core_c.h"
-#endif
-
+ #ifdef CV_COLLECT_IMPL_DATA
+ #include "opencv2/core/utils/instrumentation.hpp"
+ #else
+ /// Collect implementation data on OpenCV function call. Requires ENABLE_IMPL_COLLECTION build option.
+ #define CV_IMPL_ADD(impl)
+ #endif
+
#endif //OPENCV_CORE_UTILITY_H
--- /dev/null
-#if OPENCV_ABI_COMPATIBILITY > 300
+ // This file is part of OpenCV project.
+ // It is subject to the license terms in the LICENSE file found in the top-level directory
+ // of this distribution and at http://opencv.org/license.html.
+
+ #ifndef OPENCV_UTILS_TLS_HPP
+ #define OPENCV_UTILS_TLS_HPP
+
+ #include <opencv2/core/utility.hpp>
+
+ namespace cv {
+
+ //! @addtogroup core_utils
+ //! @{
+
+ namespace details { class TlsStorage; }
+
+ /** TLS container base implementation
+ *
+ * Don't use directly.
+ *
+ * @sa TLSData, TLSDataAccumulator templates
+ */
+ class CV_EXPORTS TLSDataContainer
+ {
+ protected:
+ TLSDataContainer();
+ virtual ~TLSDataContainer();
+
+ /// @deprecated use detachData() instead
+ void gatherData(std::vector<void*> &data) const;
+ /// get TLS data and detach all data from threads (similar to cleanup() call)
+ void detachData(std::vector<void*>& data);
+
+ void* getData() const;
+ void release();
+
+ protected:
+ virtual void* createDataInstance() const = 0;
+ virtual void deleteDataInstance(void* pData) const = 0;
+
-#else
-public:
-#endif
+ private:
- TLSDataContainer(TLSDataContainer &);
- TLSDataContainer& operator =(const TLSDataContainer &);
+ int key_;
+
+ friend class cv::details::TlsStorage; // core/src/system.cpp
+
+ public:
+ void cleanup(); //!< Release created TLS data container objects. It is similar to release() call, but it keeps TLS container valid.
+
+ private:
+ // Disable copy/assign (noncopyable pattern)
++ TLSDataContainer(TLSDataContainer &) = delete;
++ TLSDataContainer& operator =(const TLSDataContainer &) = delete;
+ };
+
+
+ /** @brief Simple TLS data class
+ *
+ * @sa TLSDataAccumulator
+ */
+ template <typename T>
+ class TLSData : protected TLSDataContainer
+ {
+ public:
+ inline TLSData() {}
+ inline ~TLSData() { release(); }
+
+ inline T* get() const { return (T*)getData(); } //!< Get data associated with key
+ inline T& getRef() const { T* ptr = (T*)getData(); CV_DbgAssert(ptr); return *ptr; } //!< Get data associated with key
+
+ /// Release associated thread data
+ inline void cleanup()
+ {
+ TLSDataContainer::cleanup();
+ }
+
+ protected:
+ /// Wrapper to allocate data by template
+ virtual void* createDataInstance() const CV_OVERRIDE { return new T; }
+ /// Wrapper to release data by template
+ virtual void deleteDataInstance(void* pData) const CV_OVERRIDE { delete (T*)pData; }
+ };
+
+
+ /// TLS data accumulator with gathering methods
+ template <typename T>
+ class TLSDataAccumulator : public TLSData<T>
+ {
+ mutable cv::Mutex mutex;
+ mutable std::vector<T*> dataFromTerminatedThreads;
+ std::vector<T*> detachedData;
+ bool cleanupMode;
+ public:
+ TLSDataAccumulator() : cleanupMode(false) {}
+ ~TLSDataAccumulator()
+ {
+ release();
+ }
+
+ /** @brief Get data from all threads
+ * @deprecated replaced by detachData()
+ *
+ * Lifetime of vector data is valid until next detachData()/cleanup()/release() calls
+ *
+ * @param[out] data result buffer (should be empty)
+ */
+ void gather(std::vector<T*> &data) const
+ {
+ CV_Assert(cleanupMode == false); // state is not valid
+ CV_Assert(data.empty());
+ {
+ std::vector<void*> &dataVoid = reinterpret_cast<std::vector<void*>&>(data);
+ TLSDataContainer::gatherData(dataVoid);
+ }
+ {
+ AutoLock lock(mutex);
+ data.reserve(data.size() + dataFromTerminatedThreads.size());
+ for (typename std::vector<T*>::const_iterator i = dataFromTerminatedThreads.begin(); i != dataFromTerminatedThreads.end(); ++i)
+ {
+ data.push_back((T*)*i);
+ }
+ }
+ }
+
+ /** @brief Get and detach data from all threads
+ *
+ * Call cleanupDetachedData() when returned vector is not needed anymore.
+ *
+ * @return Vector with associated data. Content is preserved (including lifetime of attached data pointers) until next detachData()/cleanupDetachedData()/cleanup()/release() calls
+ */
+ std::vector<T*>& detachData()
+ {
+ CV_Assert(cleanupMode == false); // state is not valid
+ std::vector<void*> dataVoid;
+ {
+ TLSDataContainer::detachData(dataVoid);
+ }
+ {
+ AutoLock lock(mutex);
+ detachedData.reserve(dataVoid.size() + dataFromTerminatedThreads.size());
+ for (typename std::vector<T*>::const_iterator i = dataFromTerminatedThreads.begin(); i != dataFromTerminatedThreads.end(); ++i)
+ {
+ detachedData.push_back((T*)*i);
+ }
+ dataFromTerminatedThreads.clear();
+ for (typename std::vector<void*>::const_iterator i = dataVoid.begin(); i != dataVoid.end(); ++i)
+ {
+ detachedData.push_back((T*)(void*)*i);
+ }
+ }
+ dataVoid.clear();
+ return detachedData;
+ }
+
+ /// Release associated thread data returned by detachData() call
+ void cleanupDetachedData()
+ {
+ AutoLock lock(mutex);
+ cleanupMode = true;
+ _cleanupDetachedData();
+ cleanupMode = false;
+ }
+
+ /// Release associated thread data
+ void cleanup()
+ {
+ cleanupMode = true;
+ TLSDataContainer::cleanup();
+
+ AutoLock lock(mutex);
+ _cleanupDetachedData();
+ _cleanupTerminatedData();
+ cleanupMode = false;
+ }
+
+ /// Release associated thread data and free TLS key
+ void release()
+ {
+ cleanupMode = true;
+ TLSDataContainer::release();
+ {
+ AutoLock lock(mutex);
+ _cleanupDetachedData();
+ _cleanupTerminatedData();
+ }
+ }
+
+ protected:
+ // synchronized
+ void _cleanupDetachedData()
+ {
+ for (typename std::vector<T*>::iterator i = detachedData.begin(); i != detachedData.end(); ++i)
+ {
+ deleteDataInstance((T*)*i);
+ }
+ detachedData.clear();
+ }
+
+ // synchronized
+ void _cleanupTerminatedData()
+ {
+ for (typename std::vector<T*>::iterator i = dataFromTerminatedThreads.begin(); i != dataFromTerminatedThreads.end(); ++i)
+ {
+ deleteDataInstance((T*)*i);
+ }
+ dataFromTerminatedThreads.clear();
+ }
+
+ protected:
+ virtual void* createDataInstance() const CV_OVERRIDE
+ {
+ // Note: we can collect all allocated data here, but this would require raced mutex locks
+ return new T;
+ }
+ virtual void deleteDataInstance(void* pData) const CV_OVERRIDE
+ {
+ if (cleanupMode)
+ {
+ delete (T*)pData;
+ }
+ else
+ {
+ AutoLock lock(mutex);
+ dataFromTerminatedThreads.push_back((T*)pData);
+ }
+ }
+ };
+
+
+ //! @}
+
+ } // namespace
+
+ #endif // OPENCV_UTILS_TLS_HPP