Sqlite源码解读(五)

2021SC@SDUSC

第四篇深入拓展了第三章讲的malloc()方法,详细讲解了VFS的内存分配和共享缓存机制,本篇将继续深入Windows的内存分配。先接着第三篇后面继续看源码。在第三篇末,由于主锁和memsys锁目前都已由我们持有,因此没有其他函数能够访问堆。现在我们尝试销毁和重新创建我们的孤立的Win 32本机堆。

if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){

   

    assert( winMemGetHeap()!=NULL );

    assert( winMemGetOwned() );

    assert( sqlite3_memory_used()==0 );

    winMemShutdown(winMemGetDataPtr());

    assert( winMemGetHeap()==NULL );

    assert( !winMemGetOwned() );

    assert( sqlite3_memory_used()==0 );

    rc = winMemInit(winMemGetDataPtr());

    assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL );

    assert( rc!=SQLITE_OK || winMemGetOwned() );

    assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 );

  }else{

  rc = SQLITE_BUSY;   /*Win32本机堆可能在忙碌中*/

  }

  sqlite3_mutex_leave(pMem);

  sqlite3_mutex_leave(pMainMtx);

  return rc;

接来下介绍一个重要函数,将指定的anis字符串输出到Win32调试器中。

void sqlite3_win32_write_debug(const char *zBuf, int nBuf){

  char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];

  int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1));  /*可能是负数*/

  if( nMin<-1 ) nMin = -1;                   /*所有负数变为-1*/

  assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );

#ifdef SQLITE_ENABLE_API_ARMOR

  if( !zBuf ){

    (void)SQLITE_MISUSE_BKPT;

    return;

  }

#endif

#if defined(SQLITE_WIN32_HAS_ANSI)

  if( nMin>0 ){

    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);

    memcpy(zDbgBuf, zBuf, nMin);

    osOutputDebugStringA(zDbgBuf);

  }else{

    osOutputDebugStringA(zBuf);

  }

#elif defined(SQLITE_WIN32_HAS_WIDE)

  memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);

  if ( osMultiByteToWideChar(

          osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,

          nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){

    return;

  }

  osOutputDebugStringW((LPCWSTR)zDbgBuf);

#else

  if( nMin>0 ){

    memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);

    memcpy(zDbgBuf, zBuf, nMin);

    fprintf(stderr, "%s", zDbgBuf);

  }else{

    fprintf(stderr, "%s", zBuf);

  }

#endif

}

下面的例程将当前线程挂起至少ms毫秒。这相当于Win 32 Slep()接口。

#if SQLITE_OS_WINRT

static HANDLE sleepObj = NULL;

#endif

void sqlite3_win32_sleep(DWORD milliseconds){

#if SQLITE_OS_WINRT

  if ( sleepObj==NULL ){

    sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,

                                SYNCHRONIZE);

  }

  assert( sleepObj!=NULL );

  osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);

#else

  osSleep(milliseconds);

#endif

}

如果我们在WinNT、Win2K、WinXP、或WinCE下运行,则返回true(非零)。返回Win 95、Win 98或WinME的false(0)。这里有一个有趣的观察:Win 95、Win 98和WinME缺乏LockFileEx()API。但是,只要我们在运行Win 95/98/ME时不调用它,我们仍然可以静态地链接到该API。调用这个例程用于确定主机是Win 95/98/ME还是WinNT/2K/XP,以便我们知道是否可以安全地调用LockFileEx()API。

此函数根据NT内核确定机器是否运行Windows的版本。

int sqlite3_win32_is_nt(void){

#if SQLITE_OS_WINRT       /* WinRT子平台被认为是基于NT内核的。*/

  return 1;

#elif SQLITE_WIN32_GETVERSIONEX

  if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){

#if defined(SQLITE_WIN32_HAS_ANSI)

    OSVERSIONINFOA sInfo;

    sInfo.dwOSVersionInfoSize = sizeof(sInfo);

    osGetVersionExA(&sInfo);

    osInterlockedCompareExchange(&sqlite3_os_type,

        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);

#elif defined(SQLITE_WIN32_HAS_WIDE)

OSVERSIONINFOW sInfo;

sInfo.dwOSVersionInfoSize = sizeof(sInfo);

    osGetVersionExW(&sInfo);

    osInterlockedCompareExchange(&sqlite3_os_type,

        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);

#endif

  }

  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;

#elif SQLITE_TEST

  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;

#else

/*所有GetVersionEx[AW]函数被废弃的子平台都被假定是基于NT内核的。*/

  return 1;

#endif

}

接下来是对Windows版本系统进行的内存分配、初始化模块

分配nBytes内存

#ifdef SQLITE_WIN32_MALLOC

static void *winMemMalloc(int nBytes){

  HANDLE hHeap;

  void *p;

  winMemAssertMagic();

  hHeap = winMemGetHeap();

  assert( hHeap!=0 );

  assert( hHeap!=INVALID_HANDLE_VALUE );

#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)

  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );

#endif

  assert( nBytes>=0 );

  p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);

  if( !p ){

    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",

                nBytes, osGetLastError(), (void*)hHeap);

  }

  return p;

}

释放内存

static void winMemFree(void *pPrior){

  HANDLE hHeap;

  winMemAssertMagic();

  hHeap = winMemGetHeap();

  assert( hHeap!=0 );

  assert( hHeap!=INVALID_HANDLE_VALUE );

#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)

  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );

#endif

  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */

  if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){

    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",

                pPrior, osGetLastError(), (void*)hHeap);

  }

}

更改现有内存分配的大小

static void *winMemRealloc(void *pPrior, int nBytes){

  HANDLE hHeap;

  void *p;

  winMemAssertMagic();

  hHeap = winMemGetHeap();

  assert( hHeap!=0 );

  assert( hHeap!=INVALID_HANDLE_VALUE );

#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)

  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );

#endif

  assert( nBytes>=0 );

  if( !pPrior ){

    p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);

  }else{

    p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);

  }

  if( !p ){

    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",

                pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),

                (void*)hHeap);

  }

  return p;

}

返回未执行分配的大小

static int winMemSize(void *p){

  HANDLE hHeap;

  SIZE_T n;

  winMemAssertMagic();

  hHeap = winMemGetHeap();

  assert( hHeap!=0 );

  assert( hHeap!=INVALID_HANDLE_VALUE );

#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)

  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );

#endif

  if( !p ) return 0;

  n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);

  if( n==(SIZE_T)-1 ){

    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",

                p, osGetLastError(), (void*)hHeap);

    return 0;

  }

  return (int)n;

}

将请求大小舍入到下一个有效分配大小

static int winMemRoundup(int n){

  return n;

}

初始化此模块

static int winMemInit(void *pAppData){

  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return SQLITE_ERROR;

  assert( pWinMemData->magic1==WINMEM_MAGIC1 );

  assert( pWinMemData->magic2==WINMEM_MAGIC2 );    /*(省略一些)*/

去初始化(deinitialize)

static void winMemShutdown(void *pAppData){

  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return;

  assert( pWinMemData->magic1==WINMEM_MAGIC1 );

  assert( pWinMemData->magic2==WINMEM_MAGIC2 );

  if( pWinMemData->hHeap ){

    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );

#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)

    assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );

#endif

    if( pWinMemData->bOwned ){

      if( !osHeapDestroy(pWinMemData->hHeap) ){

        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",

                    osGetLastError(), (void*)pWinMemData->hHeap);

      }

      pWinMemData->bOwned = FALSE;

    }

    pWinMemData->hHeap = NULL;

  }

}

用指向该文件中例程的指针填充**sqlite3GlobalConfig.m中的低级内存分配函数指针。

const sqlite3_mem_methods *sqlite3MemGetWin32(void){

  static const sqlite3_mem_methods winMemMethods = {

    winMemMalloc,

    winMemFree,

    winMemRealloc,

    winMemSize,

    winMemRoundup,

    winMemInit,

    winMemShutdown,

    &win_mem_data

  };

  return &winMemMethods;

}

void sqlite3MemSetDefault(void){

  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());

}

#endif

猜你喜欢

转载自blog.csdn.net/qq_53825872/article/details/120958331
今日推荐