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
|
#define _RESOLVE_MODINIT_FUNC_NAME(NAME) \
PyInit_ ## NAME
#define RESOLVE_MODINIT_FUNC_NAME(NAME) \
_RESOLVE_MODINIT_FUNC_NAME(NAME)
#define GETDATA(FUNC) ((_PyXIData_getdata_t){.basic=FUNC})
static int
ensure_xid_class(PyTypeObject *cls, _PyXIData_getdata_t getdata)
{
PyThreadState *tstate = PyThreadState_Get();
return _PyXIData_RegisterClass(tstate, cls, getdata);
}
#ifdef REGISTERS_HEAP_TYPES
static int
clear_xid_class(PyTypeObject *cls)
{
PyThreadState *tstate = PyThreadState_Get();
return _PyXIData_UnregisterClass(tstate, cls);
}
#endif
static inline int64_t
_get_interpid(_PyXIData_t *data)
{
int64_t interpid;
if (data != NULL) {
interpid = _PyXIData_INTERPID(data);
assert(!PyErr_Occurred());
}
else {
interpid = PyInterpreterState_GetID(PyInterpreterState_Get());
}
return interpid;
}
#ifdef HAS_FALLBACK
static int
resolve_fallback(int arg, xidata_fallback_t dflt,
xidata_fallback_t *p_fallback)
{
if (arg < 0) {
*p_fallback = dflt;
return 0;
}
xidata_fallback_t fallback;
if (arg == _PyXIDATA_XIDATA_ONLY) {
fallback =_PyXIDATA_XIDATA_ONLY;
}
else if (arg == _PyXIDATA_FULL_FALLBACK) {
fallback = _PyXIDATA_FULL_FALLBACK;
}
else {
PyErr_Format(PyExc_ValueError, "unsupported fallback %d", arg);
return -1;
}
*p_fallback = fallback;
return 0;
}
#endif
/* unbound items ************************************************************/
#ifdef HAS_UNBOUND_ITEMS
typedef int unboundop_t;
#define UNBOUND_REMOVE 1
#define UNBOUND_ERROR 2
#define UNBOUND_REPLACE 3
// It would also be possible to add UNBOUND_REPLACE where the replacement
// value is user-provided. There would be some limitations there, though.
// Another possibility would be something like UNBOUND_COPY, where the
// object is released but the underlying data is copied (with the "raw"
// allocator) and used when the item is popped off the queue.
#ifndef NDEBUG
static int
check_unbound(int unboundop)
{
switch (unboundop) {
case UNBOUND_REMOVE:
case UNBOUND_ERROR:
case UNBOUND_REPLACE:
return 1;
default:
return 0;
}
}
#endif
static int
resolve_unboundop(int arg, unboundop_t dflt, unboundop_t *p_unboundop)
{
if (arg < 0) {
*p_unboundop = dflt;
return 0;
}
unboundop_t op;
if (arg == UNBOUND_REMOVE) {
op = UNBOUND_REMOVE;
}
else if (arg == UNBOUND_ERROR) {
op = UNBOUND_ERROR;
}
else if (arg == UNBOUND_REPLACE) {
op = UNBOUND_REPLACE;
}
else {
PyErr_Format(PyExc_ValueError, "unsupported unboundop %d", arg);
return -1;
}
*p_unboundop = op;
return 0;
}
#endif
|