1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
/* KInterbasDB Python Package - Header File for Central Concurrency Facilities
*
* Version 3.3
*
* The following contributors hold Copyright (C) over their respective
* portions of code (see license.txt for details):
*
* [Original Author (maintained through version 2.0-0.3.1):]
* 1998-2001 [alex] Alexander Kuznetsov <alexan@users.sourceforge.net>
* [Maintainers (after version 2.0-0.3.1):]
* 2001-2002 [maz] Marek Isalski <kinterbasdb@maz.nu>
* 2002-2007 [dsr] David Rushby <woodsplitter@rocketmail.com>
* [Contributors:]
* 2001 [eac] Evgeny A. Cherkashin <eugeneai@icc.ru>
* 2001-2002 [janez] Janez Jere <janez.jere@void.si>
*/
/************** CONCEPTUAL NOTES (for Python client programmers) **************
* See docs/usage.html#special_issue_concurrency
*/
/************* IMPLEMENTATION NOTES (for KInterbasDB maintainers) *************
*
* 1. The GDAL (which is active at Level 1 and inactive at Level 2) and the
* GCDL (which is inactive at Level 1 and active at Level 2) are conceptually
* separate, but can be implemented as a single lock object due to the fact
* that the two conceptual locks are never active at the same time.
* To avoid confusion in the bulk of the kinterbasdb code, and to prepare
* for the potential introduction of concurrency levels greater than 2, the
* macros for manipulating the GDAL and the GCDL are arranged to imply that
* the two conceptually separate locks are truly different objects.
*/
#ifndef _KILOCK_H
#define _KILOCK_H
#include "_kinterbasdb.h"
#ifdef ENABLE_CONCURRENCY
#include "pythread.h"
extern PyThread_type_lock _global_db_client_lock;
/* The following aliases are defined due to factors discussed in
* Implementation Note #1 (see above). */
#define global_GDAL _global_db_client_lock
#define global_GCDL _global_db_client_lock
/*************************** Python GIL ************************/
/* The next two macros are for manipulating the GIL using an explicit thread
* state. For example, a thread that's bootstrapped from C, and only enters
* the GIL occasionally, might use these. */
#define ENTER_GIL_USING_THREADSTATE(ts) \
debug_print3("GIL-> ?ACQUIRE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyEval_RestoreThread(ts); \
debug_print3("GIL-> !!ACQUIRED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
#define LEAVE_GIL_USING_THREADSTATE(ts) \
/* Notice that ts is not actually used in the current implementation of \
* this macro. */ \
debug_print3("GIL-> ?RELEASE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyEval_SaveThread(); \
debug_print3("GIL-> !RELEASED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
#define LEAVE_GIL_WITHOUT_AFFECTING_DB \
debug_print3("GIL-> ?RELEASE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
Py_BEGIN_ALLOW_THREADS \
debug_print3("GIL-> !RELEASED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
#define ENTER_GIL_WITHOUT_AFFECTING_DB \
debug_print3("GIL-> ?ACQUIRE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
Py_END_ALLOW_THREADS \
debug_print3("GIL-> !!ACQUIRED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
#define OPEN_LOCAL_GIL_MANIPULATION_INFRASTRUCTURE \
{ PyThreadState *_save = NULL;
#define CLOSE_LOCAL_GIL_MANIPULATION_INFRASTRUCTURE }
#define LEAVE_GIL_WITHOUT_AFFECTING_DB_AND_WITHOUT_STARTING_CODE_BLOCK \
debug_print3("GIL-> ?RELEASE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
Py_UNBLOCK_THREADS \
debug_print3("GIL-> !!RELEASED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
#define ENTER_GIL_WITHOUT_AFFECTING_DB_AND_WITHOUT_ENDING_CODE_BLOCK \
debug_print3("GIL-> ?ACQUIRE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
Py_BLOCK_THREADS \
debug_print3("GIL-> !!ACQUIRED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
);
/*************************** GDAL ************************/
#define ENTER_GDAL \
{ \
LEAVE_GIL_WITHOUT_AFFECTING_DB \
ENTER_GDAL_WITHOUT_LEAVING_PYTHON
#define LEAVE_GDAL \
LEAVE_GDAL_WITHOUT_ENTERING_PYTHON \
ENTER_GIL_WITHOUT_AFFECTING_DB \
}
#define ENTER_GDAL_WITHOUT_LEAVING_PYTHON \
if (global_concurrency_level == 1) { \
debug_print3("GDAL-> ?ACQUIRE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyThread_acquire_lock(global_GDAL, WAIT_LOCK); \
debug_print3("GDAL-> !!ACQUIRED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
}
#define LEAVE_GDAL_WITHOUT_ENTERING_PYTHON \
if (global_concurrency_level == 1) { \
debug_print3("GDAL-> ?RELEASE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyThread_release_lock(global_GDAL); \
debug_print3("GDAL-> !RELEASED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
}
#define LEAVE_GDAL_WITHOUT_ENDING_CODE_BLOCK \
LEAVE_GDAL_WITHOUT_ENTERING_PYTHON \
ENTER_GIL_WITHOUT_AFFECTING_DB_AND_WITHOUT_ENDING_CODE_BLOCK
/*************************** GCDL ************************/
#define ENTER_GCDL \
{ \
LEAVE_GIL_WITHOUT_AFFECTING_DB \
ENTER_GCDL_WITHOUT_LEAVING_PYTHON
#define LEAVE_GCDL \
LEAVE_GCDL_WITHOUT_ENTERING_PYTHON \
ENTER_GIL_WITHOUT_AFFECTING_DB \
}
#ifdef ENABLE_FREE_CONNECTION_AND_DISCONNECTION
/* Connection and disconnection are not serialized. */
#define ENTER_GCDL_WITHOUT_LEAVING_PYTHON
#define LEAVE_GCDL_WITHOUT_ENTERING_PYTHON
#else
/* Serialize connection and disconnection. If we're operating at a
* concurrency_level < 2, the GDAL already performs this serialization. */
#define ENTER_GCDL_WITHOUT_LEAVING_PYTHON \
if (global_concurrency_level > 1) { \
debug_print3("GCDL-> ?ACQUIRE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyThread_acquire_lock(global_GCDL, WAIT_LOCK); \
debug_print3("GCDL-> !!ACQUIRED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
}
#define LEAVE_GCDL_WITHOUT_ENTERING_PYTHON \
if (global_concurrency_level > 1) { \
debug_print3("GCDL-> ?RELEASE: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
PyThread_release_lock(global_GCDL); \
debug_print3("GCDL-> !RELEASED: %ld file %s line %d\n", \
PyThread_get_thread_ident(), __FILE__, __LINE__ \
); \
}
#endif /* ENABLE_FREE_CONNECTION_AND_DISCONNECTION */
#else /* ndef ENABLE_CONCURRENCY */
#define ENTER_GDAL
#define LEAVE_GDAL
#define ENTER_GCDL
#define LEAVE_GCDL
#define ENTER_GIL_USING_THREADSTATE(ts)
#define LEAVE_GIL_USING_THREADSTATE(ts)
#define LEAVE_GIL_WITHOUT_AFFECTING_DB
#define ENTER_GIL_WITHOUT_AFFECTING_DB
#define ENTER_GIL_WITHOUT_AFFECTING_DB_AND_WITHOUT_ENDING_CODE_BLOCK
#define ENTER_GDAL_WITHOUT_LEAVING_PYTHON
#define LEAVE_GDAL_WITHOUT_ENTERING_PYTHON
#define LEAVE_GDAL_WITHOUT_ENDING_CODE_BLOCK
#define ENTER_GCDL_WITHOUT_LEAVING_PYTHON
#define LEAVE_GCDL_WITHOUT_ENTERING_PYTHON
#endif /* def ENABLE_CONCURRENCY */
#endif /* not def _KILOCK_H */
|