OLD | NEW |
1 /* | 1 /* |
2 ** 2007 September 9 | 2 ** 2007 September 9 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** | 12 ** |
13 ** This file contains the implementation of some Tcl commands used to | 13 ** This file contains the implementation of some Tcl commands used to |
14 ** test that sqlite3 database handles may be concurrently accessed by | 14 ** test that sqlite3 database handles may be concurrently accessed by |
15 ** multiple threads. Right now this only works on unix. | 15 ** multiple threads. Right now this only works on unix. |
16 ** | |
17 ** $Id: test_thread.c,v 1.15 2009/03/27 12:32:56 drh Exp $ | |
18 */ | 16 */ |
19 | 17 |
20 #include "sqliteInt.h" | 18 #include "sqliteInt.h" |
21 #include <tcl.h> | 19 #include <tcl.h> |
22 | 20 |
23 #if SQLITE_THREADSAFE | 21 #if SQLITE_THREADSAFE |
24 | 22 |
25 #include <errno.h> | 23 #include <errno.h> |
26 | 24 |
27 #if !defined(_MSC_VER) | 25 #if !defined(_MSC_VER) |
(...skipping 20 matching lines...) Expand all Loading... |
48 */ | 46 */ |
49 typedef struct EvalEvent EvalEvent; | 47 typedef struct EvalEvent EvalEvent; |
50 struct EvalEvent { | 48 struct EvalEvent { |
51 Tcl_Event base; /* Base class of type Tcl_Event */ | 49 Tcl_Event base; /* Base class of type Tcl_Event */ |
52 char *zScript; /* The script to execute. */ | 50 char *zScript; /* The script to execute. */ |
53 Tcl_Interp *interp; /* The interpreter to execute it in. */ | 51 Tcl_Interp *interp; /* The interpreter to execute it in. */ |
54 }; | 52 }; |
55 | 53 |
56 static Tcl_ObjCmdProc sqlthread_proc; | 54 static Tcl_ObjCmdProc sqlthread_proc; |
57 static Tcl_ObjCmdProc clock_seconds_proc; | 55 static Tcl_ObjCmdProc clock_seconds_proc; |
58 #if defined(SQLITE_OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) | 56 #if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) |
59 static Tcl_ObjCmdProc blocking_step_proc; | 57 static Tcl_ObjCmdProc blocking_step_proc; |
60 static Tcl_ObjCmdProc blocking_prepare_v2_proc; | 58 static Tcl_ObjCmdProc blocking_prepare_v2_proc; |
61 #endif | 59 #endif |
62 int Sqlitetest1_Init(Tcl_Interp *); | 60 int Sqlitetest1_Init(Tcl_Interp *); |
| 61 int Sqlite3_Init(Tcl_Interp *); |
63 | 62 |
64 /* Functions from test1.c */ | 63 /* Functions from test1.c */ |
65 void *sqlite3TestTextToPtr(const char *); | 64 void *sqlite3TestTextToPtr(const char *); |
66 const char *sqlite3TestErrorName(int); | 65 const char *sqlite3TestErrorName(int); |
67 int getDbPointer(Tcl_Interp *, const char *, sqlite3 **); | 66 int getDbPointer(Tcl_Interp *, const char *, sqlite3 **); |
68 int sqlite3TestMakePointerStr(Tcl_Interp *, char *, void *); | 67 int sqlite3TestMakePointerStr(Tcl_Interp *, char *, void *); |
69 int sqlite3TestErrCode(Tcl_Interp *, sqlite3 *, int); | 68 int sqlite3TestErrCode(Tcl_Interp *, sqlite3 *, int); |
70 | 69 |
71 /* | 70 /* |
72 ** Handler for events of type EvalEvent. | 71 ** Handler for events of type EvalEvent. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 Tcl_Interp *interp; | 109 Tcl_Interp *interp; |
111 Tcl_Obj *pRes; | 110 Tcl_Obj *pRes; |
112 Tcl_Obj *pList; | 111 Tcl_Obj *pList; |
113 int rc; | 112 int rc; |
114 SqlThread *p = (SqlThread *)pSqlThread; | 113 SqlThread *p = (SqlThread *)pSqlThread; |
115 extern int Sqlitetest_mutex_Init(Tcl_Interp*); | 114 extern int Sqlitetest_mutex_Init(Tcl_Interp*); |
116 | 115 |
117 interp = Tcl_CreateInterp(); | 116 interp = Tcl_CreateInterp(); |
118 Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); | 117 Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); |
119 Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0); | 118 Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0); |
120 #if defined(SQLITE_OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) | 119 #if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) |
121 Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); | 120 Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); |
122 Tcl_CreateObjCommand(interp, | 121 Tcl_CreateObjCommand(interp, |
123 "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); | 122 "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); |
124 Tcl_CreateObjCommand(interp, | 123 Tcl_CreateObjCommand(interp, |
125 "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); | 124 "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); |
126 #endif | 125 #endif |
127 Sqlitetest1_Init(interp); | 126 Sqlitetest1_Init(interp); |
128 Sqlitetest_mutex_Init(interp); | 127 Sqlitetest_mutex_Init(interp); |
| 128 Sqlite3_Init(interp); |
129 | 129 |
130 rc = Tcl_Eval(interp, p->zScript); | 130 rc = Tcl_Eval(interp, p->zScript); |
131 pRes = Tcl_GetObjResult(interp); | 131 pRes = Tcl_GetObjResult(interp); |
132 pList = Tcl_NewObj(); | 132 pList = Tcl_NewObj(); |
133 Tcl_IncrRefCount(pList); | 133 Tcl_IncrRefCount(pList); |
134 Tcl_IncrRefCount(pRes); | 134 Tcl_IncrRefCount(pRes); |
135 | 135 |
136 if( rc!=TCL_OK ){ | 136 if( rc!=TCL_OK ){ |
137 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1)); | 137 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1)); |
138 Tcl_ListObjAppendElement(interp, pList, pRes); | 138 Tcl_ListObjAppendElement(interp, pList, pRes); |
139 postToParent(p, pList); | 139 postToParent(p, pList); |
140 Tcl_DecrRefCount(pList); | 140 Tcl_DecrRefCount(pList); |
141 pList = Tcl_NewObj(); | 141 pList = Tcl_NewObj(); |
142 } | 142 } |
143 | 143 |
144 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1)); | 144 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1)); |
145 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1)); | 145 Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1)); |
146 Tcl_ListObjAppendElement(interp, pList, pRes); | 146 Tcl_ListObjAppendElement(interp, pList, pRes); |
147 postToParent(p, pList); | 147 postToParent(p, pList); |
148 | 148 |
149 ckfree((void *)p); | 149 ckfree((void *)p); |
150 Tcl_DecrRefCount(pList); | 150 Tcl_DecrRefCount(pList); |
151 Tcl_DecrRefCount(pRes); | 151 Tcl_DecrRefCount(pRes); |
152 Tcl_DeleteInterp(interp); | 152 Tcl_DeleteInterp(interp); |
| 153 while( Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT) ); |
| 154 Tcl_ExitThread(0); |
153 TCL_THREAD_CREATE_RETURN; | 155 TCL_THREAD_CREATE_RETURN; |
154 } | 156 } |
155 | 157 |
156 /* | 158 /* |
157 ** sqlthread spawn VARNAME SCRIPT | 159 ** sqlthread spawn VARNAME SCRIPT |
158 ** | 160 ** |
159 ** Spawn a new thread with its own Tcl interpreter and run the | 161 ** Spawn a new thread with its own Tcl interpreter and run the |
160 ** specified SCRIPT(s) in it. The thread terminates after running | 162 ** specified SCRIPT(s) in it. The thread terminates after running |
161 ** the script. The result of the script is stored in the variable | 163 ** the script. The result of the script is stored in the variable |
162 ** VARNAME. | 164 ** VARNAME. |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 ** is only available on UNIX for now. This is because pthread condition | 385 ** is only available on UNIX for now. This is because pthread condition |
384 ** variables are used. | 386 ** variables are used. |
385 ** | 387 ** |
386 ** The source code for the C functions sqlite3_blocking_step(), | 388 ** The source code for the C functions sqlite3_blocking_step(), |
387 ** blocking_step_notify() and the structure UnlockNotification is | 389 ** blocking_step_notify() and the structure UnlockNotification is |
388 ** automatically extracted from this file and used as part of the | 390 ** automatically extracted from this file and used as part of the |
389 ** documentation for the sqlite3_unlock_notify() API function. This | 391 ** documentation for the sqlite3_unlock_notify() API function. This |
390 ** should be considered if these functions are to be extended (i.e. to | 392 ** should be considered if these functions are to be extended (i.e. to |
391 ** support windows) in the future. | 393 ** support windows) in the future. |
392 */ | 394 */ |
393 #if defined(SQLITE_OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) | 395 #if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) |
394 | 396 |
395 /* BEGIN_SQLITE_BLOCKING_STEP */ | 397 /* BEGIN_SQLITE_BLOCKING_STEP */ |
396 /* This example uses the pthreads API */ | 398 /* This example uses the pthreads API */ |
397 #include <pthread.h> | 399 #include <pthread.h> |
398 | 400 |
399 /* | 401 /* |
400 ** A pointer to an instance of this structure is passed as the user-context | 402 ** A pointer to an instance of this structure is passed as the user-context |
401 ** pointer when registering for an unlock-notify callback. | 403 ** pointer when registering for an unlock-notify callback. |
402 */ | 404 */ |
403 typedef struct UnlockNotification UnlockNotification; | 405 typedef struct UnlockNotification UnlockNotification; |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 /* | 607 /* |
606 ** End of implementation of [sqlite3_blocking_step]. | 608 ** End of implementation of [sqlite3_blocking_step]. |
607 ************************************************************************/ | 609 ************************************************************************/ |
608 | 610 |
609 /* | 611 /* |
610 ** Register commands with the TCL interpreter. | 612 ** Register commands with the TCL interpreter. |
611 */ | 613 */ |
612 int SqlitetestThread_Init(Tcl_Interp *interp){ | 614 int SqlitetestThread_Init(Tcl_Interp *interp){ |
613 Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0); | 615 Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0); |
614 Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); | 616 Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); |
615 #if defined(SQLITE_OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) | 617 #if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) |
616 Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); | 618 Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); |
617 Tcl_CreateObjCommand(interp, | 619 Tcl_CreateObjCommand(interp, |
618 "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); | 620 "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); |
619 Tcl_CreateObjCommand(interp, | 621 Tcl_CreateObjCommand(interp, |
620 "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); | 622 "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); |
621 #endif | 623 #endif |
622 return TCL_OK; | 624 return TCL_OK; |
623 } | 625 } |
624 #else | 626 #else |
625 int SqlitetestThread_Init(Tcl_Interp *interp){ | 627 int SqlitetestThread_Init(Tcl_Interp *interp){ |
626 return TCL_OK; | 628 return TCL_OK; |
627 } | 629 } |
628 #endif | 630 #endif |
OLD | NEW |