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