1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 #include "precomp.hpp"
47 # pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
51 #if defined WIN32 || defined _WIN32 || defined WINCE
52 #ifndef _WIN32_WINNT // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
53 #define _WIN32_WINNT 0x0400 // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
56 #if (_WIN32_WINNT >= 0x0602)
68 static void __cpuid(int* cpuid_data, int)
89 #include <wrl/client.h>
90 #ifndef __cplusplus_winrt
91 #include <windows.storage.h>
92 #pragma comment(lib, "runtimeobject.lib")
95 std::wstring GetTempPathWinRT()
97 #ifdef __cplusplus_winrt
98 return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
100 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
101 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
102 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
103 Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
105 HSTRING_HEADER hstrHead;
107 if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
108 (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
110 if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
112 if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
114 if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
116 if (FAILED(storagefolderRef.As(&storageitemRef)))
119 if (FAILED(storageitemRef->get_Path(&str)))
121 wstr = WindowsGetStringRawBuffer(str, NULL);
122 WindowsDeleteString(str);
127 std::wstring GetTempFileNameWinRT(std::wstring prefix)
132 wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
133 swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
134 g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
135 UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
136 UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
138 return prefix + std::wstring(guidStr);
144 #include <sys/time.h>
147 #if defined __MACH__ && defined __APPLE__
148 #include <mach/mach.h>
149 #include <mach/mach_time.h>
160 #if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__
163 #include <sys/types.h>
165 #include <sys/sysconf.h>
167 #include <sys/sysctl.h>
172 # include <android/log.h>
178 Exception::Exception() { code = 0; line = 0; }
180 Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
181 : code(_code), err(_err), func(_func), file(_file), line(_line)
186 Exception::~Exception() throw() {}
189 \return the error description and the context as a text string.
191 const char* Exception::what() const throw() { return msg.c_str(); }
193 void Exception::formatMessage()
195 if( func.size() > 0 )
196 msg = format("%s:%d: error: (%d) %s in function %s\n", file.c_str(), line, code, err.c_str(), func.c_str());
198 msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str());
203 enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
207 memset( have, 0, sizeof(have) );
211 static HWFeatures initialize(void)
214 int cpuid_data[4] = { 0, 0, 0, 0 };
216 #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
217 __cpuid(cpuid_data, 1);
218 #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
224 :[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
235 : "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3])
242 f.x86_family = (cpuid_data[0] >> 8) & 15;
243 if( f.x86_family >= 6 )
245 f.have[CV_CPU_MMX] = (cpuid_data[3] & (1 << 23)) != 0;
246 f.have[CV_CPU_SSE] = (cpuid_data[3] & (1<<25)) != 0;
247 f.have[CV_CPU_SSE2] = (cpuid_data[3] & (1<<26)) != 0;
248 f.have[CV_CPU_SSE3] = (cpuid_data[2] & (1<<0)) != 0;
249 f.have[CV_CPU_SSSE3] = (cpuid_data[2] & (1<<9)) != 0;
250 f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
251 f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
252 f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
253 f.have[CV_CPU_AVX] = (((cpuid_data[2] & (1<<28)) != 0)&&((cpuid_data[2] & (1<<27)) != 0));//OS uses XSAVE_XRSTORE and CPU support AVX
260 bool have[MAX_FEATURE+1];
263 static HWFeatures featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
264 static HWFeatures* currentFeatures = &featuresEnabled;
266 bool checkHardwareSupport(int feature)
268 CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
269 return currentFeatures->have[feature];
273 volatile bool useOptimizedFlag = true;
275 struct IPPInitializer
277 IPPInitializer(void) { ippStaticInit(); }
280 IPPInitializer ippInitializer;
283 volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2];
284 volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2];
285 volatile bool USE_AVX = featuresEnabled.have[CV_CPU_AVX];
287 void setUseOptimized( bool flag )
289 useOptimizedFlag = flag;
290 currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
291 USE_SSE2 = currentFeatures->have[CV_CPU_SSE2];
294 bool useOptimized(void)
296 return useOptimizedFlag;
299 int64 getTickCount(void)
301 #if defined WIN32 || defined _WIN32 || defined WINCE
302 LARGE_INTEGER counter;
303 QueryPerformanceCounter( &counter );
304 return (int64)counter.QuadPart;
305 #elif defined __linux || defined __linux__
307 clock_gettime(CLOCK_MONOTONIC, &tp);
308 return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
309 #elif defined __MACH__ && defined __APPLE__
310 return (int64)mach_absolute_time();
314 gettimeofday( &tv, &tz );
315 return (int64)tv.tv_sec*1000000 + tv.tv_usec;
319 double getTickFrequency(void)
321 #if defined WIN32 || defined _WIN32 || defined WINCE
323 QueryPerformanceFrequency(&freq);
324 return (double)freq.QuadPart;
325 #elif defined __linux || defined __linux__
327 #elif defined __MACH__ && defined __APPLE__
328 static double freq = 0;
331 mach_timebase_info_data_t sTimebaseInfo;
332 mach_timebase_info(&sTimebaseInfo);
333 freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
341 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
342 #if defined(__i386__)
344 int64 getCPUTickCount(void)
347 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
350 #elif defined(__x86_64__)
352 int64 getCPUTickCount(void)
355 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
356 return (int64)lo | ((int64)hi << 32);
359 #elif defined(__ppc__)
361 int64 getCPUTickCount(void)
364 unsigned upper, lower, tmp;
372 : "=r"(upper),"=r"(lower),"=r"(tmp)
374 return lower | ((int64)upper << 32);
379 #error "RDTSC not defined"
383 #elif defined _MSC_VER && defined WIN32 && defined _M_IX86
385 int64 getCPUTickCount(void)
394 int64 getCPUTickCount(void)
396 return ippGetCpuClocks();
399 int64 getCPUTickCount(void)
401 return getTickCount();
407 const String& getBuildInformation()
409 static String build_info =
410 #include "version_string.inc"
415 String format( const char* fmt, ... )
421 int len = vsnprintf(buf, sizeof(buf), fmt, va);
424 if (len >= (int)sizeof(buf))
428 len = vsnprintf((char*)s.c_str(), len + 1, fmt, va);
433 return String(buf, len);
436 String tempfile( const char* suffix )
439 std::wstring temp_dir = L"";
440 const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH");
442 temp_dir = std::wstring(opencv_temp_dir);
444 const char *temp_dir = getenv("OPENCV_TEMP_PATH");
448 #if defined WIN32 || defined _WIN32
450 RoInitialize(RO_INIT_MULTITHREADED);
451 std::wstring temp_dir2;
452 if (temp_dir.empty())
453 temp_dir = GetTempPathWinRT();
455 std::wstring temp_file;
456 temp_file = GetTempFileNameWinRT(L"ocv");
457 if (temp_file.empty())
458 return std::string();
460 temp_file = temp_dir + std::wstring(L"\\") + temp_file;
461 DeleteFileW(temp_file.c_str());
463 char aname[MAX_PATH];
464 size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
465 CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
466 fname = std::string(aname);
469 char temp_dir2[MAX_PATH] = { 0 };
470 char temp_file[MAX_PATH] = { 0 };
472 if (temp_dir == 0 || temp_dir[0] == 0)
474 ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
475 temp_dir = temp_dir2;
477 if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
480 DeleteFileA(temp_file);
486 //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
487 char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
489 char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
492 if (temp_dir == 0 || temp_dir[0] == 0)
493 fname = defaultTemplate;
497 char ech = fname[fname.size() - 1];
498 if(ech != '/' && ech != '\\')
500 fname = fname + "__opencv_temp.XXXXXX";
503 const int fd = mkstemp((char*)fname.c_str());
504 if (fd == -1) return String();
507 remove(fname.c_str());
512 if (suffix[0] != '.')
513 return fname + "." + suffix;
515 return fname + suffix;
520 static CvErrorCallback customErrorCallback = 0;
521 static void* customErrorCallbackData = 0;
522 static bool breakOnError = false;
524 bool setBreakOnError(bool value)
526 bool prevVal = breakOnError;
527 breakOnError = value;
531 void error( const Exception& exc )
533 if (customErrorCallback != 0)
534 customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
535 exc.file.c_str(), exc.line, customErrorCallbackData);
538 const char* errorStr = cvErrorStr(exc.code);
541 sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
542 errorStr, exc.err.c_str(), exc.func.size() > 0 ?
543 exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
544 fprintf( stderr, "%s\n", buf );
547 __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
553 static volatile int* p = 0;
560 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
562 error(cv::Exception(_code, _err, _func, _file, _line));
566 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
569 *prevUserdata = customErrorCallbackData;
571 CvErrorCallback prevCallback = customErrorCallback;
573 customErrorCallback = errCallback;
574 customErrorCallbackData = userdata;
581 CV_IMPL int cvCheckHardwareSupport(int feature)
583 CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
584 return cv::currentFeatures->have[feature];
587 CV_IMPL int cvUseOptimized( int flag )
589 int prevMode = cv::useOptimizedFlag;
590 cv::setUseOptimized( flag != 0 );
594 CV_IMPL int64 cvGetTickCount(void)
596 return cv::getTickCount();
599 CV_IMPL double cvGetTickFrequency(void)
601 return cv::getTickFrequency()*1e-6;
604 CV_IMPL CvErrorCallback
605 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
607 return cv::redirectError(errCallback, userdata, prevUserdata);
610 CV_IMPL int cvNulDevReport( int, const char*, const char*,
611 const char*, int, void* )
616 CV_IMPL int cvStdErrReport( int, const char*, const char*,
617 const char*, int, void* )
622 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
623 const char*, int, void* )
628 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
634 CV_IMPL const char* cvErrorStr( int status )
636 static char buf[256];
640 case CV_StsOk : return "No Error";
641 case CV_StsBackTrace : return "Backtrace";
642 case CV_StsError : return "Unspecified error";
643 case CV_StsInternal : return "Internal error";
644 case CV_StsNoMem : return "Insufficient memory";
645 case CV_StsBadArg : return "Bad argument";
646 case CV_StsNoConv : return "Iterations do not converge";
647 case CV_StsAutoTrace : return "Autotrace call";
648 case CV_StsBadSize : return "Incorrect size of input array";
649 case CV_StsNullPtr : return "Null pointer";
650 case CV_StsDivByZero : return "Division by zero occured";
651 case CV_BadStep : return "Image step is wrong";
652 case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
653 case CV_StsObjectNotFound : return "Requested object was not found";
654 case CV_BadDepth : return "Input image depth is not supported by function";
655 case CV_StsUnmatchedFormats : return "Formats of input arguments do not match";
656 case CV_StsUnmatchedSizes : return "Sizes of input arguments do not match";
657 case CV_StsOutOfRange : return "One of arguments\' values is out of range";
658 case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats";
659 case CV_BadCOI : return "Input COI is not supported";
660 case CV_BadNumChannels : return "Bad number of channels";
661 case CV_StsBadFlag : return "Bad flag (parameter or structure field)";
662 case CV_StsBadPoint : return "Bad parameter of type CvPoint";
663 case CV_StsBadMask : return "Bad type of mask argument";
664 case CV_StsParseError : return "Parsing error";
665 case CV_StsNotImplemented : return "The function/feature is not implemented";
666 case CV_StsBadMemBlock : return "Memory block has been corrupted";
667 case CV_StsAssert : return "Assertion failed";
668 case CV_GpuNotSupported : return "No CUDA support";
669 case CV_GpuApiCallError : return "Gpu API call";
670 case CV_OpenGlNotSupported : return "No OpenGL support";
671 case CV_OpenGlApiCallError : return "OpenGL API call";
674 sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
678 CV_IMPL int cvGetErrMode(void)
683 CV_IMPL int cvSetErrMode(int)
688 CV_IMPL int cvGetErrStatus(void)
693 CV_IMPL void cvSetErrStatus(int)
698 CV_IMPL void cvError( int code, const char* func_name,
700 const char* file_name, int line )
702 cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
705 /* function, which converts int to int */
707 cvErrorFromIppStatus( int status )
711 case CV_BADSIZE_ERR: return CV_StsBadSize;
712 case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock;
713 case CV_NULLPTR_ERR: return CV_StsNullPtr;
714 case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero;
715 case CV_BADSTEP_ERR: return CV_BadStep;
716 case CV_OUTOFMEM_ERR: return CV_StsNoMem;
717 case CV_BADARG_ERR: return CV_StsBadArg;
718 case CV_NOTDEFINED_ERR: return CV_StsError;
719 case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
720 case CV_NOTFOUND_ERR: return CV_StsObjectNotFound;
721 case CV_BADCONVERGENCE_ERR: return CV_StsNoConv;
722 case CV_BADDEPTH_ERR: return CV_BadDepth;
723 case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats;
724 case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI;
725 case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels;
726 case CV_BADFLAG_ERR: return CV_StsBadFlag;
727 case CV_BADRANGE_ERR: return CV_StsBadArg;
728 case CV_BADCOEF_ERR: return CV_StsBadArg;
729 case CV_BADFACTOR_ERR: return CV_StsBadArg;
730 case CV_BADPOINT_ERR: return CV_StsBadPoint;
738 bool __termination = false;
744 #if defined WIN32 || defined _WIN32 || defined WINCE
750 #if (_WIN32_WINNT >= 0x0600)
751 ::InitializeCriticalSectionEx(&cs, 1000, 0);
753 ::InitializeCriticalSection(&cs);
757 ~Impl() { DeleteCriticalSection(&cs); }
759 void lock() { EnterCriticalSection(&cs); }
760 bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
761 void unlock() { LeaveCriticalSection(&cs); }
773 pthread_mutexattr_t attr;
774 pthread_mutexattr_init(&attr);
775 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
776 pthread_mutex_init(&mt, &attr);
777 pthread_mutexattr_destroy(&attr);
781 ~Impl() { pthread_mutex_destroy(&mt); }
783 void lock() { pthread_mutex_lock(&mt); }
784 bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
785 void unlock() { pthread_mutex_unlock(&mt); }
795 impl = new Mutex::Impl;
800 if( CV_XADD(&impl->refcount, -1) == 1 )
805 Mutex::Mutex(const Mutex& m)
808 CV_XADD(&impl->refcount, 1);
811 Mutex& Mutex::operator = (const Mutex& m)
813 CV_XADD(&m.impl->refcount, 1);
814 if( CV_XADD(&impl->refcount, -1) == 1 )
820 void Mutex::lock() { impl->lock(); }
821 void Mutex::unlock() { impl->unlock(); }
822 bool Mutex::trylock() { return impl->trylock(); }
825 //////////////////////////////// thread-local storage ////////////////////////////////
829 std::vector<void*> tlsData_;
831 TLSStorage() { tlsData_.reserve(16); }
833 inline void* getData(int key) const
835 CV_DbgAssert(key >= 0);
836 return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
838 inline void setData(int key, void* data)
840 CV_DbgAssert(key >= 0);
841 if (key >= (int)tlsData_.size())
843 tlsData_.resize(key + 1, NULL);
845 tlsData_[key] = data;
848 inline static TLSStorage* get();
852 #pragma warning(disable:4505) // unreferenced local function has been removed
855 // using C++11 thread attribute for local thread data
856 static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
858 static void deleteThreadData()
867 inline TLSStorage* TLSStorage::get()
871 g_tlsdata = new TLSStorage;
877 # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
879 static DWORD tlsKey = TLS_OUT_OF_INDEXES;
881 static void deleteThreadData()
883 if(tlsKey != TLS_OUT_OF_INDEXES)
885 delete (TLSStorage*)TlsGetValue(tlsKey);
886 TlsSetValue(tlsKey, NULL);
890 inline TLSStorage* TLSStorage::get()
892 if (tlsKey == TLS_OUT_OF_INDEXES)
895 CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
897 TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
901 TlsSetValue(tlsKey, d);
907 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
909 #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
912 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID);
914 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
916 if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
918 if (lpReserved != NULL) // called after ExitProcess() call
919 cv::__termination = true;
920 cv::deleteThreadAllocData();
921 cv::deleteThreadData();
928 static pthread_key_t tlsKey = 0;
929 static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
931 static void deleteTLSStorage(void* data)
933 delete (TLSStorage*)data;
936 static void makeKey()
938 int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
939 CV_Assert(errcode == 0);
942 inline TLSStorage* TLSStorage::get()
944 pthread_once(&tlsKeyOnce, makeKey);
945 TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
949 pthread_setspecific(tlsKey, d);
955 class TLSContainerStorage
958 std::vector<TLSDataContainer*> tlsContainers_;
960 TLSContainerStorage() { }
961 ~TLSContainerStorage()
963 for (size_t i = 0; i < tlsContainers_.size(); i++)
965 CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
966 tlsContainers_[i] = NULL;
970 int allocateKey(TLSDataContainer* pContainer)
972 cv::AutoLock lock(mutex_);
973 tlsContainers_.push_back(pContainer);
974 return (int)tlsContainers_.size() - 1;
976 void releaseKey(int id, TLSDataContainer* pContainer)
978 cv::AutoLock lock(mutex_);
979 CV_Assert(tlsContainers_[id] == pContainer);
980 tlsContainers_[id] = NULL;
981 // currently, we don't go into thread's TLSData and release data for this key
984 void destroyData(int key, void* data)
986 cv::AutoLock lock(mutex_);
987 TLSDataContainer* k = tlsContainers_[key];
992 k->deleteDataInstance(data);
996 CV_DbgAssert(k == NULL); // Debug this!
1000 static TLSContainerStorage tlsContainerStorage;
1002 TLSDataContainer::TLSDataContainer()
1005 key_ = tlsContainerStorage.allocateKey(this);
1008 TLSDataContainer::~TLSDataContainer()
1010 tlsContainerStorage.releaseKey(key_, this);
1014 void* TLSDataContainer::getData() const
1016 CV_Assert(key_ >= 0);
1017 TLSStorage* tlsData = TLSStorage::get();
1018 void* data = tlsData->getData(key_);
1021 data = this->createDataInstance();
1022 CV_DbgAssert(data != NULL);
1023 tlsData->setData(key_, data);
1028 TLSStorage::~TLSStorage()
1030 for (int i = 0; i < (int)tlsData_.size(); i++)
1032 void*& data = tlsData_[i];
1035 tlsContainerStorage.destroyData(i, data);
1042 TLSData<CoreTLSData> coreTlsData;