11#include "Python.h"
2+ #include "structmember.h" // PyMemberDef
23#include <stddef.h> // offsetof()
34
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 ;
139
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)))
1420
1521typedef struct {
1622 PyObject_HEAD
@@ -21,10 +27,17 @@ typedef struct {
2127 PyObject * weakreflist ;
2228} simplequeueobject ;
2329
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]*/
2435
2536static void
2637simplequeue_dealloc (simplequeueobject * self )
2738{
39+ PyTypeObject * tp = Py_TYPE (self );
40+
2841 PyObject_GC_UnTrack (self );
2942 if (self -> lock != NULL ) {
3043 /* Unlock the lock so it's safe to free it */
@@ -36,6 +49,7 @@ simplequeue_dealloc(simplequeueobject *self)
3649 if (self -> weakreflist != NULL )
3750 PyObject_ClearWeakRefs ((PyObject * ) self );
3851 Py_TYPE (self )-> tp_free (self );
52+ Py_DECREF (tp );
3953}
4054
4155static int
@@ -155,6 +169,9 @@ simplequeue_pop_item(simplequeueobject *self)
155169
156170/*[clinic input]
157171_queue.SimpleQueue.get
172+
173+ cls: defining_class
174+ /
158175 block: bool = True
159176 timeout: object = None
160177
@@ -171,9 +188,9 @@ in that case).
171188[clinic start generated code]*/
172189
173190static 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 ]*/
177194{
178195 _PyTime_t endtime = 0 ;
179196 _PyTime_t timeout_val ;
@@ -225,8 +242,10 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block,
225242 return NULL ;
226243 }
227244 if (r == PY_LOCK_FAILURE ) {
245+ PyObject * module = PyType_GetModule (cls );
246+ simplequeue_state * state = simplequeue_get_state (module );
228247 /* Timed out */
229- PyErr_SetNone (EmptyError );
248+ PyErr_SetNone (state -> EmptyError );
230249 return NULL ;
231250 }
232251 self -> locked = 1 ;
@@ -251,17 +270,21 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block,
251270/*[clinic input]
252271_queue.SimpleQueue.get_nowait
253272
273+ cls: defining_class
274+ /
275+
254276Remove and return an item from the queue without blocking.
255277
256278Only get an item if one is immediately available. Otherwise
257279raise the Empty exception.
258280[clinic start generated code]*/
259281
260282static 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]*/
263286{
264- return _queue_SimpleQueue_get_impl (self , 0 , Py_None );
287+ return _queue_SimpleQueue_get_impl (self , cls , 0 , Py_None );
265288}
266289
267290/*[clinic input]
@@ -290,6 +313,29 @@ _queue_SimpleQueue_qsize_impl(simplequeueobject *self)
290313 return PyList_GET_SIZE (self -> lst ) - self -> lst_pos ;
291314}
292315
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+ }
293339
294340#include "clinic/_queuemodule.c.h"
295341
@@ -306,48 +352,26 @@ static PyMethodDef simplequeue_methods[] = {
306352 {NULL , NULL } /* sentinel */
307353};
308354
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+ };
309369
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 ,
351375};
352376
353377
@@ -358,42 +382,54 @@ PyDoc_STRVAR(queue_module_doc,
358382This module is an implementation detail, please do not use it directly." );
359383
360384static 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 ,
370392};
371393
372394
373395PyMODINIT_FUNC
374396PyInit__queue (void )
375397{
376398 PyObject * m ;
399+ simplequeue_state * state ;
377400
378401 /* Create the module */
379402 m = PyModule_Create (& queuemodule );
380403 if (m == NULL )
381404 return NULL ;
382405
383- EmptyError = PyErr_NewExceptionWithDoc (
406+ state = simplequeue_get_state (m );
407+ state -> EmptyError = PyErr_NewExceptionWithDoc (
384408 "_queue.Empty" ,
385409 "Exception raised by Queue.get(block=0)/get_nowait()." ,
386410 NULL , NULL );
387- if (EmptyError == NULL )
388- return NULL ;
411+ if (state -> EmptyError == NULL )
412+ goto error ;
389413
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+ }
393419
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 ;
396428 }
397429
398430 return m ;
431+
432+ error :
433+ Py_DECREF (m );
434+ return NULL ;
399435}
0 commit comments