Merge pull request #1263 from abidrahmank:pyCLAHE_24
[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 #if defined WIN32 || defined _WIN32 || defined WINCE
46 #ifndef _WIN32_WINNT           // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
47   #define _WIN32_WINNT 0x0400  // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
48 #endif
49 #include <windows.h>
50 #if (_WIN32_WINNT >= 0x0602)
51   #include <synchapi.h>
52 #endif
53 #undef small
54 #undef min
55 #undef max
56 #undef abs
57 #include <tchar.h>
58 #if defined _MSC_VER
59   #if _MSC_VER >= 1400
60     #include <intrin.h>
61   #elif defined _M_IX86
62     static void __cpuid(int* cpuid_data, int)
63     {
64         __asm
65         {
66             push ebx
67             push edi
68             mov edi, cpuid_data
69             mov eax, 1
70             cpuid
71             mov [edi], eax
72             mov [edi + 4], ebx
73             mov [edi + 8], ecx
74             mov [edi + 12], edx
75             pop edi
76             pop ebx
77         }
78     }
79   #endif
80 #endif
81
82 #ifdef HAVE_WINRT
83 #include <wrl/client.h>
84
85 std::wstring GetTempPathWinRT()
86 {
87     return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
88 }
89
90 std::wstring GetTempFileNameWinRT(std::wstring prefix)
91 {
92     wchar_t guidStr[40];
93     GUID g;
94     CoCreateGuid(&g);
95     wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
96     swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
97              g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
98              UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
99              UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
100
101     return prefix + std::wstring(guidStr);
102 }
103
104 #endif
105 #else
106 #include <pthread.h>
107 #include <sys/time.h>
108 #include <time.h>
109
110 #if defined __MACH__ && defined __APPLE__
111 #include <mach/mach.h>
112 #include <mach/mach_time.h>
113 #endif
114
115 #endif
116
117 #ifdef _OPENMP
118 #include "omp.h"
119 #endif
120
121 #include <stdarg.h>
122
123 #if defined __linux__ || defined __APPLE__
124 #include <unistd.h>
125 #include <stdio.h>
126 #include <sys/types.h>
127 #if defined ANDROID
128 #include <sys/sysconf.h>
129 #else
130 #include <sys/sysctl.h>
131 #endif
132 #endif
133
134 #ifdef ANDROID
135 # include <android/log.h>
136 #endif
137
138 namespace cv
139 {
140
141 Exception::Exception() { code = 0; line = 0; }
142
143 Exception::Exception(int _code, const string& _err, const string& _func, const string& _file, int _line)
144 : code(_code), err(_err), func(_func), file(_file), line(_line)
145 {
146     formatMessage();
147 }
148
149 Exception::~Exception() throw() {}
150
151 /*!
152  \return the error description and the context as a text string.
153  */
154 const char* Exception::what() const throw() { return msg.c_str(); }
155
156 void Exception::formatMessage()
157 {
158     if( func.size() > 0 )
159         msg = format("%s:%d: error: (%d) %s in function %s\n", file.c_str(), line, code, err.c_str(), func.c_str());
160     else
161         msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str());
162 }
163
164 struct HWFeatures
165 {
166     enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };
167
168     HWFeatures(void)
169      {
170         memset( have, 0, sizeof(have) );
171         x86_family = 0;
172     }
173
174     static HWFeatures initialize(void)
175     {
176         HWFeatures f;
177         int cpuid_data[4] = { 0, 0, 0, 0 };
178
179     #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
180         __cpuid(cpuid_data, 1);
181     #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
182         #ifdef __x86_64__
183         asm __volatile__
184         (
185          "movl $1, %%eax\n\t"
186          "cpuid\n\t"
187          :[eax]"=a"(cpuid_data[0]),[ebx]"=b"(cpuid_data[1]),[ecx]"=c"(cpuid_data[2]),[edx]"=d"(cpuid_data[3])
188          :
189          : "cc"
190         );
191         #else
192         asm volatile
193         (
194          "pushl %%ebx\n\t"
195          "movl $1,%%eax\n\t"
196          "cpuid\n\t"
197          "popl %%ebx\n\t"
198          : "=a"(cpuid_data[0]), "=c"(cpuid_data[2]), "=d"(cpuid_data[3])
199          :
200          : "cc"
201         );
202         #endif
203     #endif
204
205         f.x86_family = (cpuid_data[0] >> 8) & 15;
206         if( f.x86_family >= 6 )
207         {
208             f.have[CV_CPU_MMX]    = (cpuid_data[3] & (1 << 23)) != 0;
209             f.have[CV_CPU_SSE]    = (cpuid_data[3] & (1<<25)) != 0;
210             f.have[CV_CPU_SSE2]   = (cpuid_data[3] & (1<<26)) != 0;
211             f.have[CV_CPU_SSE3]   = (cpuid_data[2] & (1<<0)) != 0;
212             f.have[CV_CPU_SSSE3]  = (cpuid_data[2] & (1<<9)) != 0;
213             f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
214             f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
215             f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
216             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
217         }
218
219         return f;
220     }
221
222     int x86_family;
223     bool have[MAX_FEATURE+1];
224 };
225
226 static HWFeatures  featuresEnabled = HWFeatures::initialize(), featuresDisabled = HWFeatures();
227 static HWFeatures* currentFeatures = &featuresEnabled;
228
229 bool checkHardwareSupport(int feature)
230 {
231     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
232     return currentFeatures->have[feature];
233 }
234
235
236 volatile bool useOptimizedFlag = true;
237 #ifdef HAVE_IPP
238 struct IPPInitializer
239 {
240     IPPInitializer(void) { ippStaticInit(); }
241 };
242
243 IPPInitializer ippInitializer;
244 #endif
245
246 volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2];
247 volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2];
248 volatile bool USE_AVX = featuresEnabled.have[CV_CPU_AVX];
249
250 void setUseOptimized( bool flag )
251 {
252     useOptimizedFlag = flag;
253     currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
254     USE_SSE2 = currentFeatures->have[CV_CPU_SSE2];
255 }
256
257 bool useOptimized(void)
258 {
259     return useOptimizedFlag;
260 }
261
262 int64 getTickCount(void)
263 {
264 #if defined WIN32 || defined _WIN32 || defined WINCE
265     LARGE_INTEGER counter;
266     QueryPerformanceCounter( &counter );
267     return (int64)counter.QuadPart;
268 #elif defined __linux || defined __linux__
269     struct timespec tp;
270     clock_gettime(CLOCK_MONOTONIC, &tp);
271     return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
272 #elif defined __MACH__ && defined __APPLE__
273     return (int64)mach_absolute_time();
274 #else
275     struct timeval tv;
276     struct timezone tz;
277     gettimeofday( &tv, &tz );
278     return (int64)tv.tv_sec*1000000 + tv.tv_usec;
279 #endif
280 }
281
282 double getTickFrequency(void)
283 {
284 #if defined WIN32 || defined _WIN32 || defined WINCE
285     LARGE_INTEGER freq;
286     QueryPerformanceFrequency(&freq);
287     return (double)freq.QuadPart;
288 #elif defined __linux || defined __linux__
289     return 1e9;
290 #elif defined __MACH__ && defined __APPLE__
291     static double freq = 0;
292     if( freq == 0 )
293     {
294         mach_timebase_info_data_t sTimebaseInfo;
295         mach_timebase_info(&sTimebaseInfo);
296         freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
297     }
298     return freq;
299 #else
300     return 1e6;
301 #endif
302 }
303
304 #if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
305 #if defined(__i386__)
306
307 int64 getCPUTickCount(void)
308 {
309     int64 x;
310     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
311     return x;
312 }
313 #elif defined(__x86_64__)
314
315 int64 getCPUTickCount(void)
316 {
317     unsigned hi, lo;
318     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
319     return (int64)lo | ((int64)hi << 32);
320 }
321
322 #elif defined(__ppc__)
323
324 int64 getCPUTickCount(void)
325 {
326     int64 result = 0;
327     unsigned upper, lower, tmp;
328     __asm__ volatile(
329                      "0:                  \n"
330                      "\tmftbu   %0           \n"
331                      "\tmftb    %1           \n"
332                      "\tmftbu   %2           \n"
333                      "\tcmpw    %2,%0        \n"
334                      "\tbne     0b         \n"
335                      : "=r"(upper),"=r"(lower),"=r"(tmp)
336                      );
337     return lower | ((int64)upper << 32);
338 }
339
340 #else
341
342 #error "RDTSC not defined"
343
344 #endif
345
346 #elif defined _MSC_VER && defined WIN32 && defined _M_IX86
347
348 int64 getCPUTickCount(void)
349 {
350     __asm _emit 0x0f;
351     __asm _emit 0x31;
352 }
353
354 #else
355
356 #ifdef HAVE_IPP
357 int64 getCPUTickCount(void)
358 {
359     return ippGetCpuClocks();
360 }
361 #else
362 int64 getCPUTickCount(void)
363 {
364     return getTickCount();
365 }
366 #endif
367
368 #endif
369
370 const std::string& getBuildInformation()
371 {
372     static std::string build_info =
373 #include "version_string.inc"
374     ;
375     return build_info;
376 }
377
378 string format( const char* fmt, ... )
379 {
380     char buf[1 << 16];
381     va_list args;
382     va_start( args, fmt );
383     vsprintf( buf, fmt, args );
384     return string(buf);
385 }
386
387 string tempfile( const char* suffix )
388 {
389 #ifdef HAVE_WINRT
390     std::wstring temp_dir = L"";
391     const wchar_t* opencv_temp_dir = _wgetenv(L"OPENCV_TEMP_PATH");
392     if (opencv_temp_dir)
393         temp_dir = std::wstring(opencv_temp_dir);
394 #else
395     const char *temp_dir = getenv("OPENCV_TEMP_PATH");
396 #endif
397     string fname;
398
399 #if defined WIN32 || defined _WIN32
400 #ifdef HAVE_WINRT
401     RoInitialize(RO_INIT_MULTITHREADED);
402     std::wstring temp_dir2;
403     if (temp_dir.empty())
404         temp_dir = GetTempPathWinRT();
405
406     std::wstring temp_file;
407     temp_file = GetTempFileNameWinRT(L"ocv");
408     if (temp_file.empty())
409         return std::string();
410
411     temp_file = temp_dir + std::wstring(L"\\") + temp_file;
412     DeleteFileW(temp_file.c_str());
413
414     size_t asize = wcstombs(NULL, temp_file.c_str(), 0);
415     Ptr<char> aname = new char[asize+1];
416     aname[asize] = 0;
417     wcstombs(aname, temp_file.c_str(), asize);
418     fname = std::string(aname);
419     RoUninitialize();
420 #else
421     char temp_dir2[MAX_PATH + 1] = { 0 };
422     char temp_file[MAX_PATH + 1] = { 0 };
423
424     if (temp_dir == 0 || temp_dir[0] == 0)
425     {
426         ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
427         temp_dir = temp_dir2;
428     }
429     if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
430         return string();
431
432     DeleteFileA(temp_file);
433
434     fname = temp_file;
435 #endif
436 # else
437 #  ifdef ANDROID
438     //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
439     char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
440 #  else
441     char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
442 #  endif
443
444     if (temp_dir == 0 || temp_dir[0] == 0)
445         fname = defaultTemplate;
446     else
447     {
448         fname = temp_dir;
449         char ech = fname[fname.size() - 1];
450         if(ech != '/' && ech != '\\')
451             fname += "/";
452         fname += "__opencv_temp.XXXXXX";
453     }
454
455     const int fd = mkstemp((char*)fname.c_str());
456     if (fd == -1) return string();
457
458     close(fd);
459     remove(fname.c_str());
460 # endif
461
462     if (suffix)
463     {
464         if (suffix[0] != '.')
465             return fname + "." + suffix;
466         else
467             return fname + suffix;
468     }
469     return fname;
470 }
471
472 static CvErrorCallback customErrorCallback = 0;
473 static void* customErrorCallbackData = 0;
474 static bool breakOnError = false;
475
476 bool setBreakOnError(bool value)
477 {
478     bool prevVal = breakOnError;
479     breakOnError = value;
480     return prevVal;
481 }
482
483 void error( const Exception& exc )
484 {
485     if (customErrorCallback != 0)
486         customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
487                             exc.file.c_str(), exc.line, customErrorCallbackData);
488     else
489     {
490         const char* errorStr = cvErrorStr(exc.code);
491         char buf[1 << 16];
492
493         sprintf( buf, "OpenCV Error: %s (%s) in %s, file %s, line %d",
494             errorStr, exc.err.c_str(), exc.func.size() > 0 ?
495             exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line );
496         fprintf( stderr, "%s\n", buf );
497         fflush( stderr );
498 #  ifdef __ANDROID__
499         __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
500 #  endif
501     }
502
503     if(breakOnError)
504     {
505         static volatile int* p = 0;
506         *p = 0;
507     }
508
509     throw exc;
510 }
511
512 CvErrorCallback
513 redirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
514 {
515     if( prevUserdata )
516         *prevUserdata = customErrorCallbackData;
517
518     CvErrorCallback prevCallback = customErrorCallback;
519
520     customErrorCallback     = errCallback;
521     customErrorCallbackData = userdata;
522
523     return prevCallback;
524 }
525
526 }
527
528 CV_IMPL int cvCheckHardwareSupport(int feature)
529 {
530     CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
531     return cv::currentFeatures->have[feature];
532 }
533
534 CV_IMPL int cvUseOptimized( int flag )
535 {
536     int prevMode = cv::useOptimizedFlag;
537     cv::setUseOptimized( flag != 0 );
538     return prevMode;
539 }
540
541 CV_IMPL int64  cvGetTickCount(void)
542 {
543     return cv::getTickCount();
544 }
545
546 CV_IMPL double cvGetTickFrequency(void)
547 {
548     return cv::getTickFrequency()*1e-6;
549 }
550
551 CV_IMPL CvErrorCallback
552 cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
553 {
554     return cv::redirectError(errCallback, userdata, prevUserdata);
555 }
556
557 CV_IMPL int cvNulDevReport( int, const char*, const char*,
558                             const char*, int, void* )
559 {
560     return 0;
561 }
562
563 CV_IMPL int cvStdErrReport( int, const char*, const char*,
564                             const char*, int, void* )
565 {
566     return 0;
567 }
568
569 CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
570                             const char*, int, void* )
571 {
572     return 0;
573 }
574
575 CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
576 {
577     return 0;
578 }
579
580
581 CV_IMPL const char* cvErrorStr( int status )
582 {
583     static char buf[256];
584
585     switch (status)
586     {
587     case CV_StsOk :                  return "No Error";
588     case CV_StsBackTrace :           return "Backtrace";
589     case CV_StsError :               return "Unspecified error";
590     case CV_StsInternal :            return "Internal error";
591     case CV_StsNoMem :               return "Insufficient memory";
592     case CV_StsBadArg :              return "Bad argument";
593     case CV_StsNoConv :              return "Iterations do not converge";
594     case CV_StsAutoTrace :           return "Autotrace call";
595     case CV_StsBadSize :             return "Incorrect size of input array";
596     case CV_StsNullPtr :             return "Null pointer";
597     case CV_StsDivByZero :           return "Division by zero occured";
598     case CV_BadStep :                return "Image step is wrong";
599     case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
600     case CV_StsObjectNotFound :      return "Requested object was not found";
601     case CV_BadDepth :               return "Input image depth is not supported by function";
602     case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
603     case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
604     case CV_StsOutOfRange :          return "One of arguments\' values is out of range";
605     case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
606     case CV_BadCOI :                 return "Input COI is not supported";
607     case CV_BadNumChannels :         return "Bad number of channels";
608     case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
609     case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
610     case CV_StsBadMask :             return "Bad type of mask argument";
611     case CV_StsParseError :          return "Parsing error";
612     case CV_StsNotImplemented :      return "The function/feature is not implemented";
613     case CV_StsBadMemBlock :         return "Memory block has been corrupted";
614     case CV_StsAssert :              return "Assertion failed";
615     case CV_GpuNotSupported :        return "No GPU support";
616     case CV_GpuApiCallError :        return "Gpu API call";
617     case CV_OpenGlNotSupported :     return "No OpenGL support";
618     case CV_OpenGlApiCallError :     return "OpenGL API call";
619     };
620
621     sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
622     return buf;
623 }
624
625 CV_IMPL int cvGetErrMode(void)
626 {
627     return 0;
628 }
629
630 CV_IMPL int cvSetErrMode(int)
631 {
632     return 0;
633 }
634
635 CV_IMPL int cvGetErrStatus(void)
636 {
637     return 0;
638 }
639
640 CV_IMPL void cvSetErrStatus(int)
641 {
642 }
643
644
645 CV_IMPL void cvError( int code, const char* func_name,
646                       const char* err_msg,
647                       const char* file_name, int line )
648 {
649     cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
650 }
651
652 /* function, which converts int to int */
653 CV_IMPL int
654 cvErrorFromIppStatus( int status )
655 {
656     switch (status)
657     {
658     case CV_BADSIZE_ERR:               return CV_StsBadSize;
659     case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
660     case CV_NULLPTR_ERR:               return CV_StsNullPtr;
661     case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
662     case CV_BADSTEP_ERR:               return CV_BadStep;
663     case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
664     case CV_BADARG_ERR:                return CV_StsBadArg;
665     case CV_NOTDEFINED_ERR:            return CV_StsError;
666     case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
667     case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
668     case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
669     case CV_BADDEPTH_ERR:              return CV_BadDepth;
670     case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
671     case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
672     case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
673     case CV_BADFLAG_ERR:               return CV_StsBadFlag;
674     case CV_BADRANGE_ERR:              return CV_StsBadArg;
675     case CV_BADCOEF_ERR:               return CV_StsBadArg;
676     case CV_BADFACTOR_ERR:             return CV_StsBadArg;
677     case CV_BADPOINT_ERR:              return CV_StsBadPoint;
678
679     default:
680       return CV_StsError;
681     }
682 }
683
684 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, 0 };
685
686 CvModuleInfo* CvModule::first = 0, *CvModule::last = 0;
687
688 CvModule::CvModule( CvModuleInfo* _info )
689 {
690     cvRegisterModule( _info );
691     info = last;
692 }
693
694 CvModule::~CvModule(void)
695 {
696     if( info )
697     {
698         CvModuleInfo* p = first;
699         for( ; p != 0 && p->next != info; p = p->next )
700             ;
701
702         if( p )
703             p->next = info->next;
704
705         if( first == info )
706             first = info->next;
707
708         if( last == info )
709             last = p;
710
711         free( info );
712         info = 0;
713     }
714 }
715
716 CV_IMPL int
717 cvRegisterModule( const CvModuleInfo* module )
718 {
719     CV_Assert( module != 0 && module->name != 0 && module->version != 0 );
720
721     size_t name_len = strlen(module->name);
722     size_t version_len = strlen(module->version);
723
724     CvModuleInfo* module_copy = (CvModuleInfo*)malloc( sizeof(*module_copy) +
725                                 name_len + 1 + version_len + 1 );
726
727     *module_copy = *module;
728     module_copy->name = (char*)(module_copy + 1);
729     module_copy->version = (char*)(module_copy + 1) + name_len + 1;
730
731     memcpy( (void*)module_copy->name, module->name, name_len + 1 );
732     memcpy( (void*)module_copy->version, module->version, version_len + 1 );
733     module_copy->next = 0;
734
735     if( CvModule::first == 0 )
736         CvModule::first = module_copy;
737     else
738         CvModule::last->next = module_copy;
739
740     CvModule::last = module_copy;
741
742     return 0;
743 }
744
745 CvModule cxcore_module( &cxcore_info );
746
747 CV_IMPL void
748 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
749 {
750     static char joint_verinfo[1024]   = "";
751     static char plugin_list_buf[1024] = "";
752
753     if( version )
754         *version = 0;
755
756     if( plugin_list )
757         *plugin_list = 0;
758
759     CvModuleInfo* module;
760
761     if( version )
762     {
763         if( name )
764         {
765             size_t i, name_len = strlen(name);
766
767             for( module = CvModule::first; module != 0; module = module->next )
768             {
769                 if( strlen(module->name) == name_len )
770                 {
771                     for( i = 0; i < name_len; i++ )
772                     {
773                         int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
774                         if( c0 != c1 )
775                             break;
776                     }
777                     if( i == name_len )
778                         break;
779                 }
780             }
781             if( !module )
782                 CV_Error( CV_StsObjectNotFound, "The module is not found" );
783
784             *version = module->version;
785         }
786         else
787         {
788             char* ptr = joint_verinfo;
789
790             for( module = CvModule::first; module != 0; module = module->next )
791             {
792                 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
793                 ptr += strlen(ptr);
794             }
795
796             *version = joint_verinfo;
797         }
798     }
799
800     if( plugin_list )
801         *plugin_list = plugin_list_buf;
802 }
803
804 #if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
805 #ifdef HAVE_WINRT
806     #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
807 #endif
808
809 BOOL WINAPI DllMain( HINSTANCE, DWORD  fdwReason, LPVOID );
810
811 BOOL WINAPI DllMain( HINSTANCE, DWORD  fdwReason, LPVOID )
812 {
813     if( fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH )
814     {
815         cv::deleteThreadAllocData();
816         cv::deleteThreadRNGData();
817     }
818     return TRUE;
819 }
820 #endif
821
822 namespace cv
823 {
824
825 #if defined WIN32 || defined _WIN32 || defined WINCE
826
827 struct Mutex::Impl
828 {
829     Impl()
830     {
831 #if (_WIN32_WINNT >= 0x0600)
832         ::InitializeCriticalSectionEx(&cs, 1000, 0);
833 #else
834         ::InitializeCriticalSection(&cs);
835 #endif
836         refcount = 1;
837     }
838     ~Impl() { DeleteCriticalSection(&cs); }
839
840     void lock() { EnterCriticalSection(&cs); }
841     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
842     void unlock() { LeaveCriticalSection(&cs); }
843
844     CRITICAL_SECTION cs;
845     int refcount;
846 };
847
848 #ifndef __GNUC__
849 int _interlockedExchangeAdd(int* addr, int delta)
850 {
851 #if defined _MSC_VER && _MSC_VER >= 1500
852     return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
853 #else
854     return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
855 #endif
856 }
857 #endif // __GNUC__
858
859 #elif defined __APPLE__
860
861 #include <libkern/OSAtomic.h>
862
863 struct Mutex::Impl
864 {
865     Impl() { sl = OS_SPINLOCK_INIT; refcount = 1; }
866     ~Impl() {}
867
868     void lock() { OSSpinLockLock(&sl); }
869     bool trylock() { return OSSpinLockTry(&sl); }
870     void unlock() { OSSpinLockUnlock(&sl); }
871
872     OSSpinLock sl;
873     int refcount;
874 };
875
876 #elif defined __linux__ && !defined ANDROID
877
878 struct Mutex::Impl
879 {
880     Impl() { pthread_spin_init(&sl, 0); refcount = 1; }
881     ~Impl() { pthread_spin_destroy(&sl); }
882
883     void lock() { pthread_spin_lock(&sl); }
884     bool trylock() { return pthread_spin_trylock(&sl) == 0; }
885     void unlock() { pthread_spin_unlock(&sl); }
886
887     pthread_spinlock_t sl;
888     int refcount;
889 };
890
891 #else
892
893 struct Mutex::Impl
894 {
895     Impl() { pthread_mutex_init(&sl, 0); refcount = 1; }
896     ~Impl() { pthread_mutex_destroy(&sl); }
897
898     void lock() { pthread_mutex_lock(&sl); }
899     bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
900     void unlock() { pthread_mutex_unlock(&sl); }
901
902     pthread_mutex_t sl;
903     int refcount;
904 };
905
906 #endif
907
908 Mutex::Mutex()
909 {
910     impl = new Mutex::Impl;
911 }
912
913 Mutex::~Mutex()
914 {
915     if( CV_XADD(&impl->refcount, -1) == 1 )
916         delete impl;
917     impl = 0;
918 }
919
920 Mutex::Mutex(const Mutex& m)
921 {
922     impl = m.impl;
923     CV_XADD(&impl->refcount, 1);
924 }
925
926 Mutex& Mutex::operator = (const Mutex& m)
927 {
928     CV_XADD(&m.impl->refcount, 1);
929     if( CV_XADD(&impl->refcount, -1) == 1 )
930         delete impl;
931     impl = m.impl;
932     return *this;
933 }
934
935 void Mutex::lock() { impl->lock(); }
936 void Mutex::unlock() { impl->unlock(); }
937 bool Mutex::trylock() { return impl->trylock(); }
938
939 }
940
941 /* End of file. */