File: _kilock.h

package info (click to toggle)
python-kinterbasdb 3.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,432 kB
  • ctags: 1,830
  • sloc: ansic: 16,803; python: 3,514; makefile: 63; sh: 22
file content (218 lines) | stat: -rw-r--r-- 8,006 bytes parent folder | download | duplicates (2)
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 */