@@ -341,13 +341,45 @@ test_lock_benchmark(PyObject *module, PyObject *obj)
341341 Py_RETURN_NONE ;
342342}
343343
344+ static int
345+ init_maybe_fail (void * arg )
346+ {
347+ int * counter = (int * )arg ;
348+ (* counter )++ ;
349+ if (* counter < 5 ) {
350+ // failure
351+ return -1 ;
352+ }
353+ assert (* counter == 5 );
354+ return 0 ;
355+ }
356+
357+ static PyObject *
358+ test_lock_once (PyObject * self , PyObject * obj )
359+ {
360+ _PyOnceFlag once = {0 };
361+ int counter = 0 ;
362+ for (int i = 0 ; i < 10 ; i ++ ) {
363+ int res = _PyOnceFlag_CallOnce (& once , init_maybe_fail , & counter );
364+ if (i < 4 ) {
365+ assert (res == -1 );
366+ }
367+ else {
368+ assert (res == 0 );
369+ assert (counter == 5 );
370+ }
371+ }
372+ Py_RETURN_NONE ;
373+ }
374+
344375static PyMethodDef test_methods [] = {
345376 {"test_lock_basic" , test_lock_basic , METH_NOARGS },
346377 {"test_lock_two_threads" , test_lock_two_threads , METH_NOARGS },
347378 {"test_lock_counter" , test_lock_counter , METH_NOARGS },
348379 {"test_lock_counter_slow" , test_lock_counter_slow , METH_NOARGS },
349380 _TESTINTERNALCAPI_BENCHMARK_LOCKS_METHODDEF
350381 {"test_lock_benchmark" , test_lock_benchmark , METH_NOARGS },
382+ {"test_lock_once" , test_lock_once , METH_NOARGS },
351383 {NULL , NULL } /* sentinel */
352384};
353385
0 commit comments