4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 *************************************************************************
13 ** This file contains a binding of the asynchronous IO extension interface
14 ** (defined in ext/async/sqlite3async.h) to Tcl.
18 #if defined(INCLUDE_SQLITE_TCL_H)
19 # include "sqlite_tcl.h"
22 # ifndef SQLITE_TCLAPI
23 # define SQLITE_TCLAPI
27 #ifdef SQLITE_ENABLE_ASYNCIO
29 #include "sqlite3async.h"
34 extern const char *sqlite3ErrName(int);
37 struct TestAsyncGlobal
{
38 int isInstalled
; /* True when async VFS is installed */
39 } testasync_g
= { 0 };
41 TCL_DECLARE_MUTEX(testasync_g_writerMutex
);
44 ** sqlite3async_initialize PARENT-VFS ISDEFAULT
46 static int SQLITE_TCLAPI
testAsyncInit(
57 Tcl_WrongNumArgs(interp
, 1, objv
, "PARENT-VFS ISDEFAULT");
60 zParent
= Tcl_GetString(objv
[1]);
64 if( Tcl_GetBooleanFromObj(interp
, objv
[2], &isDefault
) ){
68 rc
= sqlite3async_initialize(zParent
, isDefault
);
70 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
77 ** sqlite3async_shutdown
79 static int SQLITE_TCLAPI
testAsyncShutdown(
85 sqlite3async_shutdown();
89 static Tcl_ThreadCreateType
tclWriterThread(ClientData pIsStarted
){
90 Tcl_MutexLock(&testasync_g_writerMutex
);
91 *((int *)pIsStarted
) = 1;
93 Tcl_MutexUnlock(&testasync_g_writerMutex
);
95 TCL_THREAD_CREATE_RETURN
;
101 ** Start a new writer thread.
103 static int SQLITE_TCLAPI
testAsyncStart(
107 Tcl_Obj
*CONST objv
[]
109 volatile int isStarted
= 0;
110 ClientData threadData
= (ClientData
)&isStarted
;
113 const int nStack
= TCL_THREAD_STACK_DEFAULT
;
114 const int flags
= TCL_THREAD_NOFLAGS
;
117 rc
= Tcl_CreateThread(&x
, tclWriterThread
, threadData
, nStack
, flags
);
119 Tcl_AppendResult(interp
, "Tcl_CreateThread() failed", 0);
123 while( isStarted
==0 ) { /* Busy loop */ }
130 ** Wait for the current writer thread to terminate.
132 ** If the current writer thread is set to run forever then this
133 ** command would block forever. To prevent that, an error is returned.
135 static int SQLITE_TCLAPI
testAsyncWait(
139 Tcl_Obj
*CONST objv
[]
143 Tcl_WrongNumArgs(interp
, 1, objv
, "");
147 sqlite3async_control(SQLITEASYNC_GET_HALT
, &eCond
);
148 if( eCond
==SQLITEASYNC_HALT_NEVER
){
149 Tcl_AppendResult(interp
, "would block forever", (char*)0);
153 Tcl_MutexLock(&testasync_g_writerMutex
);
154 Tcl_MutexUnlock(&testasync_g_writerMutex
);
159 ** sqlite3async_control OPTION ?VALUE?
161 static int SQLITE_TCLAPI
testAsyncControl(
165 Tcl_Obj
*CONST objv
[]
168 int aeOpt
[] = { SQLITEASYNC_HALT
, SQLITEASYNC_DELAY
, SQLITEASYNC_LOCKFILES
};
169 const char *azOpt
[] = { "halt", "delay", "lockfiles", 0 };
170 const char *az
[] = { "never", "now", "idle", 0 };
174 if( objc
!=2 && objc
!=3 ){
175 Tcl_WrongNumArgs(interp
, 1, objv
, "OPTION ?VALUE?");
178 if( Tcl_GetIndexFromObj(interp
, objv
[1], azOpt
, "option", 0, &eOpt
) ){
185 case SQLITEASYNC_HALT
: {
186 assert( SQLITEASYNC_HALT_NEVER
==0 );
187 assert( SQLITEASYNC_HALT_NOW
==1 );
188 assert( SQLITEASYNC_HALT_IDLE
==2 );
189 if( Tcl_GetIndexFromObj(interp
, objv
[2], az
, "value", 0, &iVal
) ){
194 case SQLITEASYNC_DELAY
:
195 if( Tcl_GetIntFromObj(interp
, objv
[2], &iVal
) ){
200 case SQLITEASYNC_LOCKFILES
:
201 if( Tcl_GetBooleanFromObj(interp
, objv
[2], &iVal
) ){
207 rc
= sqlite3async_control(eOpt
, iVal
);
211 rc
= sqlite3async_control(
212 eOpt
==SQLITEASYNC_HALT
? SQLITEASYNC_GET_HALT
:
213 eOpt
==SQLITEASYNC_DELAY
? SQLITEASYNC_GET_DELAY
:
214 SQLITEASYNC_GET_LOCKFILES
, &iVal
);
218 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
222 if( eOpt
==SQLITEASYNC_HALT
){
223 Tcl_SetObjResult(interp
, Tcl_NewStringObj(az
[iVal
], -1));
225 Tcl_SetObjResult(interp
, Tcl_NewIntObj(iVal
));
231 #endif /* SQLITE_ENABLE_ASYNCIO */
234 ** This routine registers the custom TCL commands defined in this
235 ** module. This should be the only procedure visible from outside
238 int Sqlitetestasync_Init(Tcl_Interp
*interp
){
239 #ifdef SQLITE_ENABLE_ASYNCIO
240 Tcl_CreateObjCommand(interp
,"sqlite3async_start",testAsyncStart
,0,0);
241 Tcl_CreateObjCommand(interp
,"sqlite3async_wait",testAsyncWait
,0,0);
243 Tcl_CreateObjCommand(interp
,"sqlite3async_control",testAsyncControl
,0,0);
244 Tcl_CreateObjCommand(interp
,"sqlite3async_initialize",testAsyncInit
,0,0);
245 Tcl_CreateObjCommand(interp
,"sqlite3async_shutdown",testAsyncShutdown
,0,0);
246 #endif /* SQLITE_ENABLE_ASYNCIO */