@@ -46,7 +46,11 @@ typedef enum {
46
46
so that these and bitfields from TaskObj are contiguous.
47
47
*/ \
48
48
unsigned prefix ##_log_tb : 1 ; \
49
- unsigned prefix ##_blocking : 1 ;
49
+ unsigned prefix ##_blocking : 1 ; \
50
+ /* Used by profilers to make traversing the stack from an external \
51
+ process faster. */ \
52
+ unsigned prefix ##_is_task : 1 ; \
53
+ unsigned prefix ##_awaited_by_is_set : 1 ;
50
54
51
55
typedef struct {
52
56
FutureObj_HEAD (fut )
@@ -513,6 +517,8 @@ future_init(FutureObj *fut, PyObject *loop)
513
517
fut -> fut_state = STATE_PENDING ;
514
518
fut -> fut_log_tb = 0 ;
515
519
fut -> fut_blocking = 0 ;
520
+ fut -> fut_awaited_by_is_set = 0 ;
521
+ fut -> fut_is_task = 0 ;
516
522
517
523
if (loop == Py_None ) {
518
524
asyncio_state * state = get_asyncio_state_by_def ((PyObject * )fut );
@@ -568,12 +574,14 @@ future_awaited_by_add(asyncio_state *state, PyObject *fut, PyObject *thing)
568
574
to avoid always creating a set for `fut_awaited_by`.
569
575
*/
570
576
if (_fut -> fut_awaited_by == NULL ) {
577
+ assert (!_fut -> fut_awaited_by_is_set );
571
578
Py_INCREF (thing );
572
579
_fut -> fut_awaited_by = thing ;
573
580
return 0 ;
574
581
}
575
582
576
- if (PySet_Check (_fut -> fut_awaited_by )) {
583
+ if (_fut -> fut_awaited_by_is_set ) {
584
+ assert (PySet_Check (_fut -> fut_awaited_by ));
577
585
return PySet_Add (_fut -> fut_awaited_by , thing );
578
586
}
579
587
@@ -590,6 +598,7 @@ future_awaited_by_add(asyncio_state *state, PyObject *fut, PyObject *thing)
590
598
return -1 ;
591
599
}
592
600
Py_SETREF (_fut -> fut_awaited_by , set );
601
+ _fut -> fut_awaited_by_is_set = 1 ;
593
602
return 0 ;
594
603
}
595
604
@@ -615,7 +624,8 @@ future_awaited_by_discard(asyncio_state *state, PyObject *fut, PyObject *thing)
615
624
Py_CLEAR (_fut -> fut_awaited_by );
616
625
return 0 ;
617
626
}
618
- if (PySet_Check (_fut -> fut_awaited_by )) {
627
+ if (_fut -> fut_awaited_by_is_set ) {
628
+ assert (PySet_Check (_fut -> fut_awaited_by ));
619
629
int err = PySet_Discard (_fut -> fut_awaited_by , thing );
620
630
if (err < 0 && PyErr_Occurred ()) {
621
631
return -1 ;
@@ -633,7 +643,9 @@ future_get_awaited_by(FutureObj *fut)
633
643
if (fut -> fut_awaited_by == NULL ) {
634
644
Py_RETURN_NONE ;
635
645
}
636
- if (PySet_Check (fut -> fut_awaited_by )) {
646
+ if (fut -> fut_awaited_by_is_set ) {
647
+ /* Already a set, just wrap it into a frozen set and return. */
648
+ assert (PySet_Check (fut -> fut_awaited_by ));
637
649
return PyFrozenSet_New (fut -> fut_awaited_by );
638
650
}
639
651
@@ -935,6 +947,7 @@ FutureObj_clear(FutureObj *fut)
935
947
Py_CLEAR (fut -> fut_cancel_msg );
936
948
Py_CLEAR (fut -> fut_cancelled_exc );
937
949
Py_CLEAR (fut -> fut_awaited_by );
950
+ fut -> fut_awaited_by_is_set = 0 ;
938
951
PyObject_ClearManagedDict ((PyObject * )fut );
939
952
return 0 ;
940
953
}
@@ -2229,6 +2242,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2229
2242
if (future_init ((FutureObj * )self , loop )) {
2230
2243
return -1 ;
2231
2244
}
2245
+ self -> task_is_task = 1 ;
2232
2246
2233
2247
asyncio_state * state = get_asyncio_state_by_def ((PyObject * )self );
2234
2248
int is_coro = is_coroutine (state , coro );
0 commit comments