ba2c9d536f50c46736a0a9ca59a8762ea85b4239
[platform/upstream/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 // Copyright (C) 2015, Itseez Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43
44 #include "precomp.hpp"
45 #include <iostream>
46
47 namespace cv {
48
49 static Mutex* __initialization_mutex = NULL;
50 Mutex& getInitializationMutex()
51 {
52     if (__initialization_mutex == NULL)
53         __initialization_mutex = new Mutex();
54     return *__initialization_mutex;
55 }
56 // force initialization (single-threaded environment)
57 Mutex* __initialization_mutex_initializer = &getInitializationMutex();
58
59 } // namespace cv
60
61 #ifdef _MSC_VER
62 # if _MSC_VER >= 1700
63 #  pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
64 # endif
65 #endif
66
67 #if defined ANDROID || defined __linux__ || defined __FreeBSD__
68 #  include <unistd.h>
69 #  include <fcntl.h>
70 #  include <elf.h>
71 #if defined ANDROID || defined __linux__
72 #  include <linux/auxvec.h>
73 #endif
74 #endif
75
76 #if defined WIN32 || defined _WIN32 || defined WINCE
77 #ifndef _WIN32_WINNT           // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
78   #define _WIN32_WINNT 0x0400  // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
79 #endif
80 #include <windows.h>
81 #if (_WIN32_WINNT >= 0x0602)
82   #include <synchapi.h>
83 #endif
84 #undef small
85 #undef min
86 #undef max
87 #undef abs
88 #include <tchar.h>
89
90 #ifdef WINRT
91 #include <wrl/client.h>
92 #ifndef __cplusplus_winrt
93 #include <windows.storage.h>
94 #pragma comment(lib, "runtimeobject.lib")
95 #endif
96
97 std::wstring GetTempPathWinRT()
98 {
99 #ifdef __cplusplus_winrt
100     return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
101 #else
102     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
103     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
104     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
105     Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
106     HSTRING str;
107     HSTRING_HEADER hstrHead;
108     std::wstring wstr;
109     if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
110                                             (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
111         return wstr;
112     if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
113         return wstr;
114     if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
115         return wstr;
116     if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
117         return wstr;
118     if (FAILED(storagefolderRef.As(&storageitemRef)))
119         return wstr;
120     str = NULL;
121     if (FAILED(storageitemRef->get_Path(&str)))
122         return wstr;
123     wstr = WindowsGetStringRawBuffer(str, NULL);
124     WindowsDeleteString(str);
125     return wstr;
126 #endif
127 }
128
129 std::wstring GetTempFileNameWinRT(std::wstring prefix)
130 {
131     wchar_t guidStr[40];
132     GUID g;
133     CoCreateGuid(&g);
134     wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
135     swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
136              g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
137              UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
138              UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
139
140     return prefix.append(std::wstring(guidStr));
141 }
142
143 #endif
144 #else
145 #include <pthread.h>
146 #include <sys/time.h>
147 #include <time.h>
148
149 #if defined __MACH__ && defined __APPLE__
150 #include <mach/mach.h>
151 #include <mach/mach_time.h>
152 #endif
153
154 #endif
155
156 #ifdef _OPENMP
157 #include "omp.h"
158 #endif
159
160 #include <stdarg.h>
161
162 #if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__
163 #include <unistd.h>
164 #include <stdio.h>
165 #include <sys/types.h>
166 #if defined ANDROID
167 #include <sys/sysconf.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 bool checkHardwareSupport(int feature)
202 {
203     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
204     return cv::hal::checkHardwareSupport(feature);
205 }
206
207 void setUseOptimized( bool flag )
208 {
209     cv::hal::setUseOptimized(flag);
210
211     ipp::setUseIPP(flag);
212 #ifdef HAVE_OPENCL
213     ocl::setUseOpenCL(flag);
214 #endif
215 #ifdef HAVE_TEGRA_OPTIMIZATION
216     ::tegra::setUseTegra(flag);
217 #endif
218 }
219
220 bool useOptimized(void)
221 {
222     return cv::hal::useOptimized();
223 }
224
225 int64 getTickCount(void)
226 {
227 #if defined WIN32 || defined _WIN32 || defined WINCE
228     LARGE_INTEGER counter;
229     QueryPerformanceCounter( &counter );
230     return (int64)counter.QuadPart;
231 #elif defined __linux || defined __linux__
232     struct timespec tp;
233     clock_gettime(CLOCK_MONOTONIC, &tp);
234     return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
235 #elif defined __MACH__ && defined __APPLE__
236     return (int64)mach_absolute_time();
237 #else
238     struct timeval tv;
239     struct timezone tz;
240     gettimeofday( &tv, &tz );
241     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
242 #endif
243 }
244
245 double getTickFrequency(void)
246 {
247 #if defined WIN32 || defined _WIN32 || defined WINCE
248     LARGE_INTEGER freq;
249     QueryPerformanceFrequency(&freq);
250     return (double)freq.QuadPart;
251 #elif defined __linux || defined __linux__
252     return 1e9;
253 #elif defined __MACH__ && defined __APPLE__
254     static double freq = 0;
255     if( freq == 0 )
256     {
257         mach_timebase_info_data_t sTimebaseInfo;
258         mach_timebase_info(&sTimebaseInfo);
259         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
260     }
261     return freq;
262 #else
263     return 1e6;
264 #endif
265 }
266
267 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
268 #if defined(__i386__)
269
270 int64 getCPUTickCount(void)
271 {
272     int64 x;
273     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
274     return x;
275 }
276 #elif defined(__x86_64__)
277
278 int64 getCPUTickCount(void)
279 {
280     unsigned hi, lo;
281     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
282     return (int64)lo | ((int64)hi << 32);
283 }
284
285 #elif defined(__ppc__)
286
287 int64 getCPUTickCount(void)
288 {
289     int64 result = 0;
290     unsigned upper, lower, tmp;
291     __asm__ volatile(
292                      "0:                  \n"
293                      "\tmftbu   %0           \n"
294                      "\tmftb    %1           \n"
295                      "\tmftbu   %2           \n"
296                      "\tcmpw    %2,%0        \n"
297                      "\tbne     0b         \n"
298                      : "=r"(upper),"=r"(lower),"=r"(tmp)
299                      );
300     return lower | ((int64)upper << 32);
301 }
302
303 #else
304
305 #error "RDTSC not defined"
306
307 #endif
308
309 #elif defined _MSC_VER && defined WIN32 && defined _M_IX86
310
311 int64 getCPUTickCount(void)
312 {
313     __asm _emit 0x0f;
314     __asm _emit 0x31;
315 }
316
317 #else
318
319 //#ifdef HAVE_IPP
320 //int64 getCPUTickCount(void)
321 //{
322 //    return ippGetCpuClocks();
323 //}
324 //#else
325 int64 getCPUTickCount(void)
326 {
327     return getTickCount();
328 }
329 //#endif
330
331 #endif
332
333 const String& getBuildInformation()
334 {
335     static String build_info =
336 #include "version_string.inc"
337     ;
338     return build_info;
339 }
340
341 String format( const char* fmt, ... )
342 {
343     AutoBuffer<char, 1024> buf;
344
345     for ( ; ; )
346     {
347         va_list va;
348         va_start(va, fmt);
349         int bsize = static_cast<int>(buf.size()),
350                 len = vsnprintf((char *)buf, bsize, fmt, va);
351         va_end(va);
352
353         if (len < 0 || len >= bsize)
354         {
355             buf.resize(std::max(bsize << 1, len + 1));
356             continue;
357         }
358         return String((char *)buf, len);
359     }
360 }
361
362 String tempfile( const char* suffix )
363 {
364     String fname;
365 #ifndef WINRT
366     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
367 #endif
368
369 #if defined WIN32 || defined _WIN32
370 #ifdef WINRT
371     RoInitialize(RO_INIT_MULTITHREADED);
372     std::wstring temp_dir = GetTempPathWinRT();
373
374     std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
375     if (temp_file.empty())
376         return String();
377
378     temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
379     DeleteFileW(temp_file.c_str());
380
381     char aname[MAX_PATH];
382     size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
383     CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
384     fname = String(aname);
385     RoUninitialize();
386 #else
387     char temp_dir2[MAX_PATH] = { 0 };
388     char temp_file[MAX_PATH] = { 0 };
389
390     if (temp_dir == 0 || temp_dir[0] == 0)
391     {
392         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
393         temp_dir = temp_dir2;
394     }
395     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
396         return String();
397
398     DeleteFileA(temp_file);
399
400     fname = temp_file;
401 #endif
402 # else
403 #  ifdef ANDROID
404     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
405     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
406 #  else
407     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
408 #  endif
409
410     if (temp_dir == 0 || temp_dir[0] == 0)
411         fname = defaultTemplate;
412     else
413     {
414         fname = temp_dir;
415         char ech = fname[fname.size() - 1];
416         if(ech != '/' && ech != '\\')
417             fname = fname + "/";
418         fname = fname + "__opencv_temp.XXXXXX";
419     }
420
421     const int fd = mkstemp((char*)fname.c_str());
422     if (fd == -1) return String();
423
424     close(fd);
425     remove(fname.c_str());
426 # endif
427
428     if (suffix)
429     {
430         if (suffix[0] != '.')
431             return fname + "." + suffix;
432         else
433             return fname + suffix;
434     }
435     return fname;
436 }
437
438 static CvErrorCallback customErrorCallback = 0;
439 static void* customErrorCallbackData = 0;
440 static bool breakOnError = false;
441
442 bool setBreakOnError(bool value)
443 {
444     bool prevVal = breakOnError;
445     breakOnError = value;
446     return prevVal;
447 }
448
449 void error( const Exception& exc )
450 {
451     if (customErrorCallback != 0)
452         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
453                             exc.file.c_str(), exc.line, customErrorCallbackData);
454     else
455     {
456         const char* errorStr = cvErrorStr(exc.code);
457         char buf[1 << 16];
458
459         sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
460             errorStr, exc.err.c_str(), exc.func.size() > 0 ?
461             exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
462         fprintf( stderr, "%s\n", buf );
463         fflush( stderr );
464 #  ifdef __ANDROID__
465         __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
466 #  endif
467     }
468
469     if(breakOnError)
470     {
471         static volatile int* p = 0;
472         *p = 0;
473     }
474
475     throw exc;
476 }
477
478 void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
479 {
480     error(cv::Exception(_code, _err, _func, _file, _line));
481 }
482
483 CvErrorCallback
484 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
485 {
486     if( prevUserdata )
487         *prevUserdata = customErrorCallbackData;
488
489     CvErrorCallback prevCallback = customErrorCallback;
490
491     customErrorCallback     = errCallback;
492     customErrorCallbackData = userdata;
493
494     return prevCallback;
495 }
496
497 }
498
499 CV_IMPL int cvCheckHardwareSupport(int feature)
500 {
501     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
502     return cv::hal::checkHardwareSupport(feature);
503 }
504
505 CV_IMPL int cvUseOptimized( int flag )
506 {
507     int prevMode = cv::useOptimized();
508     cv::setUseOptimized( flag != 0 );
509     return prevMode;
510 }
511
512 CV_IMPL int64  cvGetTickCount(void)
513 {
514     return cv::getTickCount();
515 }
516
517 CV_IMPL double cvGetTickFrequency(void)
518 {
519     return cv::getTickFrequency()*1e-6;
520 }
521
522 CV_IMPL CvErrorCallback
523 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
524 {
525     return cv::redirectError(errCallback, userdata, prevUserdata);
526 }
527
528 CV_IMPL int cvNulDevReport( int, const char*, const char*,
529                             const char*, int, void* )
530 {
531     return 0;
532 }
533
534 CV_IMPL int cvStdErrReport( int, const char*, const char*,
535                             const char*, int, void* )
536 {
537     return 0;
538 }
539
540 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
541                             const char*, int, void* )
542 {
543     return 0;
544 }
545
546 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
547 {
548     return 0;
549 }
550
551
552 CV_IMPL const char* cvErrorStr( int status )
553 {
554     static char buf[256];
555
556     switch (status)
557     {
558     case CV_StsOk :                  return "No Error";
559     case CV_StsBackTrace :           return "Backtrace";
560     case CV_StsError :               return "Unspecified error";
561     case CV_StsInternal :            return "Internal error";
562     case CV_StsNoMem :               return "Insufficient memory";
563     case CV_StsBadArg :              return "Bad argument";
564     case CV_StsNoConv :              return "Iterations do not converge";
565     case CV_StsAutoTrace :           return "Autotrace call";
566     case CV_StsBadSize :             return "Incorrect size of input array";
567     case CV_StsNullPtr :             return "Null pointer";
568     case CV_StsDivByZero :           return "Division by zero occured";
569     case CV_BadStep :                return "Image step is wrong";
570     case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
571     case CV_StsObjectNotFound :      return "Requested object was not found";
572     case CV_BadDepth :               return "Input image depth is not supported by function";
573     case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
574     case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
575     case CV_StsOutOfRange :          return "One of arguments\' values is out of range";
576     case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
577     case CV_BadCOI :                 return "Input COI is not supported";
578     case CV_BadNumChannels :         return "Bad number of channels";
579     case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
580     case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
581     case CV_StsBadMask :             return "Bad type of mask argument";
582     case CV_StsParseError :          return "Parsing error";
583     case CV_StsNotImplemented :      return "The function/feature is not implemented";
584     case CV_StsBadMemBlock :         return "Memory block has been corrupted";
585     case CV_StsAssert :              return "Assertion failed";
586     case CV_GpuNotSupported :        return "No CUDA support";
587     case CV_GpuApiCallError :        return "Gpu API call";
588     case CV_OpenGlNotSupported :     return "No OpenGL support";
589     case CV_OpenGlApiCallError :     return "OpenGL API call";
590     };
591
592     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
593     return buf;
594 }
595
596 CV_IMPL int cvGetErrMode(void)
597 {
598     return 0;
599 }
600
601 CV_IMPL int cvSetErrMode(int)
602 {
603     return 0;
604 }
605
606 CV_IMPL int cvGetErrStatus(void)
607 {
608     return 0;
609 }
610
611 CV_IMPL void cvSetErrStatus(int)
612 {
613 }
614
615
616 CV_IMPL void cvError( int code, const char* func_name,
617                       const char* err_msg,
618                       const char* file_name, int line )
619 {
620     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
621 }
622
623 /* function, which converts int to int */
624 CV_IMPL int
625 cvErrorFromIppStatus( int status )
626 {
627     switch (status)
628     {
629     case CV_BADSIZE_ERR:               return CV_StsBadSize;
630     case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
631     case CV_NULLPTR_ERR:               return CV_StsNullPtr;
632     case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
633     case CV_BADSTEP_ERR:               return CV_BadStep;
634     case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
635     case CV_BADARG_ERR:                return CV_StsBadArg;
636     case CV_NOTDEFINED_ERR:            return CV_StsError;
637     case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
638     case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
639     case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
640     case CV_BADDEPTH_ERR:              return CV_BadDepth;
641     case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
642     case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
643     case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
644     case CV_BADFLAG_ERR:               return CV_StsBadFlag;
645     case CV_BADRANGE_ERR:              return CV_StsBadArg;
646     case CV_BADCOEF_ERR:               return CV_StsBadArg;
647     case CV_BADFACTOR_ERR:             return CV_StsBadArg;
648     case CV_BADPOINT_ERR:              return CV_StsBadPoint;
649
650     default:
651       return CV_StsError;
652     }
653 }
654
655 namespace cv {
656 bool __termination = false;
657 }
658
659 namespace cv
660 {
661
662 #if defined WIN32 || defined _WIN32 || defined WINCE
663
664 struct Mutex::Impl
665 {
666     Impl()
667     {
668 #if (_WIN32_WINNT >= 0x0600)
669         ::InitializeCriticalSectionEx(&cs, 1000, 0);
670 #else
671         ::InitializeCriticalSection(&cs);
672 #endif
673         refcount = 1;
674     }
675     ~Impl() { DeleteCriticalSection(&cs); }
676
677     void lock() { EnterCriticalSection(&cs); }
678     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
679     void unlock() { LeaveCriticalSection(&cs); }
680
681     CRITICAL_SECTION cs;
682     int refcount;
683 };
684
685 #else
686
687 struct Mutex::Impl
688 {
689     Impl()
690     {
691         pthread_mutexattr_t attr;
692         pthread_mutexattr_init(&attr);
693         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
694         pthread_mutex_init(&mt, &attr);
695         pthread_mutexattr_destroy(&attr);
696
697         refcount = 1;
698     }
699     ~Impl() { pthread_mutex_destroy(&mt); }
700
701     void lock() { pthread_mutex_lock(&mt); }
702     bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
703     void unlock() { pthread_mutex_unlock(&mt); }
704
705     pthread_mutex_t mt;
706     int refcount;
707 };
708
709 #endif
710
711 Mutex::Mutex()
712 {
713     impl = new Mutex::Impl;
714 }
715
716 Mutex::~Mutex()
717 {
718     if( CV_XADD(&impl->refcount, -1) == 1 )
719         delete impl;
720     impl = 0;
721 }
722
723 Mutex::Mutex(const Mutex& m)
724 {
725     impl = m.impl;
726     CV_XADD(&impl->refcount, 1);
727 }
728
729 Mutex& Mutex::operator = (const Mutex& m)
730 {
731     CV_XADD(&m.impl->refcount, 1);
732     if( CV_XADD(&impl->refcount, -1) == 1 )
733         delete impl;
734     impl = m.impl;
735     return *this;
736 }
737
738 void Mutex::lock() { impl->lock(); }
739 void Mutex::unlock() { impl->unlock(); }
740 bool Mutex::trylock() { return impl->trylock(); }
741
742
743 //////////////////////////////// thread-local storage ////////////////////////////////
744
745 #ifdef WIN32
746 #ifdef _MSC_VER
747 #pragma warning(disable:4505) // unreferenced local function has been removed
748 #endif
749 #ifndef TLS_OUT_OF_INDEXES
750 #define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
751 #endif
752 #endif
753
754 // TLS platform abstraction layer
755 class TlsAbstraction
756 {
757 public:
758     TlsAbstraction();
759     ~TlsAbstraction();
760     void* GetData() const;
761     void  SetData(void *pData);
762
763 private:
764 #ifdef WIN32
765 #ifndef WINRT
766     DWORD tlsKey;
767 #endif
768 #else // WIN32
769     pthread_key_t  tlsKey;
770 #endif
771 };
772
773 #ifdef WIN32
774 #ifdef WINRT
775 static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
776 TlsAbstraction::TlsAbstraction() {}
777 TlsAbstraction::~TlsAbstraction() {}
778 void* TlsAbstraction::GetData() const
779 {
780     return tlsData;
781 }
782 void  TlsAbstraction::SetData(void *pData)
783 {
784     tlsData = pData;
785 }
786 #else //WINRT
787 TlsAbstraction::TlsAbstraction()
788 {
789     tlsKey = TlsAlloc();
790     CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
791 }
792 TlsAbstraction::~TlsAbstraction()
793 {
794     TlsFree(tlsKey);
795 }
796 void* TlsAbstraction::GetData() const
797 {
798     return TlsGetValue(tlsKey);
799 }
800 void  TlsAbstraction::SetData(void *pData)
801 {
802     CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
803 }
804 #endif
805 #else // WIN32
806 TlsAbstraction::TlsAbstraction()
807 {
808     CV_Assert(pthread_key_create(&tlsKey, NULL) == 0);
809 }
810 TlsAbstraction::~TlsAbstraction()
811 {
812     CV_Assert(pthread_key_delete(tlsKey) == 0);
813 }
814 void* TlsAbstraction::GetData() const
815 {
816     return pthread_getspecific(tlsKey);
817 }
818 void  TlsAbstraction::SetData(void *pData)
819 {
820     CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
821 }
822 #endif
823
824 // Per-thread data structure
825 struct ThreadData
826 {
827     ThreadData()
828     {
829         idx = 0;
830         slots.reserve(32);
831     }
832
833     std::vector<void*> slots; // Data array for a thread
834     size_t idx;               // Thread index in TLS storage. This is not OS thread ID!
835 };
836
837 // Main TLS storage class
838 class TlsStorage
839 {
840 public:
841     TlsStorage()
842     {
843         tlsSlots.reserve(32);
844         threads.reserve(32);
845     }
846     ~TlsStorage()
847     {
848         for(size_t i = 0; i < threads.size(); i++)
849         {
850             if(threads[i])
851             {
852                 /* Current architecture doesn't allow proper global objects relase, so this check can cause crashes
853
854                 // Check if all slots were properly cleared
855                 for(size_t j = 0; j < threads[i]->slots.size(); j++)
856                 {
857                     CV_Assert(threads[i]->slots[j] == 0);
858                 }
859                 */
860                 delete threads[i];
861             }
862         }
863         threads.clear();
864     }
865
866     void releaseThread()
867     {
868         AutoLock guard(mtxGlobalAccess);
869         ThreadData *pTD = (ThreadData*)tls.GetData();
870         for(size_t i = 0; i < threads.size(); i++)
871         {
872             if(pTD == threads[i])
873             {
874                 threads[i] = 0;
875                 break;
876             }
877         }
878         tls.SetData(0);
879         delete pTD;
880     }
881
882     // Reserve TLS storage index
883     size_t reserveSlot()
884     {
885         AutoLock guard(mtxGlobalAccess);
886
887         // Find unused slots
888         for(size_t slot = 0; slot < tlsSlots.size(); slot++)
889         {
890             if(!tlsSlots[slot])
891             {
892                 tlsSlots[slot] = 1;
893                 return slot;
894             }
895         }
896
897         // Create new slot
898         tlsSlots.push_back(1);
899         return (tlsSlots.size()-1);
900     }
901
902     // Release TLS storage index and pass assosiated data to caller
903     void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec)
904     {
905         AutoLock guard(mtxGlobalAccess);
906         CV_Assert(tlsSlots.size() > slotIdx);
907
908         for(size_t i = 0; i < threads.size(); i++)
909         {
910             std::vector<void*>& thread_slots = threads[i]->slots;
911             if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
912             {
913                 dataVec.push_back(thread_slots[slotIdx]);
914                 threads[i]->slots[slotIdx] = 0;
915             }
916         }
917
918         tlsSlots[slotIdx] = 0;
919     }
920
921     // Get data by TLS storage index
922     void* getData(size_t slotIdx) const
923     {
924         CV_Assert(tlsSlots.size() > slotIdx);
925
926         ThreadData* threadData = (ThreadData*)tls.GetData();
927         if(threadData && threadData->slots.size() > slotIdx)
928             return threadData->slots[slotIdx];
929
930         return NULL;
931     }
932
933     // Gather data from threads by TLS storage index
934     void gather(size_t slotIdx, std::vector<void*> &dataVec)
935     {
936         AutoLock guard(mtxGlobalAccess);
937         CV_Assert(tlsSlots.size() > slotIdx);
938
939         for(size_t i = 0; i < threads.size(); i++)
940         {
941             std::vector<void*>& thread_slots = threads[i]->slots;
942             if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
943                 dataVec.push_back(thread_slots[slotIdx]);
944         }
945     }
946
947     // Set data to storage index
948     void setData(size_t slotIdx, void* pData)
949     {
950         CV_Assert(tlsSlots.size() > slotIdx && pData != NULL);
951
952         ThreadData* threadData = (ThreadData*)tls.GetData();
953         if(!threadData)
954         {
955             threadData = new ThreadData;
956             tls.SetData((void*)threadData);
957             {
958                 AutoLock guard(mtxGlobalAccess);
959                 threadData->idx = threads.size();
960                 threads.push_back(threadData);
961             }
962         }
963
964         if(slotIdx >= threadData->slots.size())
965         {
966             AutoLock guard(mtxGlobalAccess);
967             while(slotIdx >= threadData->slots.size())
968                 threadData->slots.push_back(NULL);
969         }
970         threadData->slots[slotIdx] = pData;
971     }
972
973 private:
974     TlsAbstraction tls; // TLS abstraction layer instance
975
976     Mutex  mtxGlobalAccess;           // Shared objects operation guard
977     std::vector<int> tlsSlots;        // TLS keys state
978     std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
979 };
980
981 // Create global TLS storage object
982 static TlsStorage &getTlsStorage()
983 {
984     CV_SINGLETON_LAZY_INIT_REF(TlsStorage, new TlsStorage())
985 }
986
987 TLSDataContainer::TLSDataContainer()
988 {
989     key_ = (int)getTlsStorage().reserveSlot(); // Reserve key from TLS storage
990 }
991
992 TLSDataContainer::~TLSDataContainer()
993 {
994     CV_Assert(key_ == -1); // Key must be released in child object
995 }
996
997 void TLSDataContainer::gatherData(std::vector<void*> &data) const
998 {
999     getTlsStorage().gather(key_, data);
1000 }
1001
1002 void TLSDataContainer::release()
1003 {
1004     std::vector<void*> data;
1005     data.reserve(32);
1006     getTlsStorage().releaseSlot(key_, data); // Release key and get stored data for proper destruction
1007     for(size_t i = 0; i < data.size(); i++)  // Delete all assosiated data
1008         deleteDataInstance(data[i]);
1009     key_ = -1;
1010 }
1011
1012 void* TLSDataContainer::getData() const
1013 {
1014     void* pData = getTlsStorage().getData(key_); // Check if data was already allocated
1015     if(!pData)
1016     {
1017         // Create new data instance and save it to TLS storage
1018         pData = createDataInstance();
1019         getTlsStorage().setData(key_, pData);
1020     }
1021     return pData;
1022 }
1023
1024 TLSData<CoreTLSData>& getCoreTlsData()
1025 {
1026     CV_SINGLETON_LAZY_INIT_REF(TLSData<CoreTLSData>, new TLSData<CoreTLSData>())
1027 }
1028
1029 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
1030 #ifdef WINRT
1031     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
1032 #endif
1033
1034 extern "C"
1035 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved);
1036
1037 extern "C"
1038 BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
1039 {
1040     if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
1041     {
1042         if (lpReserved != NULL) // called after ExitProcess() call
1043         {
1044             cv::__termination = true;
1045         }
1046         else
1047         {
1048             // Not allowed to free resources if lpReserved is non-null
1049             // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
1050             cv::deleteThreadAllocData();
1051             cv::getTlsStorage().releaseThread();
1052         }
1053     }
1054     return TRUE;
1055 }
1056 #endif
1057
1058 #ifdef CV_COLLECT_IMPL_DATA
1059 ImplCollector& getImplData()
1060 {
1061     CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector())
1062 }
1063
1064 void setImpl(int flags)
1065 {
1066     cv::AutoLock lock(getImplData().mutex);
1067
1068     getImplData().implFlags = flags;
1069     getImplData().implCode.clear();
1070     getImplData().implFun.clear();
1071 }
1072
1073 void addImpl(int flag, const char* func)
1074 {
1075     cv::AutoLock lock(getImplData().mutex);
1076
1077     getImplData().implFlags |= flag;
1078     if(func) // use lazy collection if name was not specified
1079     {
1080         size_t index = getImplData().implCode.size();
1081         if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
1082         {
1083             getImplData().implCode.push_back(flag);
1084             getImplData().implFun.push_back(func);
1085         }
1086     }
1087 }
1088
1089 int getImpl(std::vector<int> &impl, std::vector<String> &funName)
1090 {
1091     cv::AutoLock lock(getImplData().mutex);
1092
1093     impl    = getImplData().implCode;
1094     funName = getImplData().implFun;
1095     return getImplData().implFlags; // return actual flags for lazy collection
1096 }
1097
1098 bool useCollection()
1099 {
1100     return getImplData().useCollection;
1101 }
1102
1103 void setUseCollection(bool flag)
1104 {
1105     cv::AutoLock lock(getImplData().mutex);
1106
1107     getImplData().useCollection = flag;
1108 }
1109 #endif
1110
1111 namespace ipp
1112 {
1113
1114 struct IPPInitSingelton
1115 {
1116 public:
1117     IPPInitSingelton()
1118     {
1119         useIPP      = true;
1120         ippStatus   = 0;
1121         funcname    = NULL;
1122         filename    = NULL;
1123         linen       = 0;
1124         ippFeatures = 0;
1125
1126 #ifdef HAVE_IPP
1127         const char* pIppEnv = getenv("OPENCV_IPP");
1128         cv::String env = pIppEnv;
1129         if(env.size())
1130         {
1131             if(env == "disabled")
1132             {
1133                 std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl;
1134                 useIPP = false;
1135             }
1136 #if IPP_VERSION_X100 >= 900
1137             else if(env == "sse")
1138                 ippFeatures = ippCPUID_SSE;
1139             else if(env == "sse2")
1140                 ippFeatures = ippCPUID_SSE2;
1141             else if(env == "sse3")
1142                 ippFeatures = ippCPUID_SSE3;
1143             else if(env == "ssse3")
1144                 ippFeatures = ippCPUID_SSSE3;
1145             else if(env == "sse41")
1146                 ippFeatures = ippCPUID_SSE41;
1147             else if(env == "sse42")
1148                 ippFeatures = ippCPUID_SSE42;
1149             else if(env == "avx")
1150                 ippFeatures = ippCPUID_AVX;
1151             else if(env == "avx2")
1152                 ippFeatures = ippCPUID_AVX2;
1153 #endif
1154             else
1155                 std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << std::endl;
1156         }
1157
1158         IPP_INITIALIZER(ippFeatures)
1159 #endif
1160     }
1161
1162     bool useIPP;
1163
1164     int         ippStatus; // 0 - all is ok, -1 - IPP functions failed
1165     const char *funcname;
1166     const char *filename;
1167     int         linen;
1168     int         ippFeatures;
1169 };
1170
1171 static IPPInitSingelton& getIPPSingelton()
1172 {
1173     CV_SINGLETON_LAZY_INIT_REF(IPPInitSingelton, new IPPInitSingelton())
1174 }
1175
1176 int getIppFeatures()
1177 {
1178 #ifdef HAVE_IPP
1179     return getIPPSingelton().ippFeatures;
1180 #else
1181     return 0;
1182 #endif
1183 }
1184
1185 void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
1186 {
1187     getIPPSingelton().ippStatus = status;
1188     getIPPSingelton().funcname = _funcname;
1189     getIPPSingelton().filename = _filename;
1190     getIPPSingelton().linen = _line;
1191 }
1192
1193 int getIppStatus()
1194 {
1195     return getIPPSingelton().ippStatus;
1196 }
1197
1198 String getIppErrorLocation()
1199 {
1200     return format("%s:%d %s", getIPPSingelton().filename ? getIPPSingelton().filename : "", getIPPSingelton().linen, getIPPSingelton().funcname ? getIPPSingelton().funcname : "");
1201 }
1202
1203 bool useIPP()
1204 {
1205 #ifdef HAVE_IPP
1206     CoreTLSData* data = getCoreTlsData().get();
1207     if(data->useIPP < 0)
1208     {
1209         data->useIPP = getIPPSingelton().useIPP;
1210     }
1211     return (data->useIPP > 0);
1212 #else
1213     return false;
1214 #endif
1215 }
1216
1217 void setUseIPP(bool flag)
1218 {
1219     CoreTLSData* data = getCoreTlsData().get();
1220 #ifdef HAVE_IPP
1221     data->useIPP = flag;
1222 #else
1223     (void)flag;
1224     data->useIPP = false;
1225 #endif
1226 }
1227
1228 } // namespace ipp
1229
1230 } // namespace cv
1231
1232 #ifdef HAVE_TEGRA_OPTIMIZATION
1233
1234 namespace tegra {
1235
1236 bool useTegra()
1237 {
1238     cv::CoreTLSData* data = cv::getCoreTlsData().get();
1239
1240     if (data->useTegra < 0)
1241     {
1242         const char* pTegraEnv = getenv("OPENCV_TEGRA");
1243         if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
1244             data->useTegra = false;
1245         else
1246             data->useTegra = true;
1247     }
1248
1249     return (data->useTegra > 0);
1250 }
1251
1252 void setUseTegra(bool flag)
1253 {
1254     cv::CoreTLSData* data = cv::getCoreTlsData().get();
1255     data->useTegra = flag;
1256 }
1257
1258 } // namespace tegra
1259
1260 #endif
1261
1262 /* End of file. */