using System.Diagnostics; using DWORD = System.Int32; using System.Threading; using System; namespace Community.CsharpSqlite { public partial class Sqlite3 { /* ** 2007 August 14 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d ** ************************************************************************* */ //#include "sqliteInt.h" /* ** The code in this file is only used if we are compiling multithreaded ** on a win32 system. */ #if SQLITE_MUTEX_W32 /* ** Each recursive mutex is an instance of the following structure. */ public partial class sqlite3_mutex { public Object mutex; /* Mutex controlling the lock */ public int id; /* Mutex type */ public int nRef; /* Number of enterances */ public DWORD owner; /* Thread holding this mutex */ #if SQLITE_DEBUG public int trace; /* True to trace changes */ #endif public sqlite3_mutex() { mutex = new Object(); } public sqlite3_mutex( Mutex mutex, int id, int nRef, DWORD owner #if SQLITE_DEBUG , int trace #endif ) { this.mutex = mutex; this.id = id; this.nRef = nRef; this.owner = owner; #if SQLITE_DEBUG this.trace = 0; #endif } }; //#define SQLITE_W32_MUTEX_INITIALIZER { 0 } static Mutex SQLITE_W32_MUTEX_INITIALIZER = null; #if SQLITE_DEBUG //#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } #else //#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 } #endif /* ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, ** or WinCE. Return false (zero) for Win95, Win98, or WinME. ** ** Here is an interesting observation: Win95, Win98, and WinME lack ** the LockFileEx() API. But we can still statically link against that ** API as long as we don't call it win running Win95/98/ME. A call to ** this routine is used to determine if the host is Win95/98/ME or ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. ** ** mutexIsNT() is only used for the TryEnterCriticalSection() API call, ** which is only available if your application was compiled with ** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only ** call to TryEnterCriticalSection() is #ifdef'ed out, so #if ** this out as well. */ #if FALSE #if SQLITE_OS_WINCE //# define mutexIsNT() (1) #else static int mutexIsNT(void){ static int osType = 0; if( osType==0 ){ OSVERSIONINFO sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); GetVersionEx(&sInfo); osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return osType==2; } #endif //* SQLITE_OS_WINCE */ #endif #if SQLITE_DEBUG /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use only inside Debug.Assert() statements. */ static bool winMutexHeld( sqlite3_mutex p ) { return p.nRef != 0 && p.owner == GetCurrentThreadId(); } static bool winMutexNotheld2( sqlite3_mutex p, DWORD tid ) { return p.nRef == 0 || p.owner != tid; } static bool winMutexNotheld( sqlite3_mutex p ) { DWORD tid = GetCurrentThreadId(); return winMutexNotheld2( p, tid ); } #endif /* ** Initialize and deinitialize the mutex subsystem. */ //No MACROS under C#; Cannot use SQLITE3_MUTEX_INITIALIZER, static sqlite3_mutex[] winMutex_staticMutexes = new sqlite3_mutex[]{ new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, new sqlite3_mutex( SQLITE_W32_MUTEX_INITIALIZER, 0, 0, (DWORD)0 #if SQLITE_DEBUG , 0 #endif ),// SQLITE3_MUTEX_INITIALIZER, }; static int winMutex_isInit = 0; /* As winMutexInit() and winMutexEnd() are called as part ** of the sqlite3_initialize and sqlite3_shutdown() ** processing, the "interlocked" magic is probably not ** strictly necessary. */ static long winMutex_lock = 0; private static System.Object lockThis = new System.Object(); static int winMutexInit() { /* The first to increment to 1 does actual initialization */ lock ( lockThis ) //if ( Interlocked.CompareExchange(ref winMutex_lock, 1, 0 ) == 0 ) { int i; for ( i = 0; i < ArraySize( winMutex_staticMutexes ); i++ ) { if (winMutex_staticMutexes[i].mutex== null) winMutex_staticMutexes[i].mutex = new Mutex(); //InitializeCriticalSection( winMutex_staticMutexes[i].mutex ); } winMutex_isInit = 1; } //else //{ // /* Someone else is in the process of initing the static mutexes */ // while ( 0 == winMutex_isInit ) // { // Thread.Sleep( 1 ); // } //} return SQLITE_OK; } static int winMutexEnd() { /* The first to decrement to 0 does actual shutdown ** (which should be the last to shutdown.) */ if ( Interlocked.CompareExchange( ref winMutex_lock, 0, 1 ) == 1 ) { if ( winMutex_isInit == 1 ) { int i; for ( i = 0; i < ArraySize( winMutex_staticMutexes ); i++ ) { DeleteCriticalSection( winMutex_staticMutexes[i].mutex ); } winMutex_isInit = 0; } } return SQLITE_OK; } /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite ** will unwind its stack and return an error. The argument ** to sqlite3_mutex_alloc() is one of these integer constants: ** **