-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpython.h
More file actions
175 lines (152 loc) · 4.64 KB
/
Copy pathpython.h
File metadata and controls
175 lines (152 loc) · 4.64 KB
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
/*
* Python utility macros and definitions.
*/
#ifndef PyPg_python_H
#define PyPg_python_H 0
#ifdef __cplusplus
extern "C" {
#endif
#define PYSTR(NAME) py_##NAME##_str_ob
typedef PyObject * PyObj;
extern PyObj Py_builtins_module, Py_compile_ob, PYSTR(exec);
extern const char *python_server_encoding;
PyObj PyObject_AsASCIIString(PyObj stringable_ob);
/* New References */
/* Avoids exception on absence */
#define Py_ATTR(ob,str) (PyObject_HasAttrString(ob,str)? \
PyObject_GetAttrString(ob,str):(PyObj) NULL)
#define Py_Call(OB,...) PyObject_CallFunctionObjArgs(OB, __VA_ARGS__, NULL)
/*
* Create a 'python_server_encoding' encoded bytes object from an arbitrary
* Python object.
*/
#define PyObject_StrBytes(_OB) \
do{ \
PyObj _OB_STR = PyObject_Str(*_OB); \
Assert(_OB != NULL && *_OB != NULL);\
Py_DECREF(*_OB); \
*_OB = NULL; \
if (_OB_STR != NULL) { \
*_OB = PyUnicode_AsEncodedString(_OB_STR, python_server_encoding, "strict"); \
Py_DECREF(_OB_STR); \
} \
}while(0)
#define PyUnicode_FromPointerAndSize(CHAR, SIZE) \
PyUnicode_Decode((const char *) CHAR, SIZE, python_server_encoding, "replace")
#define PyUnicode_FromCString(CHAR) \
PyUnicode_FromPointerAndSize(CHAR, strlen(CHAR))
#define PyUnicode_FromTEXT(TEXT) \
PyUnicode_FromPointerAndSize(VARDATA(TEXT), VARSIZE_ANY_EXHDR(TEXT))
#define Py_Require_Type(TYP, ITYP) \
((PyObj) ITYP == (PyObj) TYP || PyType_IsSubtype((ITYP), ((PyTypeObject *) TYP))) ? 0 : ( \
PyErr_Format(PyExc_TypeError, \
"%s requires a %s, given '%s'", \
PG_FUNCNAME_MACRO, \
((PyTypeObject *) TYP)->tp_name, ((PyTypeObject *) ITYP)->tp_name) ? -1 : -1 \
)
/*
* Python Reference Owners
*
* Py_ALLOCATE_OWNER(), Py_ACQUIRE(), Py_DEALLOCATE_OWNER()
*
* Constructs for tracking and releasing references owned by a C block.
*
* Usage:
*
* Py_ALLOCATE_OWNER();
* {
* PyObj ob;
*
* ob = PyLong_FromLong(10);
* Py_ACQUIRE(ob);
* ...
* ...
* Py_ACQUIRE_SPACE();
* {
* while ((ob = PyIter_Next(iter_ob)) != NULL)
* {
* Py_XREPLACE(ob);
* ...
* }
* }
* Py_RELEASE_SPACE();
* }
* Py_DEALLOCATE_OWNER();
*
* Py_ACQUIRE will "send" the reference to the current owner. When the ownership
* ends(Py_END_OWNERSHIP()), the acquired references will be released.
*
* NOTE: Jumping out of the block will cause reference leaks.
* If you must 'break', or 'goto', be sure to call _PYRO_DEALLOCATE()
* before doing so.
*/
extern struct PyObject_ReferenceOwner *_PyObject_OwnerStack;
#define _PYRO_CAPACITY 8
struct PyObject_ReferenceOwner {
PyObject *acquired[_PYRO_CAPACITY];
int n_objects; /* Number of acquisitions */
};
#define _PYRO_DECLARE_OWNER() \
volatile struct PyObject_ReferenceOwner _next_owner = {{NULL,},0}; \
struct PyObject_ReferenceOwner * volatile _prev_owner; \
_prev_owner = (struct PyObject_ReferenceOwner * volatile) _PyObject_OwnerStack; \
_PyObject_OwnerStack = ((struct PyObject_ReferenceOwner *) &_next_owner)
#define _PYRO_GET_ACQUIRED(_py_NN) \
(_PyObject_OwnerStack->acquired[_py_NN])
#define _PYRO_SET_ACQUIRED(_py_N, _py_OB) \
(_PYRO_GET_ACQUIRED(_py_N) = _py_OB)
#define _PYRO_N_ACQUIRED (_PyObject_OwnerStack->n_objects)
#define Py_ALLOCATE_OWNER() \
{ \
_PYRO_DECLARE_OWNER()
/* cheers, suffix operator. */
#define Py_ACQUIRE(OB) \
(_PYRO_SET_ACQUIRED(_PYRO_N_ACQUIRED++, OB))
#define Py_XACQUIRE(OB) \
(OB == NULL ? NULL : Py_ACQUIRE(OB))
#define Py_ACQUIRE_SPACE() \
{ \
int _pyro_acquired_offset = _PYRO_N_ACQUIRED++; \
Assert(_PYRO_GET_ACQUIRED(_pyro_acquired_offset) == NULL);
/*
* For use with iterators. At the start of a loop, Py_XREPLACE(nextval).
*/
#define Py_XREPLACE(OB) do { \
PyObj _STORED_pyro = _PYRO_GET_ACQUIRED(_pyro_acquired_offset); \
_PYRO_SET_ACQUIRED(_pyro_acquired_offset, OB); \
Py_XDECREF(_STORED_pyro); \
} while (0)
/*
* If we can reclaim the space for further acquisitions, do so.
* Otherwise, just ignore the whole thing let owner deallocation take care of
* the reference.
*/
#define Py_RELEASE_SPACE() \
if (_pyro_acquired_offset + 1 == _PYRO_N_ACQUIRED) \
{ \
PyObj _STORED_pyro = _PYRO_GET_ACQUIRED(_pyro_acquired_offset); \
_PYRO_SET_ACQUIRED(_pyro_acquired_offset, NULL); \
_PYRO_N_ACQUIRED = _pyro_acquired_offset; \
Py_XDECREF(_STORED_pyro); \
} \
}
#define _PYRO_RELEASE_ALL() do { \
int i; \
for (i = 0; i < _PYRO_N_ACQUIRED; ++i) \
{ \
Py_XDECREF(_PYRO_GET_ACQUIRED(i)); \
} \
_PYRO_N_ACQUIRED = 0; \
} while(0)
#define _PYRO_DEALLOCATE(...) do { \
_PYRO_RELEASE_ALL(); \
_PyObject_OwnerStack = ((struct PyObject_ReferenceOwner *) _prev_owner); \
__VA_ARGS__; \
} while(0)
#define Py_DEALLOCATE_OWNER() \
_PYRO_DEALLOCATE(); \
}
#ifdef __cplusplus
}
#endif
#endif /* !PyPg_python_H */