1
1
#include "Python.h"
2
+ #include "structmember.h" // PyMemberDef
2
3
#include <stddef.h> // offsetof()
3
4
4
- /*[clinic input]
5
- module _queue
6
- class _queue.SimpleQueue "simplequeueobject *" "&PySimpleQueueType"
7
- [clinic start generated code]*/
8
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf49af81bcbbbea6]*/
9
-
10
- static PyTypeObject PySimpleQueueType ; /* forward decl */
11
-
12
- static PyObject * EmptyError ;
5
+ typedef struct {
6
+ PyTypeObject * SimpleQueueType ;
7
+ PyObject * EmptyError ;
8
+ } simplequeue_state ;
13
9
10
+ static simplequeue_state *
11
+ simplequeue_get_state (PyObject * module )
12
+ {
13
+ simplequeue_state * state = PyModule_GetState (module );
14
+ assert (state );
15
+ return state ;
16
+ }
17
+ static struct PyModuleDef queuemodule ;
18
+ #define simplequeue_get_state_by_type (tp ) \
19
+ (simplequeue_get_state(_PyType_GetModuleByDef(type, &queuemodule)))
14
20
15
21
typedef struct {
16
22
PyObject_HEAD
@@ -21,10 +27,17 @@ typedef struct {
21
27
PyObject * weakreflist ;
22
28
} simplequeueobject ;
23
29
30
+ /*[clinic input]
31
+ module _queue
32
+ class _queue.SimpleQueue "simplequeueobject *" "simplequeue_get_state_by_type(type)->SimpleQueueType"
33
+ [clinic start generated code]*/
34
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a4023fe4d198c8d]*/
24
35
25
36
static void
26
37
simplequeue_dealloc (simplequeueobject * self )
27
38
{
39
+ PyTypeObject * tp = Py_TYPE (self );
40
+
28
41
PyObject_GC_UnTrack (self );
29
42
if (self -> lock != NULL ) {
30
43
/* Unlock the lock so it's safe to free it */
@@ -36,6 +49,7 @@ simplequeue_dealloc(simplequeueobject *self)
36
49
if (self -> weakreflist != NULL )
37
50
PyObject_ClearWeakRefs ((PyObject * ) self );
38
51
Py_TYPE (self )-> tp_free (self );
52
+ Py_DECREF (tp );
39
53
}
40
54
41
55
static int
@@ -155,6 +169,9 @@ simplequeue_pop_item(simplequeueobject *self)
155
169
156
170
/*[clinic input]
157
171
_queue.SimpleQueue.get
172
+
173
+ cls: defining_class
174
+ /
158
175
block: bool = True
159
176
timeout: object = None
160
177
@@ -171,9 +188,9 @@ in that case).
171
188
[clinic start generated code]*/
172
189
173
190
static PyObject *
174
- _queue_SimpleQueue_get_impl (simplequeueobject * self , int block ,
175
- PyObject * timeout )
176
- /*[clinic end generated code: output=ec82a7157dcccd1a input=4bf691f9f01fa297 ]*/
191
+ _queue_SimpleQueue_get_impl (simplequeueobject * self , PyTypeObject * cls ,
192
+ int block , PyObject * timeout )
193
+ /*[clinic end generated code: output=1969aefa7db63666 input=5fc4d56b9a54757e ]*/
177
194
{
178
195
_PyTime_t endtime = 0 ;
179
196
_PyTime_t timeout_val ;
@@ -225,8 +242,10 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block,
225
242
return NULL ;
226
243
}
227
244
if (r == PY_LOCK_FAILURE ) {
245
+ PyObject * module = PyType_GetModule (cls );
246
+ simplequeue_state * state = simplequeue_get_state (module );
228
247
/* Timed out */
229
- PyErr_SetNone (EmptyError );
248
+ PyErr_SetNone (state -> EmptyError );
230
249
return NULL ;
231
250
}
232
251
self -> locked = 1 ;
@@ -251,17 +270,21 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block,
251
270
/*[clinic input]
252
271
_queue.SimpleQueue.get_nowait
253
272
273
+ cls: defining_class
274
+ /
275
+
254
276
Remove and return an item from the queue without blocking.
255
277
256
278
Only get an item if one is immediately available. Otherwise
257
279
raise the Empty exception.
258
280
[clinic start generated code]*/
259
281
260
282
static PyObject *
261
- _queue_SimpleQueue_get_nowait_impl (simplequeueobject * self )
262
- /*[clinic end generated code: output=a89731a75dbe4937 input=6fe5102db540a1b9]*/
283
+ _queue_SimpleQueue_get_nowait_impl (simplequeueobject * self ,
284
+ PyTypeObject * cls )
285
+ /*[clinic end generated code: output=620c58e2750f8b8a input=842f732bf04216d3]*/
263
286
{
264
- return _queue_SimpleQueue_get_impl (self , 0 , Py_None );
287
+ return _queue_SimpleQueue_get_impl (self , cls , 0 , Py_None );
265
288
}
266
289
267
290
/*[clinic input]
@@ -290,6 +313,29 @@ _queue_SimpleQueue_qsize_impl(simplequeueobject *self)
290
313
return PyList_GET_SIZE (self -> lst ) - self -> lst_pos ;
291
314
}
292
315
316
+ static int
317
+ queue_traverse (PyObject * m , visitproc visit , void * arg )
318
+ {
319
+ simplequeue_state * state = simplequeue_get_state (m );
320
+ Py_VISIT (state -> SimpleQueueType );
321
+ Py_VISIT (state -> EmptyError );
322
+ return 0 ;
323
+ }
324
+
325
+ static int
326
+ queue_clear (PyObject * m )
327
+ {
328
+ simplequeue_state * state = simplequeue_get_state (m );
329
+ Py_CLEAR (state -> SimpleQueueType );
330
+ Py_CLEAR (state -> EmptyError );
331
+ return 0 ;
332
+ }
333
+
334
+ static void
335
+ queue_free (void * m )
336
+ {
337
+ queue_clear ((PyObject * )m );
338
+ }
293
339
294
340
#include "clinic/_queuemodule.c.h"
295
341
@@ -306,48 +352,26 @@ static PyMethodDef simplequeue_methods[] = {
306
352
{NULL , NULL } /* sentinel */
307
353
};
308
354
355
+ static struct PyMemberDef simplequeue_members [] = {
356
+ {"__weaklistoffset__" , T_PYSSIZET , offsetof(simplequeueobject , weakreflist ), READONLY },
357
+ {NULL },
358
+ };
359
+
360
+ static PyType_Slot simplequeue_slots [] = {
361
+ {Py_tp_dealloc , simplequeue_dealloc },
362
+ {Py_tp_doc , (void * )simplequeue_new__doc__ },
363
+ {Py_tp_traverse , simplequeue_traverse },
364
+ {Py_tp_members , simplequeue_members },
365
+ {Py_tp_methods , simplequeue_methods },
366
+ {Py_tp_new , simplequeue_new },
367
+ {0 , NULL },
368
+ };
309
369
310
- static PyTypeObject PySimpleQueueType = {
311
- PyVarObject_HEAD_INIT (NULL , 0 )
312
- "_queue.SimpleQueue" , /*tp_name*/
313
- sizeof (simplequeueobject ), /*tp_basicsize*/
314
- 0 , /*tp_itemsize*/
315
- /* methods */
316
- (destructor )simplequeue_dealloc , /*tp_dealloc*/
317
- 0 , /*tp_vectorcall_offset*/
318
- 0 , /*tp_getattr*/
319
- 0 , /*tp_setattr*/
320
- 0 , /*tp_as_async*/
321
- 0 , /*tp_repr*/
322
- 0 , /*tp_as_number*/
323
- 0 , /*tp_as_sequence*/
324
- 0 , /*tp_as_mapping*/
325
- 0 , /*tp_hash*/
326
- 0 , /*tp_call*/
327
- 0 , /*tp_str*/
328
- 0 , /*tp_getattro*/
329
- 0 , /*tp_setattro*/
330
- 0 , /*tp_as_buffer*/
331
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
332
- | Py_TPFLAGS_HAVE_GC , /* tp_flags */
333
- simplequeue_new__doc__ , /*tp_doc*/
334
- (traverseproc )simplequeue_traverse , /*tp_traverse*/
335
- 0 , /*tp_clear*/
336
- 0 , /*tp_richcompare*/
337
- offsetof(simplequeueobject , weakreflist ), /*tp_weaklistoffset*/
338
- 0 , /*tp_iter*/
339
- 0 , /*tp_iternext*/
340
- simplequeue_methods , /*tp_methods*/
341
- 0 , /* tp_members */
342
- 0 , /* tp_getset */
343
- 0 , /* tp_base */
344
- 0 , /* tp_dict */
345
- 0 , /* tp_descr_get */
346
- 0 , /* tp_descr_set */
347
- 0 , /* tp_dictoffset */
348
- 0 , /* tp_init */
349
- 0 , /* tp_alloc */
350
- simplequeue_new /* tp_new */
370
+ static PyType_Spec simplequeue_spec = {
371
+ .name = "_queue.SimpleQueue" ,
372
+ .basicsize = sizeof (simplequeueobject ),
373
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
374
+ .slots = simplequeue_slots ,
351
375
};
352
376
353
377
@@ -358,42 +382,54 @@ PyDoc_STRVAR(queue_module_doc,
358
382
This module is an implementation detail, please do not use it directly." );
359
383
360
384
static struct PyModuleDef queuemodule = {
361
- PyModuleDef_HEAD_INIT ,
362
- "_queue" ,
363
- queue_module_doc ,
364
- -1 ,
365
- NULL ,
366
- NULL ,
367
- NULL ,
368
- NULL ,
369
- NULL
385
+ .m_base = PyModuleDef_HEAD_INIT ,
386
+ .m_name = "_queue" ,
387
+ .m_doc = queue_module_doc ,
388
+ .m_size = sizeof (simplequeue_state ),
389
+ .m_traverse = queue_traverse ,
390
+ .m_clear = queue_clear ,
391
+ .m_free = queue_free ,
370
392
};
371
393
372
394
373
395
PyMODINIT_FUNC
374
396
PyInit__queue (void )
375
397
{
376
398
PyObject * m ;
399
+ simplequeue_state * state ;
377
400
378
401
/* Create the module */
379
402
m = PyModule_Create (& queuemodule );
380
403
if (m == NULL )
381
404
return NULL ;
382
405
383
- EmptyError = PyErr_NewExceptionWithDoc (
406
+ state = simplequeue_get_state (m );
407
+ state -> EmptyError = PyErr_NewExceptionWithDoc (
384
408
"_queue.Empty" ,
385
409
"Exception raised by Queue.get(block=0)/get_nowait()." ,
386
410
NULL , NULL );
387
- if (EmptyError == NULL )
388
- return NULL ;
411
+ if (state -> EmptyError == NULL )
412
+ goto error ;
389
413
390
- Py_INCREF (EmptyError );
391
- if (PyModule_AddObject (m , "Empty" , EmptyError ) < 0 )
392
- return NULL ;
414
+ Py_INCREF (state -> EmptyError );
415
+ if (PyModule_AddObject (m , "Empty" , state -> EmptyError ) < 0 ) {
416
+ Py_DECREF (state -> EmptyError );
417
+ goto error ;
418
+ }
393
419
394
- if (PyModule_AddType (m , & PySimpleQueueType ) < 0 ) {
395
- return NULL ;
420
+ state -> SimpleQueueType = (PyTypeObject * )PyType_FromModuleAndSpec (m ,
421
+ & simplequeue_spec ,
422
+ NULL );
423
+ if (state -> SimpleQueueType == NULL ) {
424
+ goto error ;
425
+ }
426
+ if (PyModule_AddType (m , state -> SimpleQueueType ) < 0 ) {
427
+ goto error ;
396
428
}
397
429
398
430
return m ;
431
+
432
+ error :
433
+ Py_DECREF (m );
434
+ return NULL ;
399
435
}
0 commit comments