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 std::string& getBuildInformation()
409 static std::string build_info =
410 #include "version_string.inc"
415 string format( const char* fmt, ... )
419 va_start( args, fmt );
420 vsprintf( buf, fmt, args );
424 string tempfile( const char* suffix )
427 std::wstring temp_dir = L"";
428 const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH");
430 temp_dir = std::wstring(opencv_temp_dir);
432 const char *temp_dir = getenv("OPENCV_TEMP_PATH");
436 #if defined WIN32 || defined _WIN32
438 RoInitialize(RO_INIT_MULTITHREADED);
439 std::wstring temp_dir2;
440 if (temp_dir.empty())
441 temp_dir = GetTempPathWinRT();
443 std::wstring temp_file;
444 temp_file = GetTempFileNameWinRT(L"ocv");
445 if (temp_file.empty())
446 return std::string();
448 temp_file = temp_dir + std::wstring(L"\\") + temp_file;
449 DeleteFileW(temp_file.c_str());
451 char aname[MAX_PATH];
452 size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
453 CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
454 fname = std::string(aname);
457 char temp_dir2[MAX_PATH] = { 0 };
458 char temp_file[MAX_PATH] = { 0 };
460 if (temp_dir == 0 || temp_dir[0] == 0)
462 ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
463 temp_dir = temp_dir2;
465 if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
468 DeleteFileA(temp_file);
474 //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
475 char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
477 char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
480 if (temp_dir == 0 || temp_dir[0] == 0)
481 fname = defaultTemplate;
485 char ech = fname[fname.size() - 1];
486 if(ech != '/' && ech != '\\')
488 fname += "__opencv_temp.XXXXXX";
491 const int fd = mkstemp((char*)fname.c_str());
492 if (fd == -1) return string();
495 remove(fname.c_str());
500 if (suffix[0] != '.')
501 return fname + "." + suffix;
503 return fname + suffix;
508 static CvErrorCallback customErrorCallback = 0;
509 static void* customErrorCallbackData = 0;
510 static bool breakOnError = false;
512 bool setBreakOnError(bool value)
514 bool prevVal = breakOnError;
515 breakOnError = value;
519 void error( const Exception& exc )
521 if (customErrorCallback != 0)
522 customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
523 exc.file.c_str(), exc.line, customErrorCallbackData);
526 const char* errorStr = cvErrorStr(exc.code);
529 sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
530 errorStr, exc.err.c_str(), exc.func.size() > 0 ?
531 exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
532 fprintf( stderr, "%s\n", buf );
535 __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
541 static volatile int* p = 0;
549 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
552 *prevUserdata = customErrorCallbackData;
554 CvErrorCallback prevCallback = customErrorCallback;
556 customErrorCallback = errCallback;
557 customErrorCallbackData = userdata;
564 CV_IMPL int cvCheckHardwareSupport(int feature)
566 CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
567 return cv::currentFeatures->have[feature];
570 CV_IMPL int cvUseOptimized( int flag )
572 int prevMode = cv::useOptimizedFlag;
573 cv::setUseOptimized( flag != 0 );
577 CV_IMPL int64 cvGetTickCount(void)
579 return cv::getTickCount();
582 CV_IMPL double cvGetTickFrequency(void)
584 return cv::getTickFrequency()*1e-6;
587 CV_IMPL CvErrorCallback
588 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
590 return cv::redirectError(errCallback, userdata, prevUserdata);
593 CV_IMPL int cvNulDevReport( int, const char*, const char*,
594 const char*, int, void* )
599 CV_IMPL int cvStdErrReport( int, const char*, const char*,
600 const char*, int, void* )
605 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
606 const char*, int, void* )
611 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
617 CV_IMPL const char* cvErrorStr( int status )
619 static char buf[256];
623 case CV_StsOk : return "No Error";
624 case CV_StsBackTrace : return "Backtrace";
625 case CV_StsError : return "Unspecified error";
626 case CV_StsInternal : return "Internal error";
627 case CV_StsNoMem : return "Insufficient memory";
628 case CV_StsBadArg : return "Bad argument";
629 case CV_StsNoConv : return "Iterations do not converge";
630 case CV_StsAutoTrace : return "Autotrace call";
631 case CV_StsBadSize : return "Incorrect size of input array";
632 case CV_StsNullPtr : return "Null pointer";
633 case CV_StsDivByZero : return "Division by zero occured";
634 case CV_BadStep : return "Image step is wrong";
635 case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
636 case CV_StsObjectNotFound : return "Requested object was not found";
637 case CV_BadDepth : return "Input image depth is not supported by function";
638 case CV_StsUnmatchedFormats : return "Formats of input arguments do not match";
639 case CV_StsUnmatchedSizes : return "Sizes of input arguments do not match";
640 case CV_StsOutOfRange : return "One of arguments\' values is out of range";
641 case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats";
642 case CV_BadCOI : return "Input COI is not supported";
643 case CV_BadNumChannels : return "Bad number of channels";
644 case CV_StsBadFlag : return "Bad flag (parameter or structure field)";
645 case CV_StsBadPoint : return "Bad parameter of type CvPoint";
646 case CV_StsBadMask : return "Bad type of mask argument";
647 case CV_StsParseError : return "Parsing error";
648 case CV_StsNotImplemented : return "The function/feature is not implemented";
649 case CV_StsBadMemBlock : return "Memory block has been corrupted";
650 case CV_StsAssert : return "Assertion failed";
651 case CV_GpuNotSupported : return "No GPU support";
652 case CV_GpuApiCallError : return "Gpu API call";
653 case CV_OpenGlNotSupported : return "No OpenGL support";
654 case CV_OpenGlApiCallError : return "OpenGL API call";
657 sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
661 CV_IMPL int cvGetErrMode(void)
666 CV_IMPL int cvSetErrMode(int)
671 CV_IMPL int cvGetErrStatus(void)
676 CV_IMPL void cvSetErrStatus(int)
681 CV_IMPL void cvError( int code, const char* func_name,
683 const char* file_name, int line )
685 cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
688 /* function, which converts int to int */
690 cvErrorFromIppStatus( int status )
694 case CV_BADSIZE_ERR: return CV_StsBadSize;
695 case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock;
696 case CV_NULLPTR_ERR: return CV_StsNullPtr;
697 case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero;
698 case CV_BADSTEP_ERR: return CV_BadStep;
699 case CV_OUTOFMEM_ERR: return CV_StsNoMem;
700 case CV_BADARG_ERR: return CV_StsBadArg;
701 case CV_NOTDEFINED_ERR: return CV_StsError;
702 case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
703 case CV_NOTFOUND_ERR: return CV_StsObjectNotFound;
704 case CV_BADCONVERGENCE_ERR: return CV_StsNoConv;
705 case CV_BADDEPTH_ERR: return CV_BadDepth;
706 case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats;
707 case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI;
708 case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels;
709 case CV_BADFLAG_ERR: return CV_StsBadFlag;
710 case CV_BADRANGE_ERR: return CV_StsBadArg;
711 case CV_BADCOEF_ERR: return CV_StsBadArg;
712 case CV_BADFACTOR_ERR: return CV_StsBadArg;
713 case CV_BADPOINT_ERR: return CV_StsBadPoint;
720 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, 0 };
722 CvModuleInfo* CvModule::first = 0, *CvModule::last = 0;
724 CvModule::CvModule( CvModuleInfo* _info )
726 cvRegisterModule( _info );
730 CvModule::~CvModule(void)
734 CvModuleInfo* p = first;
735 for( ; p != 0 && p->next != info; p = p->next )
739 p->next = info->next;
753 cvRegisterModule( const CvModuleInfo* module )
755 CV_Assert( module != 0 && module->name != 0 && module->version != 0 );
757 size_t name_len = strlen(module->name);
758 size_t version_len = strlen(module->version);
760 CvModuleInfo* module_copy = (CvModuleInfo*)malloc( sizeof(*module_copy) +
761 name_len + 1 + version_len + 1 );
763 *module_copy = *module;
764 module_copy->name = (char*)(module_copy + 1);
765 module_copy->version = (char*)(module_copy + 1) + name_len + 1;
767 memcpy( (void*)module_copy->name, module->name, name_len + 1 );
768 memcpy( (void*)module_copy->version, module->version, version_len + 1 );
769 module_copy->next = 0;
771 if( CvModule::first == 0 )
772 CvModule::first = module_copy;
774 CvModule::last->next = module_copy;
776 CvModule::last = module_copy;
781 CvModule cxcore_module( &cxcore_info );
784 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
786 static char joint_verinfo[1024] = "";
787 static char plugin_list_buf[1024] = "";
795 CvModuleInfo* module;
801 size_t i, name_len = strlen(name);
803 for( module = CvModule::first; module != 0; module = module->next )
805 if( strlen(module->name) == name_len )
807 for( i = 0; i < name_len; i++ )
809 int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
818 CV_Error( CV_StsObjectNotFound, "The module is not found" );
820 *version = module->version;
824 char* ptr = joint_verinfo;
826 for( module = CvModule::first; module != 0; module = module->next )
828 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
832 *version = joint_verinfo;
837 *plugin_list = plugin_list_buf;
843 #if defined WIN32 || defined _WIN32 || defined WINCE
849 #if (_WIN32_WINNT >= 0x0600)
850 ::InitializeCriticalSectionEx(&cs, 1000, 0);
852 ::InitializeCriticalSection(&cs);
856 ~Impl() { DeleteCriticalSection(&cs); }
858 void lock() { EnterCriticalSection(&cs); }
859 bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
860 void unlock() { LeaveCriticalSection(&cs); }
867 int _interlockedExchangeAdd(int* addr, int delta)
869 #if defined _MSC_VER && _MSC_VER >= 1500
870 return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
872 return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
877 #elif defined __APPLE__
879 #include <libkern/OSAtomic.h>
883 Impl() { sl = OS_SPINLOCK_INIT; refcount = 1; }
886 void lock() { OSSpinLockLock(&sl); }
887 bool trylock() { return OSSpinLockTry(&sl); }
888 void unlock() { OSSpinLockUnlock(&sl); }
894 #elif defined __linux__ && !defined ANDROID
898 Impl() { pthread_spin_init(&sl, 0); refcount = 1; }
899 ~Impl() { pthread_spin_destroy(&sl); }
901 void lock() { pthread_spin_lock(&sl); }
902 bool trylock() { return pthread_spin_trylock(&sl) == 0; }
903 void unlock() { pthread_spin_unlock(&sl); }
905 pthread_spinlock_t sl;
913 Impl() { pthread_mutex_init(&sl, 0); refcount = 1; }
914 ~Impl() { pthread_mutex_destroy(&sl); }
916 void lock() { pthread_mutex_lock(&sl); }
917 bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
918 void unlock() { pthread_mutex_unlock(&sl); }
928 impl = new Mutex::Impl;
933 if( CV_XADD(&impl->refcount, -1) == 1 )
938 Mutex::Mutex(const Mutex& m)
941 CV_XADD(&impl->refcount, 1);
944 Mutex& Mutex::operator = (const Mutex& m)
946 CV_XADD(&m.impl->refcount, 1);
947 if( CV_XADD(&impl->refcount, -1) == 1 )
953 void Mutex::lock() { impl->lock(); }
954 void Mutex::unlock() { impl->unlock(); }
955 bool Mutex::trylock() { return impl->trylock(); }
958 //////////////////////////////// thread-local storage ////////////////////////////////
962 std::vector<void*> tlsData_;
964 TLSStorage() { tlsData_.reserve(16); }
966 inline void* getData(int key) const
968 CV_DbgAssert(key >= 0);
969 return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
971 inline void setData(int key, void* data)
973 CV_DbgAssert(key >= 0);
974 if (key >= (int)tlsData_.size())
976 tlsData_.resize(key + 1, NULL);
978 tlsData_[key] = data;
981 inline static TLSStorage* get();
986 #pragma warning(disable:4505) // unreferenced local function has been removed
990 // using C++11 thread attribute for local thread data
991 static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
993 static void deleteThreadData()
1002 inline TLSStorage* TLSStorage::get()
1006 g_tlsdata = new TLSStorage;
1012 # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
1014 static DWORD tlsKey = TLS_OUT_OF_INDEXES;
1016 static void deleteThreadData()
1018 if(tlsKey != TLS_OUT_OF_INDEXES)
1020 delete (TLSStorage*)TlsGetValue(tlsKey);
1021 TlsSetValue(tlsKey, NULL);
1025 inline TLSStorage* TLSStorage::get()
1027 if (tlsKey == TLS_OUT_OF_INDEXES)
1029 tlsKey = TlsAlloc();
1030 CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
1032 TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
1036 TlsSetValue(tlsKey, d);
1042 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
1044 #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1047 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID);
1049 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID)
1051 if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1053 cv::deleteThreadAllocData();
1054 cv::deleteThreadRNGData();
1055 cv::deleteThreadData();
1062 static pthread_key_t tlsKey = 0;
1063 static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
1065 static void deleteTLSStorage(void* data)
1067 delete (TLSStorage*)data;
1070 static void makeKey()
1072 int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
1073 CV_Assert(errcode == 0);
1076 inline TLSStorage* TLSStorage::get()
1078 pthread_once(&tlsKeyOnce, makeKey);
1079 TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
1083 pthread_setspecific(tlsKey, d);
1089 class TLSContainerStorage
1092 std::vector<TLSDataContainer*> tlsContainers_;
1094 TLSContainerStorage() { }
1095 ~TLSContainerStorage()
1097 for (size_t i = 0; i < tlsContainers_.size(); i++)
1099 CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
1100 tlsContainers_[i] = NULL;
1104 int allocateKey(TLSDataContainer* pContainer)
1106 cv::AutoLock lock(mutex_);
1107 tlsContainers_.push_back(pContainer);
1108 return (int)tlsContainers_.size() - 1;
1110 void releaseKey(int id, TLSDataContainer* pContainer)
1112 cv::AutoLock lock(mutex_);
1113 CV_Assert(tlsContainers_[id] == pContainer);
1114 tlsContainers_[id] = NULL;
1115 // currently, we don't go into thread's TLSData and release data for this key
1118 void destroyData(int key, void* data)
1120 cv::AutoLock lock(mutex_);
1121 TLSDataContainer* k = tlsContainers_[key];
1126 k->deleteDataInstance(data);
1130 CV_DbgAssert(k == NULL); // Debug this!
1135 // This is a wrapper function that will ensure 'tlsContainerStorage' is constructed on first use.
1136 // For more information: http://www.parashift.com/c++-faq/static-init-order-on-first-use.html
1137 static TLSContainerStorage& getTLSContainerStorage()
1139 static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
1140 return *tlsContainerStorage;
1143 TLSDataContainer::TLSDataContainer()
1146 key_ = getTLSContainerStorage().allocateKey(this);
1149 TLSDataContainer::~TLSDataContainer()
1151 getTLSContainerStorage().releaseKey(key_, this);
1155 void* TLSDataContainer::getData() const
1157 CV_Assert(key_ >= 0);
1158 TLSStorage* tlsData = TLSStorage::get();
1159 void* data = tlsData->getData(key_);
1162 data = this->createDataInstance();
1163 CV_DbgAssert(data != NULL);
1164 tlsData->setData(key_, data);
1169 TLSStorage::~TLSStorage()
1171 for (int i = 0; i < (int)tlsData_.size(); i++)
1173 void*& data = tlsData_[i];
1176 getTLSContainerStorage().destroyData(i, data);