tizen 2.4 release
[external/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 std::string& getBuildInformation()
408 {
409     static std::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[1 << 16];
418     va_list args;
419     va_start( args, fmt );
420     vsprintf( buf, fmt, args );
421     return string(buf);
422 }
423
424 string tempfile( const char* suffix )
425 {
426 #ifdef HAVE_WINRT
427     std::wstring temp_dir = L"";
428     const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH");
429     if (opencv_temp_dir)
430         temp_dir = std::wstring(opencv_temp_dir);
431 #else
432     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
433 #endif
434     string fname;
435
436 #if defined WIN32 || defined _WIN32
437 #ifdef HAVE_WINRT
438     RoInitialize(RO_INIT_MULTITHREADED);
439     std::wstring temp_dir2;
440     if (temp_dir.empty())
441         temp_dir = GetTempPathWinRT();
442
443     std::wstring temp_file;
444     temp_file = GetTempFileNameWinRT(L"ocv");
445     if (temp_file.empty())
446         return std::string();
447
448     temp_file = temp_dir + std::wstring(L"\\") + temp_file;
449     DeleteFileW(temp_file.c_str());
450
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);
455     RoUninitialize();
456 #else
457     char temp_dir2[MAX_PATH] = { 0 };
458     char temp_file[MAX_PATH] = { 0 };
459
460     if (temp_dir == 0 || temp_dir[0] == 0)
461     {
462         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
463         temp_dir = temp_dir2;
464     }
465     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
466         return string();
467
468     DeleteFileA(temp_file);
469
470     fname = temp_file;
471 #endif
472 # else
473 #  ifdef ANDROID
474     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
475     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
476 #  else
477     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
478 #  endif
479
480     if (temp_dir == 0 || temp_dir[0] == 0)
481         fname = defaultTemplate;
482     else
483     {
484         fname = temp_dir;
485         char ech = fname[fname.size() - 1];
486         if(ech != '/' && ech != '\\')
487             fname += "/";
488         fname += "__opencv_temp.XXXXXX";
489     }
490
491     const int fd = mkstemp((char*)fname.c_str());
492     if (fd == -1) return string();
493
494     close(fd);
495     remove(fname.c_str());
496 # endif
497
498     if (suffix)
499     {
500         if (suffix[0] != '.')
501             return fname + "." + suffix;
502         else
503             return fname + suffix;
504     }
505     return fname;
506 }
507
508 static CvErrorCallback customErrorCallback = 0;
509 static void* customErrorCallbackData = 0;
510 static bool breakOnError = false;
511
512 bool setBreakOnError(bool value)
513 {
514     bool prevVal = breakOnError;
515     breakOnError = value;
516     return prevVal;
517 }
518
519 void error( const Exception& exc )
520 {
521     if (customErrorCallback != 0)
522         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
523                             exc.file.c_str(), exc.line, customErrorCallbackData);
524     else
525     {
526         const char* errorStr = cvErrorStr(exc.code);
527         char buf[1 << 16];
528
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 );
533         fflush( stderr );
534 #  ifdef __ANDROID__
535         __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
536 #  endif
537     }
538
539     if(breakOnError)
540     {
541         static volatile int* p = 0;
542         *p = 0;
543     }
544
545     throw exc;
546 }
547
548 CvErrorCallback
549 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
550 {
551     if( prevUserdata )
552         *prevUserdata = customErrorCallbackData;
553
554     CvErrorCallback prevCallback = customErrorCallback;
555
556     customErrorCallback     = errCallback;
557     customErrorCallbackData = userdata;
558
559     return prevCallback;
560 }
561
562 }
563
564 CV_IMPL int cvCheckHardwareSupport(int feature)
565 {
566     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
567     return cv::currentFeatures->have[feature];
568 }
569
570 CV_IMPL int cvUseOptimized( int flag )
571 {
572     int prevMode = cv::useOptimizedFlag;
573     cv::setUseOptimized( flag != 0 );
574     return prevMode;
575 }
576
577 CV_IMPL int64  cvGetTickCount(void)
578 {
579     return cv::getTickCount();
580 }
581
582 CV_IMPL double cvGetTickFrequency(void)
583 {
584     return cv::getTickFrequency()*1e-6;
585 }
586
587 CV_IMPL CvErrorCallback
588 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
589 {
590     return cv::redirectError(errCallback, userdata, prevUserdata);
591 }
592
593 CV_IMPL int cvNulDevReport( int, const char*, const char*,
594                             const char*, int, void* )
595 {
596     return 0;
597 }
598
599 CV_IMPL int cvStdErrReport( int, const char*, const char*,
600                             const char*, int, void* )
601 {
602     return 0;
603 }
604
605 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
606                             const char*, int, void* )
607 {
608     return 0;
609 }
610
611 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
612 {
613     return 0;
614 }
615
616
617 CV_IMPL const char* cvErrorStr( int status )
618 {
619     static char buf[256];
620
621     switch (status)
622     {
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";
655     };
656
657     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
658     return buf;
659 }
660
661 CV_IMPL int cvGetErrMode(void)
662 {
663     return 0;
664 }
665
666 CV_IMPL int cvSetErrMode(int)
667 {
668     return 0;
669 }
670
671 CV_IMPL int cvGetErrStatus(void)
672 {
673     return 0;
674 }
675
676 CV_IMPL void cvSetErrStatus(int)
677 {
678 }
679
680
681 CV_IMPL void cvError( int code, const char* func_name,
682                       const char* err_msg,
683                       const char* file_name, int line )
684 {
685     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
686 }
687
688 /* function, which converts int to int */
689 CV_IMPL int
690 cvErrorFromIppStatus( int status )
691 {
692     switch (status)
693     {
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;
714
715     default:
716       return CV_StsError;
717     }
718 }
719
720 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, 0 };
721
722 CvModuleInfo* CvModule::first = 0, *CvModule::last = 0;
723
724 CvModule::CvModule( CvModuleInfo* _info )
725 {
726     cvRegisterModule( _info );
727     info = last;
728 }
729
730 CvModule::~CvModule(void)
731 {
732     if( info )
733     {
734         CvModuleInfo* p = first;
735         for( ; p != 0 && p->next != info; p = p->next )
736             ;
737
738         if( p )
739             p->next = info->next;
740
741         if( first == info )
742             first = info->next;
743
744         if( last == info )
745             last = p;
746
747         free( info );
748         info = 0;
749     }
750 }
751
752 CV_IMPL int
753 cvRegisterModule( const CvModuleInfo* module )
754 {
755     CV_Assert( module != 0 && module->name != 0 && module->version != 0 );
756
757     size_t name_len = strlen(module->name);
758     size_t version_len = strlen(module->version);
759
760     CvModuleInfo* module_copy = (CvModuleInfo*)malloc( sizeof(*module_copy) +
761                                 name_len + 1 + version_len + 1 );
762
763     *module_copy = *module;
764     module_copy->name = (char*)(module_copy + 1);
765     module_copy->version = (char*)(module_copy + 1) + name_len + 1;
766
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;
770
771     if( CvModule::first == 0 )
772         CvModule::first = module_copy;
773     else
774         CvModule::last->next = module_copy;
775
776     CvModule::last = module_copy;
777
778     return 0;
779 }
780
781 CvModule cxcore_module( &cxcore_info );
782
783 CV_IMPL void
784 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
785 {
786     static char joint_verinfo[1024]   = "";
787     static char plugin_list_buf[1024] = "";
788
789     if( version )
790         *version = 0;
791
792     if( plugin_list )
793         *plugin_list = 0;
794
795     CvModuleInfo* module;
796
797     if( version )
798     {
799         if( name )
800         {
801             size_t i, name_len = strlen(name);
802
803             for( module = CvModule::first; module != 0; module = module->next )
804             {
805                 if( strlen(module->name) == name_len )
806                 {
807                     for( i = 0; i < name_len; i++ )
808                     {
809                         int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
810                         if( c0 != c1 )
811                             break;
812                     }
813                     if( i == name_len )
814                         break;
815                 }
816             }
817             if( !module )
818                 CV_Error( CV_StsObjectNotFound, "The module is not found" );
819
820             *version = module->version;
821         }
822         else
823         {
824             char* ptr = joint_verinfo;
825
826             for( module = CvModule::first; module != 0; module = module->next )
827             {
828                 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
829                 ptr += strlen(ptr);
830             }
831
832             *version = joint_verinfo;
833         }
834     }
835
836     if( plugin_list )
837         *plugin_list = plugin_list_buf;
838 }
839
840 namespace cv
841 {
842
843 #if defined WIN32 || defined _WIN32 || defined WINCE
844
845 struct Mutex::Impl
846 {
847     Impl()
848     {
849 #if (_WIN32_WINNT >= 0x0600)
850         ::InitializeCriticalSectionEx(&cs, 1000, 0);
851 #else
852         ::InitializeCriticalSection(&cs);
853 #endif
854         refcount = 1;
855     }
856     ~Impl() { DeleteCriticalSection(&cs); }
857
858     void lock() { EnterCriticalSection(&cs); }
859     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
860     void unlock() { LeaveCriticalSection(&cs); }
861
862     CRITICAL_SECTION cs;
863     int refcount;
864 };
865
866 #ifndef __GNUC__
867 int _interlockedExchangeAdd(int* addr, int delta)
868 {
869 #if defined _MSC_VER && _MSC_VER >= 1500
870     return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
871 #else
872     return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
873 #endif
874 }
875 #endif // __GNUC__
876
877 #elif defined __APPLE__
878
879 #include <libkern/OSAtomic.h>
880
881 struct Mutex::Impl
882 {
883     Impl() { sl = OS_SPINLOCK_INIT; refcount = 1; }
884     ~Impl() {}
885
886     void lock() { OSSpinLockLock(&sl); }
887     bool trylock() { return OSSpinLockTry(&sl); }
888     void unlock() { OSSpinLockUnlock(&sl); }
889
890     OSSpinLock sl;
891     int refcount;
892 };
893
894 #elif defined __linux__ && !defined ANDROID
895
896 struct Mutex::Impl
897 {
898     Impl() { pthread_spin_init(&sl, 0); refcount = 1; }
899     ~Impl() { pthread_spin_destroy(&sl); }
900
901     void lock() { pthread_spin_lock(&sl); }
902     bool trylock() { return pthread_spin_trylock(&sl) == 0; }
903     void unlock() { pthread_spin_unlock(&sl); }
904
905     pthread_spinlock_t sl;
906     int refcount;
907 };
908
909 #else
910
911 struct Mutex::Impl
912 {
913     Impl() { pthread_mutex_init(&sl, 0); refcount = 1; }
914     ~Impl() { pthread_mutex_destroy(&sl); }
915
916     void lock() { pthread_mutex_lock(&sl); }
917     bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
918     void unlock() { pthread_mutex_unlock(&sl); }
919
920     pthread_mutex_t sl;
921     int refcount;
922 };
923
924 #endif
925
926 Mutex::Mutex()
927 {
928     impl = new Mutex::Impl;
929 }
930
931 Mutex::~Mutex()
932 {
933     if( CV_XADD(&impl->refcount, -1) == 1 )
934         delete impl;
935     impl = 0;
936 }
937
938 Mutex::Mutex(const Mutex& m)
939 {
940     impl = m.impl;
941     CV_XADD(&impl->refcount, 1);
942 }
943
944 Mutex& Mutex::operator = (const Mutex& m)
945 {
946     CV_XADD(&m.impl->refcount, 1);
947     if( CV_XADD(&impl->refcount, -1) == 1 )
948         delete impl;
949     impl = m.impl;
950     return *this;
951 }
952
953 void Mutex::lock() { impl->lock(); }
954 void Mutex::unlock() { impl->unlock(); }
955 bool Mutex::trylock() { return impl->trylock(); }
956
957
958 //////////////////////////////// thread-local storage ////////////////////////////////
959
960 class TLSStorage
961 {
962     std::vector<void*> tlsData_;
963 public:
964     TLSStorage() { tlsData_.reserve(16); }
965     ~TLSStorage();
966     inline void* getData(int key) const
967     {
968         CV_DbgAssert(key >= 0);
969         return (key < (int)tlsData_.size()) ? tlsData_[key] : NULL;
970     }
971     inline void setData(int key, void* data)
972     {
973         CV_DbgAssert(key >= 0);
974         if (key >= (int)tlsData_.size())
975         {
976             tlsData_.resize(key + 1, NULL);
977         }
978         tlsData_[key] = data;
979     }
980
981     inline static TLSStorage* get();
982 };
983
984 #ifdef WIN32
985 #ifdef _MSC_VER
986 #pragma warning(disable:4505) // unreferenced local function has been removed
987 #endif
988
989 #ifdef HAVE_WINRT
990     // using C++11 thread attribute for local thread data
991     static __declspec( thread ) TLSStorage* g_tlsdata = NULL;
992
993     static void deleteThreadData()
994     {
995         if (g_tlsdata)
996         {
997             delete g_tlsdata;
998             g_tlsdata = NULL;
999         }
1000     }
1001
1002     inline TLSStorage* TLSStorage::get()
1003     {
1004         if (!g_tlsdata)
1005         {
1006             g_tlsdata = new TLSStorage;
1007         }
1008         return g_tlsdata;
1009     }
1010 #else
1011 #ifdef WINCE
1012 #   define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
1013 #endif
1014     static DWORD tlsKey = TLS_OUT_OF_INDEXES;
1015
1016     static void deleteThreadData()
1017     {
1018         if(tlsKey != TLS_OUT_OF_INDEXES)
1019         {
1020             delete (TLSStorage*)TlsGetValue(tlsKey);
1021             TlsSetValue(tlsKey, NULL);
1022         }
1023     }
1024
1025     inline TLSStorage* TLSStorage::get()
1026     {
1027         if (tlsKey == TLS_OUT_OF_INDEXES)
1028         {
1029             tlsKey = TlsAlloc();
1030             CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
1031         }
1032         TLSStorage* d = (TLSStorage*)TlsGetValue(tlsKey);
1033         if (!d)
1034         {
1035             d = new TLSStorage;
1036             TlsSetValue(tlsKey, d);
1037         }
1038         return d;
1039     }
1040 #endif //HAVE_WINRT
1041
1042 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
1043 #ifdef HAVE_WINRT
1044     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1045 #endif
1046
1047 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID);
1048
1049 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID)
1050 {
1051     if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1052     {
1053         cv::deleteThreadAllocData();
1054         cv::deleteThreadRNGData();
1055         cv::deleteThreadData();
1056     }
1057     return TRUE;
1058 }
1059 #endif
1060
1061 #else
1062     static pthread_key_t tlsKey = 0;
1063     static pthread_once_t tlsKeyOnce = PTHREAD_ONCE_INIT;
1064
1065     static void deleteTLSStorage(void* data)
1066     {
1067         delete (TLSStorage*)data;
1068     }
1069
1070     static void makeKey()
1071     {
1072         int errcode = pthread_key_create(&tlsKey, deleteTLSStorage);
1073         CV_Assert(errcode == 0);
1074     }
1075
1076     inline TLSStorage* TLSStorage::get()
1077     {
1078         pthread_once(&tlsKeyOnce, makeKey);
1079         TLSStorage* d = (TLSStorage*)pthread_getspecific(tlsKey);
1080         if( !d )
1081         {
1082             d = new TLSStorage;
1083             pthread_setspecific(tlsKey, d);
1084         }
1085         return d;
1086     }
1087 #endif
1088
1089 class TLSContainerStorage
1090 {
1091     cv::Mutex mutex_;
1092     std::vector<TLSDataContainer*> tlsContainers_;
1093 public:
1094     TLSContainerStorage() { }
1095     ~TLSContainerStorage()
1096     {
1097         for (size_t i = 0; i < tlsContainers_.size(); i++)
1098         {
1099             CV_DbgAssert(tlsContainers_[i] == NULL); // not all keys released
1100             tlsContainers_[i] = NULL;
1101         }
1102     }
1103
1104     int allocateKey(TLSDataContainer* pContainer)
1105     {
1106         cv::AutoLock lock(mutex_);
1107         tlsContainers_.push_back(pContainer);
1108         return (int)tlsContainers_.size() - 1;
1109     }
1110     void releaseKey(int id, TLSDataContainer* pContainer)
1111     {
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
1116     }
1117
1118     void destroyData(int key, void* data)
1119     {
1120         cv::AutoLock lock(mutex_);
1121         TLSDataContainer* k = tlsContainers_[key];
1122         if (!k)
1123             return;
1124         try
1125         {
1126             k->deleteDataInstance(data);
1127         }
1128         catch (...)
1129         {
1130             CV_DbgAssert(k == NULL); // Debug this!
1131         }
1132     }
1133 };
1134
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()
1138 {
1139     static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage();
1140     return *tlsContainerStorage;
1141 }
1142
1143 TLSDataContainer::TLSDataContainer()
1144     : key_(-1)
1145 {
1146     key_ = getTLSContainerStorage().allocateKey(this);
1147 }
1148
1149 TLSDataContainer::~TLSDataContainer()
1150 {
1151     getTLSContainerStorage().releaseKey(key_, this);
1152     key_ = -1;
1153 }
1154
1155 void* TLSDataContainer::getData() const
1156 {
1157     CV_Assert(key_ >= 0);
1158     TLSStorage* tlsData = TLSStorage::get();
1159     void* data = tlsData->getData(key_);
1160     if (!data)
1161     {
1162         data = this->createDataInstance();
1163         CV_DbgAssert(data != NULL);
1164         tlsData->setData(key_, data);
1165     }
1166     return data;
1167 }
1168
1169 TLSStorage::~TLSStorage()
1170 {
1171     for (int i = 0; i < (int)tlsData_.size(); i++)
1172     {
1173         void*& data = tlsData_[i];
1174         if (data)
1175         {
1176             getTLSContainerStorage().destroyData(i, data);
1177             data = NULL;
1178         }
1179     }
1180     tlsData_.clear();
1181 }
1182
1183 } // namespace cv
1184
1185 /* End of file. */