mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Testing of the automatic TSD deallocation logic. The sqlite3_thread_cleanup()
API is documented. This should close ticket #1601. (CVS 2920) FossilOrigin-Name: fb518b0ce4ddd4aaca5cccf61e651f173e735119
This commit is contained in:
26
manifest
26
manifest
@ -1,5 +1,5 @@
|
||||
C Automatically\sdeallocate\sthread-specific\sdata\swhen\sit\sis\sno\slonger\nbeing\sused.\s\sTicket\s#1601.\s\sAlso\simplemented\sthe\ssuggestion\sof\nticket\s#1603.\sMemory\smanagement\sis\snow\soff\sby\sdefault\sat\scompile-time.\nThe\ssqlite3_enable_memory_management()\sAPI\shas\sbeen\sremoved.\s(CVS\s2919)
|
||||
D 2006-01-11T21:41:21
|
||||
C Testing\sof\sthe\sautomatic\sTSD\sdeallocation\slogic.\s\sThe\ssqlite3_thread_cleanup()\nAPI\sis\sdocumented.\s\sThis\sshould\sclose\sticket\s#1601.\s(CVS\s2920)
|
||||
D 2006-01-11T23:40:33
|
||||
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
|
||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -55,9 +55,9 @@ F src/os.h 9debc3d3ca4cdafde222a0ea74a4c8415aef4f22
|
||||
F src/os_common.h 78bcc34dded9b625b3c16d072b7e5b76d075a674
|
||||
F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
|
||||
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
|
||||
F src/os_unix.c 557a21c563496a1ccef32b1d57376d135884eac5
|
||||
F src/os_unix.c d3ec9c61a1194d3e475423298de6ce13871605a1
|
||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c b67dd34bf1ae796851910a229bd94026b42d942f
|
||||
F src/os_win.c e372f99c4a89b9c54249a29c8c4912e5a2e67fb4
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c a96b9c43664670576e41eac699277c7862d604d8
|
||||
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
|
||||
@ -67,19 +67,19 @@ F src/prepare.c 60c1f5e3d2901d651f8ca9f06e39e2ff3f335844
|
||||
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
|
||||
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
|
||||
F src/select.c 7b19d350cb2a18ae4a59d6b87049aa2ce9c671ae
|
||||
F src/server.c 519e308651e30102dd3d1f4053ac64c14267e44c
|
||||
F src/server.c e425729aa7ff374637033a38ba9fd9938c432244
|
||||
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
|
||||
F src/sqlite.h.in 4320cff369e37897d2839d526c2b8917a2756d60
|
||||
F src/sqliteInt.h bd3fba6d7163ef402b5633191ee5d7de5b7f6e80
|
||||
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
|
||||
F src/tclsqlite.c d650bea0248fc0a310ddc2cb94273a3a5021fddf
|
||||
F src/test1.c d38c9f4da2136c5e1747517d7b564ba88a91fbee
|
||||
F src/test1.c 30ed0d4d594db0bb2beb98be7024cde1fe686f14
|
||||
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
|
||||
F src/test3.c 9742aa146eb750cab81c1d5605286c3a0eb88054
|
||||
F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f
|
||||
F src/test4.c 0f95de81629a53fc6ab104f64a7ccb1dcbb8af90
|
||||
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
||||
F src/test6.c 74d91b487c68154156eded457925d96aa2a3fdbb
|
||||
F src/test7.c bfe36c62cae189509660acfeeb891ffb9da8ef0c
|
||||
F src/test7.c c87fd373a613986113717ba51e6a5ad86407c1f7
|
||||
F src/test_async.c 6776f5027ca6378c116ff5ccc2fe41b908e33772
|
||||
F src/tokenize.c b75d24cbb419eef9ae7be286dd66723a2ee49f4f
|
||||
F src/trigger.c 694b247476d2fc0dce003af564f79e8752fc1158
|
||||
@ -234,7 +234,7 @@ F test/table.test 6dc0dfa44dd429520e0e5a0c5e55025f730e9403
|
||||
F test/tableapi.test 6a66d58b37d46dc0f2b3c7d4bd2617d209399bd1
|
||||
F test/tclsqlite.test 2c4b5fb2f21e6740479463c263f3020f08e472d7
|
||||
F test/temptable.test 7927261befdbc7b0a7ffebb85ecc70a74fa7b15b
|
||||
F test/tester.tcl b9b2c481dbef7fec4b8b3b91c6b810e7f916ba28
|
||||
F test/tester.tcl ed59b4eaa180728e4be1c55dc2823d66e03ae79a
|
||||
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
F test/threadtest2.c 97a830d53c24c42290501fdfba4a6e5bdd34748b
|
||||
@ -297,7 +297,7 @@ F www/audit.tcl 90e09d580f79c7efec0c7d6f447b7ec5c2dce5c0
|
||||
F www/autoinc.tcl b357f5ba954b046ee35392ce0f884a2fcfcdea06
|
||||
F www/c_interface.tcl b51b08591554c16a0c3ef718364a508ac25abc7e
|
||||
F www/capi3.tcl 7a7cc225fe02eb7ab861a6019b08baa0014409e1
|
||||
F www/capi3ref.tcl 3885ca3847f394db7aa035647f0ab1c140244042
|
||||
F www/capi3ref.tcl 47c6014600805f4e385cf6b2e12b227ba1a906ec
|
||||
F www/changes.tcl 661937260b6eac4af510e068f33f3ce7b3298ff6
|
||||
F www/common.tcl 14d121c28532ad20c3e349caa4db708b0b822083
|
||||
F www/compile.tcl 276546d7eb445add5a867193bbd80f6919a6b084
|
||||
@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 8c26893c65574b0667bb84bde3ca49751079cc8d
|
||||
R a464a0f33259fc5b6aae2e3199e401a7
|
||||
P 5d9c6aa964305c3f36741ff0058da5b5f3ce0d24
|
||||
R 3399b09fea32a929acfc809e2317093c
|
||||
U drh
|
||||
Z 7760f8b5862256854e201380c09a40e6
|
||||
Z 938c3f3406b28a56fdbffbe4eafe6c93
|
||||
|
@ -1 +1 @@
|
||||
5d9c6aa964305c3f36741ff0058da5b5f3ce0d24
|
||||
fb518b0ce4ddd4aaca5cccf61e651f173e735119
|
@ -1626,6 +1626,27 @@ int sqlite3UnixInMutex(){
|
||||
return inMutex;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remember the number of thread-specific-data blocks allocated.
|
||||
** Use this to verify that we are not leaking thread-specific-data.
|
||||
** Ticket #1601
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_tsd_count = 0;
|
||||
# ifdef SQLITE_UNIX_THREADS
|
||||
static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
# define TSD_COUNTER(N) \
|
||||
pthread_mutex_lock(&tsd_counter_mutex); \
|
||||
sqlite3_tsd_count += N; \
|
||||
pthread_mutex_unlock(&tsd_counter_mutex);
|
||||
# else
|
||||
# define TSD_COUNTER(N) sqlite3_tsd_count += N
|
||||
# endif
|
||||
#else
|
||||
# define TSD_COUNTER(N) /* no-op */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** If called with allocateFlag==1, then return a pointer to thread
|
||||
** specific data for the current thread. Allocate and zero the
|
||||
@ -1664,11 +1685,13 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
pthread_setspecific(key, pTsd);
|
||||
TSD_COUNTER(+1);
|
||||
}
|
||||
}
|
||||
}else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
|
||||
sqlite3OsFree(pTsd);
|
||||
pthread_setspecific(key, 0);
|
||||
TSD_COUNTER(-1);
|
||||
pTsd = 0;
|
||||
}
|
||||
return pTsd;
|
||||
@ -1679,10 +1702,12 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){
|
||||
pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
TSD_COUNTER(+1);
|
||||
}
|
||||
}
|
||||
}else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
|
||||
sqlite3OsFree(pTsd);
|
||||
TSD_COUNTER(-1);
|
||||
pTsd = 0;
|
||||
}
|
||||
return pTsd;
|
||||
|
24
src/os_win.c
24
src/os_win.c
@ -1148,6 +1148,22 @@ int sqlite3WinCurrentTime(double *prNow){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remember the number of thread-specific-data blocks allocated.
|
||||
** Use this to verify that we are not leaking thread-specific-data.
|
||||
** Ticket #1601
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_tsd_count = 0;
|
||||
# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
|
||||
# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
|
||||
#else
|
||||
# define TSD_COUNTER_INCR /* no-op */
|
||||
# define TSD_COUNTER_DECR /* no-op */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** If called with allocateFlag==1, then return a pointer to thread
|
||||
** specific data for the current thread. Allocate and zero the
|
||||
@ -1158,11 +1174,11 @@ int sqlite3WinCurrentTime(double *prNow){
|
||||
** Return a pointer to the thread specific data or NULL if it is
|
||||
** unallocated.
|
||||
*/
|
||||
void *sqlite3WinThreadSpecificData(int allocateFlag){
|
||||
static void *pTsd = 0;
|
||||
ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
|
||||
static int key;
|
||||
static int keyInit = 0;
|
||||
static const ThreadData zeroData;
|
||||
ThreadData *pTsd;
|
||||
|
||||
if( !keyInit ){
|
||||
sqlite3OsEnterMutex();
|
||||
@ -1179,15 +1195,17 @@ void *sqlite3WinThreadSpecificData(int allocateFlag){
|
||||
pTsd = TlsGetValue(key);
|
||||
if( allocateFlag ){
|
||||
if( !pTsd ){
|
||||
pTsd = sqlite3OsMalloc(nByte);
|
||||
pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
TlsSetValue(key, pTsd);
|
||||
TSD_COUNTER_INCR;
|
||||
}
|
||||
}
|
||||
}else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
|
||||
sqlite3OsFree(pTsd);
|
||||
TlsSetValue(key, 0);
|
||||
TSD_COUNTER_DECR;
|
||||
pTsd = 0;
|
||||
}
|
||||
return pTsd;
|
||||
|
@ -332,6 +332,7 @@ int sqlite3_client_close(sqlite3 *pDb){
|
||||
void *sqlite3_server(void *NotUsed){
|
||||
sqlite3_enable_shared_cache(1);
|
||||
if( pthread_mutex_trylock(&g.serverMutex) ){
|
||||
sqlite3_enable_shared_cache(0);
|
||||
return 0; /* Another server is already running */
|
||||
}
|
||||
while( !g.serverHalt ){
|
||||
@ -393,6 +394,7 @@ void *sqlite3_server(void *NotUsed){
|
||||
pthread_cond_signal(&pMsg->clientWakeup);
|
||||
}
|
||||
pthread_mutex_unlock(&g.serverMutex);
|
||||
sqlite3_thread_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
75
src/test1.c
75
src/test1.c
@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.188 2006/01/11 21:41:22 drh Exp $
|
||||
** $Id: test1.c,v 1.189 2006/01/11 23:40:34 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -3001,6 +3001,60 @@ static int test_soft_heap_limit(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_clear_tsd_memdebug
|
||||
**
|
||||
** Clear all of the MEMDEBUG information out of thread-specific data.
|
||||
** This will allow it to be deallocated.
|
||||
*/
|
||||
static int test_clear_tsd_memdebug(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
#if defined(SQLITE_MEMDEBUG)
|
||||
ThreadData *pTd = sqlite3ThreadData();
|
||||
pTd->nMaxAlloc = 0;
|
||||
pTd->zFile = 0;
|
||||
pTd->iLine = 0;
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_tsd_release
|
||||
**
|
||||
** Call sqlite3ReleaseThreadData.
|
||||
*/
|
||||
static int test_tsd_release(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
#if defined(SQLITE_MEMDEBUG)
|
||||
sqlite3ReleaseThreadData();
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_thread_cleanup
|
||||
**
|
||||
** Call the sqlite3_thread_cleanup API.
|
||||
*/
|
||||
static int test_thread_cleanup(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_thread_cleanup();
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This routine sets entries in the global ::sqlite_options() array variable
|
||||
** according to the compile-time configuration of the database. Test
|
||||
@ -3372,8 +3426,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_changes", test_changes ,0 },
|
||||
{ "sqlite3_step", test_step ,0 },
|
||||
|
||||
{ "sqlite3_release_memory", test_release_memory, 0},
|
||||
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
||||
{ "sqlite3_release_memory", test_release_memory, 0},
|
||||
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
||||
{ "sqlite3_clear_tsd_memdebug", test_clear_tsd_memdebug, 0},
|
||||
{ "sqlite3_tsd_release", test_tsd_release, 0},
|
||||
{ "sqlite3_thread_cleanup", test_thread_cleanup, 0},
|
||||
|
||||
/* sqlite3_column_*() API */
|
||||
{ "sqlite3_column_count", test_column_count ,0 },
|
||||
@ -3429,6 +3486,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
extern int sqlite3_malloc_id;
|
||||
extern int sqlite3_memMax;
|
||||
extern int sqlite3_like_count;
|
||||
extern int sqlite3_tsd_count;
|
||||
#if OS_WIN
|
||||
extern int sqlite3_os_type;
|
||||
#endif
|
||||
@ -3461,6 +3519,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
(char*)&sqlite3_current_time, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite_os_trace",
|
||||
(char*)&sqlite3_os_trace, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite3_tsd_count",
|
||||
(char*)&sqlite3_tsd_count, TCL_LINK_INT);
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
Tcl_LinkVar(interp, "sqlite_last_needed_collation",
|
||||
(char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
|
||||
@ -3507,8 +3567,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
#endif /* OS_UNIX */
|
||||
set_options(interp);
|
||||
|
||||
int sqlite3_shared_cache_report(void *, Tcl_Interp *, int, Tcl_Obj *CONST[]);
|
||||
Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report",
|
||||
sqlite3_shared_cache_report, 0, 0);
|
||||
{
|
||||
extern int sqlite3_shared_cache_report(void *, Tcl_Interp *,
|
||||
int, Tcl_Obj *CONST[]);
|
||||
Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report",
|
||||
sqlite3_shared_cache_report, 0, 0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Code for testing the the SQLite library in a multithreaded environment.
|
||||
**
|
||||
** $Id: test4.c,v 1.13 2005/08/11 02:10:19 drh Exp $
|
||||
** $Id: test4.c,v 1.14 2006/01/11 23:40:34 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -97,6 +97,7 @@ static void *thread_main(void *pArg){
|
||||
p->zErr = 0;
|
||||
}
|
||||
p->completed++;
|
||||
sqlite3_thread_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
** Code for testing the client/server version of the SQLite library.
|
||||
** Derived from test4.c.
|
||||
**
|
||||
** $Id: test7.c,v 1.1 2006/01/09 23:40:25 drh Exp $
|
||||
** $Id: test7.c,v 1.2 2006/01/11 23:40:34 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -118,6 +118,7 @@ static void *client_main(void *pArg){
|
||||
p->zErr = 0;
|
||||
}
|
||||
p->completed++;
|
||||
sqlite3_thread_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements some common TCL routines used for regression
|
||||
# testing the SQLite library
|
||||
#
|
||||
# $Id: tester.tcl,v 1.58 2006/01/06 22:11:21 drh Exp $
|
||||
# $Id: tester.tcl,v 1.59 2006/01/11 23:40:34 drh Exp $
|
||||
|
||||
# Make sure tclsqlite3 was compiled correctly. Abort now with an
|
||||
# error message if not.
|
||||
@ -149,7 +149,16 @@ proc finalize_testing {} {
|
||||
catch {
|
||||
pp_check_for_leaks
|
||||
}
|
||||
|
||||
sqlite3 db {}
|
||||
sqlite3_clear_tsd_memdebug
|
||||
db close
|
||||
if {$::sqlite3_tsd_count} {
|
||||
puts "Thread-specific data leak: $::sqlite3_tsd_count instances"
|
||||
incr nErr
|
||||
} else {
|
||||
puts "Thread-specific data deallocated properly"
|
||||
}
|
||||
incr nTest
|
||||
puts "$nErr errors out of $nTest tests"
|
||||
puts "Failures on these tests: $::failList"
|
||||
if {$nProb>0} {
|
||||
|
@ -1,4 +1,4 @@
|
||||
set rcsid {$Id: capi3ref.tcl,v 1.27 2006/01/10 18:08:10 danielk1977 Exp $}
|
||||
set rcsid {$Id: capi3ref.tcl,v 1.28 2006/01/11 23:40:34 drh Exp $}
|
||||
source common.tcl
|
||||
header {C/C++ Interface For SQLite Version 3}
|
||||
puts {
|
||||
@ -1237,6 +1237,10 @@ api {} {
|
||||
There is no mechanism for sharing cache between database connections
|
||||
running in different threads.
|
||||
|
||||
Sharing must be disabled prior to shutting down a thread or else
|
||||
the thread will leak memory. Call this routine with an argument of
|
||||
0 to turn of sharing. Or use the sqlite3_thread_cleanup() API.
|
||||
|
||||
This routine must not be called when any database connections
|
||||
are active in the current thread. Enabling or disabling shared
|
||||
cache while there are active database connections will result
|
||||
@ -1264,55 +1268,20 @@ api {} {
|
||||
}
|
||||
|
||||
api {} {
|
||||
int sqlite3_enable_memory_management(int);
|
||||
void sqlite3_thread_cleanup(void);
|
||||
} {
|
||||
This routine enables or disables heap memory management for the
|
||||
thread in which it is called. Memory management is enabled if
|
||||
the argument is true and disabled if the argument is false.
|
||||
This routine makes sure that all thread local storage used by SQLite
|
||||
in the current thread has been deallocated. A thread can call this
|
||||
routine prior to terminating in order to make sure there are no memory
|
||||
leaks.
|
||||
|
||||
This routine must not be called when any database connections
|
||||
are active in the current thread. Enabling or disabling memory
|
||||
management while there are active database connections will result
|
||||
in memory corruption.
|
||||
|
||||
When memory management is enabled, SQLite tries to automatically
|
||||
recover from out-of-memory errors by freeing unused cache memory
|
||||
and retrying the allocation.
|
||||
This allows operations to continue when available memory is limit
|
||||
though with some loss of performance due to the reduction in cache
|
||||
size.
|
||||
|
||||
The sqlite3_soft_heap_limit() API can be used to restrict SQLite's
|
||||
heap memory usage to a preset amount so that the reclamation of
|
||||
cache begins to occur before memory is exhausted.
|
||||
|
||||
Memory management is enabled and disabled on a thread-by-thread basis.
|
||||
Each call to this routine enables or disabled memory management only for
|
||||
database connections created and used in the same thread in which this
|
||||
routine is called.
|
||||
|
||||
For any given database connection, SQLite requires that the
|
||||
following routines always be called from the same thread:
|
||||
sqlite3_open(), sqlite3_prepare(), sqlite3_step(), sqlite3_reset(),
|
||||
sqlite3_finalize(), and sqlite3_close(). On some operating systems
|
||||
(ex: windows and linux 2.6) you can get away with calling these routines
|
||||
from different threads as long as their executions never overlap in time
|
||||
and memory management is disabled.
|
||||
But when the memory management is enabled, some information about the
|
||||
database connections is stored in thread-specific storage so that it
|
||||
will be available to remediate memory shortages. Consequently,
|
||||
the previously enumerated routines must always be called from the
|
||||
same thread when memory management is enabled, regardless of what
|
||||
operating system is used.
|
||||
|
||||
This routine returns SQLITE_OK if the memory management module was
|
||||
enabled or disabled successfully. An error code is returned
|
||||
otherwise.
|
||||
|
||||
Memory management is disabled by default for backwards compatibility
|
||||
and because it is normally only useful for embedded devices. The
|
||||
code that implements the memory management feature can be omitted by
|
||||
recompiling SQLite with the SQLITE_OMIT_MEMORY_MANAGEMENT macro defined.
|
||||
This routine is not strictly necessary. If cache sharing has been
|
||||
disabled using sqlite3_enable_shared_cache() and if all database
|
||||
connections have been closed and if SQLITE_ENABLE_MEMORY_MANAGMENT is
|
||||
on and all memory has been freed, then the thread local storage will
|
||||
already have been automatically deallocated. This routine is provided
|
||||
as a convenience to the program who just wants to make sure that there
|
||||
are no leaks.
|
||||
}
|
||||
|
||||
api {} {
|
||||
@ -1323,30 +1292,29 @@ api {} {
|
||||
routine is called. The value returned is the number of bytes actually
|
||||
freed.
|
||||
|
||||
If memory management has not been enabled by calling
|
||||
sqlite3_enable_memory_management() then this routine is a no-op
|
||||
and always returns 0.
|
||||
This routine is only available if memory management has been enabled
|
||||
by compiling with the SQLITE_ENABLE_MEMORY_MANAGMENT macro.
|
||||
}
|
||||
|
||||
api {} {
|
||||
void sqlite3_soft_heap_limit(int N);
|
||||
} {
|
||||
This routine sets the soft heap limit for the current thread to N.
|
||||
If memory management is enabled on the thread by the
|
||||
sqlite3_enable_memory_management() function and the total heap usage
|
||||
by SQLite in that thread exceeds N, then sqlite3_release_memory() is
|
||||
If the total heap usage by SQLite in the current thread exceeds N,
|
||||
then sqlite3_release_memory() is
|
||||
called to try to reduce the memory usage below the soft limit.
|
||||
|
||||
A negative value for N means that there is no soft heap limit and
|
||||
A negative or zero value for N means that there is no soft heap limit and
|
||||
sqlite3_release_memory() will only be called when memory is exhaused.
|
||||
The default value for the soft heap limit is negative.
|
||||
The default value for the soft heap limit is zero.
|
||||
|
||||
SQLite makes a best effort to honor the soft heap limit. But if it
|
||||
is unable to reduce memory usage below the soft limit, execution will
|
||||
continue without error or notification. This is why the limit is
|
||||
called a "soft" limit. It is advisory only.
|
||||
|
||||
If memory management is not enabled, the soft heap limit is ignored.
|
||||
This routine is only available if memory management has been enabled
|
||||
by compiling with the SQLITE_ENABLE_MEMORY_MANAGMENT macro.
|
||||
}
|
||||
|
||||
set n 0
|
||||
|
Reference in New Issue
Block a user