Merge commit '0566ab4d3d' into merge-2.4
[profile/ivi/opencv.git] / modules / core / src / system.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
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.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
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.
26 //
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.
29 //
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.
40 //
41 //M*/
42
43 #include "precomp.hpp"
44
45 #ifdef _MSC_VER
46 # if _MSC_VER >= 1700
47 #  pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
48 # endif
49 #endif
50
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
54 #endif
55 #include <windows.h>
56 #if (_WIN32_WINNT >= 0x0602)
57   #include <synchapi.h>
58 #endif
59 #undef small
60 #undef min
61 #undef max
62 #undef abs
63 #include <tchar.h>
64 #if defined _MSC_VER
65   #if _MSC_VER >= 1400
66     #include <intrin.h>
67   #elif defined _M_IX86
68     static void __cpuid(int* cpuid_data, int)
69     {
70         __asm
71         {
72             push ebx
73             push edi
74             mov edi, cpuid_data
75             mov eax, 1
76             cpuid
77             mov [edi], eax
78             mov [edi + 4], ebx
79             mov [edi + 8], ecx
80             mov [edi + 12], edx
81             pop edi
82             pop ebx
83         }
84     }
85   #endif
86 #endif
87
88 #ifdef HAVE_WINRT
89 #include <wrl/client.h>
90 #ifndef __cplusplus_winrt
91 #include <windows.storage.h>
92 #pragma comment(lib, "runtimeobject.lib")
93 #endif
94
95 std::wstring GetTempPathWinRT()
96 {
97 #ifdef __cplusplus_winrt
98     return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
99 #else
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;
104     HSTRING str;
105     HSTRING_HEADER hstrHead;
106     std::wstring wstr;
107     if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
108                                             (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
109         return wstr;
110     if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
111         return wstr;
112     if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
113         return wstr;
114     if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
115         return wstr;
116     if (FAILED(storagefolderRef.As(&storageitemRef)))
117         return wstr;
118     str = NULL;
119     if (FAILED(storageitemRef->get_Path(&str)))
120         return wstr;
121     wstr = WindowsGetStringRawBuffer(str, NULL);
122     WindowsDeleteString(str);
123     return wstr;
124 #endif
125 }
126
127 std::wstring GetTempFileNameWinRT(std::wstring prefix)
128 {
129     wchar_t guidStr[40];
130     GUID g;
131     CoCreateGuid(&g);
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]));
137
138     return prefix + std::wstring(guidStr);
139 }
140
141 #endif
142 #else
143 #include <pthread.h>
144 #include <sys/time.h>
145 #include <time.h>
146
147 #if defined __MACH__ && defined __APPLE__
148 #include <mach/mach.h>
149 #include <mach/mach_time.h>
150 #endif
151
152 #endif
153
154 #ifdef _OPENMP
155 #include "omp.h"
156 #endif
157
158 #include <stdarg.h>
159
160 #if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__
161 #include <unistd.h>
162 #include <stdio.h>
163 #include <sys/types.h>
164 #if defined ANDROID
165 #include <sys/sysconf.h>
166 #else
167 #include <sys/sysctl.h>
168 #endif
169 #endif
170
171 #ifdef ANDROID
172 # include <android/log.h>
173 #endif
174
175 namespace cv
176 {
177
178 Exception::Exception() { code = 0; line = 0; }
179
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)
182 {
183     formatMessage();
184 }
185
186 Exception::~Exception() throw() {}
187
188 /*!
189  \return the error description and the context as a text string.
190  */
191 const char* Exception::what() const throw() { return msg.c_str(); }
192
193 void Exception::formatMessage()
194 {
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());
197     else
198         msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str());
199 }
200
201 struct HWFeatures
202 {
203     enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
204
205     HWFeatures(void)
206      {
207         memset( have, 0, sizeof(have) );
208         x86_family = 0;
209     }
210
211     static HWFeatures initialize(void)
212     {
213         HWFeatures f;
214         int cpuid_data[4] = { 0, 0, 0, 0 };
215
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__)
219         #ifdef __x86_64__
220         asm __volatile__
221         (
222          "movl $1, %%eax\n\t"
223          "cpuid\n\t"
224          :[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
225          :
226          : "cc"
227         );
228         #else
229         asm volatile
230         (
231          "pushl %%ebx\n\t"
232          "movl $1,%%eax\n\t"
233          "cpuid\n\t"
234          "popl %%ebx\n\t"
235          : "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3])
236          :
237          : "cc"
238         );
239         #endif
240     #endif
241
242         f.x86_family = (cpuid_data[0] >> 8) & 15;
243         if( f.x86_family >= 6 )
244         {
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
254         }
255
256         return f;
257     }
258
259     int x86_family;
260     bool have[MAX_FEATURE+1];
261 };
262
263 static HWFeatures  featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
264 static HWFeatures* currentFeatures = &featuresEnabled;
265
266 bool checkHardwareSupport(int feature)
267 {
268     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
269     return currentFeatures->have[feature];
270 }
271
272
273 volatile bool useOptimizedFlag = true;
274 #ifdef HAVE_IPP
275 struct IPPInitializer
276 {
277     IPPInitializer(void) { ippStaticInit(); }
278 };
279
280 IPPInitializer ippInitializer;
281 #endif
282
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];
286
287 void setUseOptimized( bool flag )
288 {
289     useOptimizedFlag = flag;
290     currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
291     USE_SSE2 = currentFeatures->have[CV_CPU_SSE2];
292 }
293
294 bool useOptimized(void)
295 {
296     return useOptimizedFlag;
297 }
298
299 int64 getTickCount(void)
300 {
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__
306     struct timespec tp;
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();
311 #else
312     struct timeval tv;
313     struct timezone tz;
314     gettimeofday( &tv, &tz );
315     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
316 #endif
317 }
318
319 double getTickFrequency(void)
320 {
321 #if defined WIN32 || defined _WIN32 || defined WINCE
322     LARGE_INTEGER freq;
323     QueryPerformanceFrequency(&freq);
324     return (double)freq.QuadPart;
325 #elif defined __linux || defined __linux__
326     return 1e9;
327 #elif defined __MACH__ && defined __APPLE__
328     static double freq = 0;
329     if( freq == 0 )
330     {
331         mach_timebase_info_data_t sTimebaseInfo;
332         mach_timebase_info(&sTimebaseInfo);
333         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
334     }
335     return freq;
336 #else
337     return 1e6;
338 #endif
339 }
340
341 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
342 #if defined(__i386__)
343
344 int64 getCPUTickCount(void)
345 {
346     int64 x;
347     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
348     return x;
349 }
350 #elif defined(__x86_64__)
351
352 int64 getCPUTickCount(void)
353 {
354     unsigned hi, lo;
355     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
356     return (int64)lo | ((int64)hi << 32);
357 }
358
359 #elif defined(__ppc__)
360
361 int64 getCPUTickCount(void)
362 {
363     int64 result = 0;
364     unsigned upper, lower, tmp;
365     __asm__ volatile(
366                      "0:                  \n"
367                      "\tmftbu   %0           \n"
368                      "\tmftb    %1           \n"
369                      "\tmftbu   %2           \n"
370                      "\tcmpw    %2,%0        \n"
371                      "\tbne     0b         \n"
372                      : "=r"(upper),"=r"(lower),"=r"(tmp)
373                      );
374     return lower | ((int64)upper << 32);
375 }
376
377 #else
378
379 #error "RDTSC not defined"
380
381 #endif
382
383 #elif defined _MSC_VER && defined WIN32 && defined _M_IX86
384
385 int64 getCPUTickCount(void)
386 {
387     __asm _emit 0x0f;
388     __asm _emit 0x31;
389 }
390
391 #else
392
393 #ifdef HAVE_IPP
394 int64 getCPUTickCount(void)
395 {
396     return ippGetCpuClocks();
397 }
398 #else
399 int64 getCPUTickCount(void)
400 {
401     return getTickCount();
402 }
403 #endif
404
405 #endif
406
407 const String& getBuildInformation()
408 {
409     static String build_info =
410 #include "version_string.inc"
411     ;
412     return build_info;
413 }
414
415 String format( const char* fmt, ... )
416 {
417     char buf[1024];
418
419     va_list va;
420     va_start(va, fmt);
421     int len = vsnprintf(buf, sizeof(buf), fmt, va);
422     va_end(va);
423
424     if (len >= (int)sizeof(buf))
425     {
426         String s(len, '\0');
427         va_start(va, fmt);
428         len = vsnprintf((char*)s.c_str(), len + 1, fmt, va);
429         va_end(va);
430         return s;
431     }
432
433     return String(buf, len);
434 }
435
436 String tempfile( const char* suffix )
437 {
438 #ifdef HAVE_WINRT
439     std::wstring temp_dir = L"";
440     const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH");
441     if (opencv_temp_dir)
442         temp_dir = std::wstring(opencv_temp_dir);
443 #else
444     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
445     String fname;
446 #endif
447
448 #if defined WIN32 || defined _WIN32
449 #ifdef HAVE_WINRT
450     RoInitialize(RO_INIT_MULTITHREADED);
451     std::wstring temp_dir2;
452     if (temp_dir.empty())
453         temp_dir = GetTempPathWinRT();
454
455     std::wstring temp_file;
456     temp_file = GetTempFileNameWinRT(L"ocv");
457     if (temp_file.empty())
458         return std::string();
459
460     temp_file = temp_dir + std::wstring(L"\\") + temp_file;
461     DeleteFileW(temp_file.c_str());
462
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);
467     RoUninitialize();
468 #else
469     char temp_dir2[MAX_PATH] = { 0 };
470     char temp_file[MAX_PATH] = { 0 };
471
472     if (temp_dir == 0 || temp_dir[0] == 0)
473     {
474         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
475         temp_dir = temp_dir2;
476     }
477     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
478         return String();
479
480     DeleteFileA(temp_file);
481
482     fname = temp_file;
483 #endif
484 # else
485 #  ifdef ANDROID
486     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
487     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
488 #  else
489     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
490 #  endif
491
492     if (temp_dir == 0 || temp_dir[0] == 0)
493         fname = defaultTemplate;
494     else
495     {
496         fname = temp_dir;
497         char ech = fname[fname.size() - 1];
498         if(ech != '/' && ech != '\\')
499             fname = fname + "/";
500         fname = fname + "__opencv_temp.XXXXXX";
501     }
502
503     const int fd = mkstemp((char*)fname.c_str());
504     if (fd == -1) return String();
505
506     close(fd);
507     remove(fname.c_str());
508 # endif
509
510     if (suffix)
511     {
512         if (suffix[0] != '.')
513             return fname + "." + suffix;
514         else
515             return fname + suffix;
516     }
517     return fname;
518 }
519
520 static CvErrorCallback customErrorCallback = 0;
521 static void* customErrorCallbackData = 0;
522 static bool breakOnError = false;
523
524 bool setBreakOnError(bool value)
525 {
526     bool prevVal = breakOnError;
527     breakOnError = value;
528     return prevVal;
529 }
530
531 void error( const Exception& exc )
532 {
533     if (customErrorCallback != 0)
534         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
535                             exc.file.c_str(), exc.line, customErrorCallbackData);
536     else
537     {
538         const char* errorStr = cvErrorStr(exc.code);
539         char buf[1 << 16];
540
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 );
545         fflush( stderr );
546 #  ifdef __ANDROID__
547         __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
548 #  endif
549     }
550
551     if(breakOnError)
552     {
553         static volatile int* p = 0;
554         *p = 0;
555     }
556
557     throw exc;
558 }
559
560 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
561 {
562     error(cv::Exception(_code, _err, _func, _file, _line));
563 }
564
565 CvErrorCallback
566 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
567 {
568     if( prevUserdata )
569         *prevUserdata = customErrorCallbackData;
570
571     CvErrorCallback prevCallback = customErrorCallback;
572
573     customErrorCallback     = errCallback;
574     customErrorCallbackData = userdata;
575
576     return prevCallback;
577 }
578
579 }
580
581 CV_IMPL int cvCheckHardwareSupport(int feature)
582 {
583     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
584     return cv::currentFeatures->have[feature];
585 }
586
587 CV_IMPL int cvUseOptimized( int flag )
588 {
589     int prevMode = cv::useOptimizedFlag;
590     cv::setUseOptimized( flag != 0 );
591     return prevMode;
592 }
593
594 CV_IMPL int64  cvGetTickCount(void)
595 {
596     return cv::getTickCount();
597 }
598
599 CV_IMPL double cvGetTickFrequency(void)
600 {
601     return cv::getTickFrequency()*1e-6;
602 }
603
604 CV_IMPL CvErrorCallback
605 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
606 {
607     return cv::redirectError(errCallback, userdata, prevUserdata);
608 }
609
610 CV_IMPL int cvNulDevReport( int, const char*, const char*,
611                             const char*, int, void* )
612 {
613     return 0;
614 }
615
616 CV_IMPL int cvStdErrReport( int, const char*, const char*,
617                             const char*, int, void* )
618 {
619     return 0;
620 }
621
622 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
623                             const char*, int, void* )
624 {
625     return 0;
626 }
627
628 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
629 {
630     return 0;
631 }
632
633
634 CV_IMPL const char* cvErrorStr( int status )
635 {
636     static char buf[256];
637
638     switch (status)
639     {
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";
672     };
673
674     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
675     return buf;
676 }
677
678 CV_IMPL int cvGetErrMode(void)
679 {
680     return 0;
681 }
682
683 CV_IMPL int cvSetErrMode(int)
684 {
685     return 0;
686 }
687
688 CV_IMPL int cvGetErrStatus(void)
689 {
690     return 0;
691 }
692
693 CV_IMPL void cvSetErrStatus(int)
694 {
695 }
696
697
698 CV_IMPL void cvError( int code, const char* func_name,
699                       const char* err_msg,
700                       const char* file_name, int line )
701 {
702     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
703 }
704
705 /* function, which converts int to int */
706 CV_IMPL int
707 cvErrorFromIppStatus( int status )
708 {
709     switch (status)
710     {
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;
731
732     default:
733       return CV_StsError;
734     }
735 }
736
737 namespace cv {
738 bool __termination = false;
739 }
740
741 namespace cv
742 {
743
744 #if defined WIN32 || defined _WIN32 || defined WINCE
745
746 struct Mutex::Impl
747 {
748     Impl()
749     {
750 #if (_WIN32_WINNT >= 0x0600)
751         ::InitializeCriticalSectionEx(&cs, 1000, 0);
752 #else
753         ::InitializeCriticalSection(&cs);
754 #endif
755         refcount = 1;
756     }
757     ~Impl() { DeleteCriticalSection(&cs); }
758
759     void lock() { EnterCriticalSection(&cs); }
760     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
761     void unlock() { LeaveCriticalSection(&cs); }
762
763     CRITICAL_SECTION cs;
764     int refcount;
765 };
766
767 #else
768
769 struct Mutex::Impl
770 {
771     Impl()
772     {
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);
778
779         refcount = 1;
780     }
781     ~Impl() { pthread_mutex_destroy(&mt); }
782
783     void lock() { pthread_mutex_lock(&mt); }
784     bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
785     void unlock() { pthread_mutex_unlock(&mt); }
786
787     pthread_mutex_t mt;
788     int refcount;
789 };
790
791 #endif
792
793 Mutex::Mutex()
794 {
795     impl = new Mutex::Impl;
796 }
797
798 Mutex::~Mutex()
799 {
800     if( CV_XADD(&impl->refcount, -1) == 1 )
801         delete impl;
802     impl = 0;
803 }
804
805 Mutex::Mutex(const Mutex& m)
806 {
807     impl = m.impl;
808     CV_XADD(&impl->refcount, 1);
809 }
810
811 Mutex& Mutex::operator = (const Mutex& m)
812 {
813     CV_XADD(&m.impl->refcount, 1);
814     if( CV_XADD(&impl->refcount, -1) == 1 )
815         delete impl;
816     impl = m.impl;
817     return *this;
818 }
819
820 void Mutex::lock() { impl->lock(); }
821 void Mutex::unlock() { impl->unlock(); }
822 bool Mutex::trylock() { return impl->trylock(); }
823
824
825 //////////////////////////////// thread-local storage ////////////////////////////////
826
827 class TLSStorage
828 {
829     std::vector<void*> tlsData_;
830 public:
831     TLSStorage() { tlsData_.reserve(16); }
832     ~TLSStorage();
833     inline void* getData(int key) const
834     {
835         CV_DbgAssert(key >= 0);
836         return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
837     }
838     inline void setData(int key, void* data)
839     {
840         CV_DbgAssert(key >= 0);
841         if (key >= (int)tlsData_.size())
842         {
843             tlsData_.resize(key + 1, NULL);
844         }
845         tlsData_[key] = data;
846     }
847
848     inline static TLSStorage* get();
849 };
850
851 #ifdef WIN32
852 #pragma warning(disable:4505) // unreferenced local function has been removed
853
854 #ifdef HAVE_WINRT
855     // using C++11 thread attribute for local thread data
856     static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
857
858     static void deleteThreadData()
859     {
860         if (g_tlsdata)
861         {
862             delete g_tlsdata;
863             g_tlsdata = NULL;
864         }
865     }
866
867     inline TLSStorage* TLSStorage::get()
868     {
869         if (!g_tlsdata)
870         {
871             g_tlsdata = new TLSStorage;
872         }
873         return g_tlsdata;
874     }
875 #else
876 #ifdef WINCE
877 #   define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
878 #endif
879     static DWORD tlsKey = TLS_OUT_OF_INDEXES;
880
881     static void deleteThreadData()
882     {
883         if(tlsKey != TLS_OUT_OF_INDEXES)
884         {
885             delete (TLSStorage*)TlsGetValue(tlsKey);
886             TlsSetValue(tlsKey, NULL);
887         }
888     }
889
890     inline TLSStorage* TLSStorage::get()
891     {
892         if (tlsKey == TLS_OUT_OF_INDEXES)
893         {
894             tlsKey = TlsAlloc();
895             CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
896         }
897         TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
898         if (!d)
899         {
900             d = new TLSStorage;
901             TlsSetValue(tlsKey, d);
902         }
903         return d;
904     }
905 #endif //HAVE_WINRT
906
907 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
908 #ifdef HAVE_WINRT
909     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
910 #endif
911
912 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID);
913
914 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
915 {
916     if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
917     {
918         if (lpReserved != NULL) // called after ExitProcess() call
919             cv::__termination = true;
920         cv::deleteThreadAllocData();
921         cv::deleteThreadData();
922     }
923     return TRUE;
924 }
925 #endif
926
927 #else
928     static pthread_key_t tlsKey = 0;
929     static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
930
931     static void deleteTLSStorage(void* data)
932     {
933         delete (TLSStorage*)data;
934     }
935
936     static void makeKey()
937     {
938         int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
939         CV_Assert(errcode == 0);
940     }
941
942     inline TLSStorage* TLSStorage::get()
943     {
944         pthread_once(&tlsKeyOnce, makeKey);
945         TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
946         if( !d )
947         {
948             d = new TLSStorage;
949             pthread_setspecific(tlsKey, d);
950         }
951         return d;
952     }
953 #endif
954
955 class TLSContainerStorage
956 {
957     cv::Mutex mutex_;
958     std::vector<TLSDataContainer*> tlsContainers_;
959 public:
960     TLSContainerStorage() { }
961     ~TLSContainerStorage()
962     {
963         for (size_t i = 0; i < tlsContainers_.size(); i++)
964         {
965             CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
966             tlsContainers_[i] = NULL;
967         }
968     }
969
970     int allocateKey(TLSDataContainer* pContainer)
971     {
972         cv::AutoLock lock(mutex_);
973         tlsContainers_.push_back(pContainer);
974         return (int)tlsContainers_.size() - 1;
975     }
976     void releaseKey(int id, TLSDataContainer* pContainer)
977     {
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
982     }
983
984     void destroyData(int key, void* data)
985     {
986         cv::AutoLock lock(mutex_);
987         TLSDataContainer* k = tlsContainers_[key];
988         if (!k)
989             return;
990         try
991         {
992             k->deleteDataInstance(data);
993         }
994         catch (...)
995         {
996             CV_DbgAssert(k == NULL); // Debug this!
997         }
998     }
999 };
1000 static TLSContainerStorage tlsContainerStorage;
1001
1002 TLSDataContainer::TLSDataContainer()
1003     : key_(-1)
1004 {
1005     key_ = tlsContainerStorage.allocateKey(this);
1006 }
1007
1008 TLSDataContainer::~TLSDataContainer()
1009 {
1010     tlsContainerStorage.releaseKey(key_, this);
1011     key_ = -1;
1012 }
1013
1014 void* TLSDataContainer::getData() const
1015 {
1016     CV_Assert(key_ >= 0);
1017     TLSStorage* tlsData = TLSStorage::get();
1018     void* data = tlsData->getData(key_);
1019     if (!data)
1020     {
1021         data = this->createDataInstance();
1022         CV_DbgAssert(data != NULL);
1023         tlsData->setData(key_, data);
1024     }
1025     return data;
1026 }
1027
1028 TLSStorage::~TLSStorage()
1029 {
1030     for (int i = 0; i < (int)tlsData_.size(); i++)
1031     {
1032         void*& data = tlsData_[i];
1033         if (data)
1034         {
1035             tlsContainerStorage.destroyData(i, data);
1036             data = NULL;
1037         }
1038     }
1039     tlsData_.clear();
1040 }
1041
1042 TLSData<CoreTLSData> coreTlsData;
1043
1044 } // namespace cv
1045
1046 /* End of file. */