22
33#include "Python.h"
44#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
5+ #include "pycore_moduleobject.h" // _PyModule_GetState()
56#include "pycore_namespace.h" // _PyNamespace_New()
67
78#include <ctype.h>
6465static int pysleep (_PyTime_t timeout );
6566
6667
68+ typedef struct {
69+ PyTypeObject * struct_time_type ;
70+ } time_module_state ;
71+
72+ static inline time_module_state *
73+ get_time_state (PyObject * module )
74+ {
75+ void * state = _PyModule_GetState (module );
76+ assert (state != NULL );
77+ return (time_module_state * )state ;
78+ }
79+
80+
6781static PyObject *
6882_PyFloat_FromPyTime (_PyTime_t t )
6983{
@@ -405,9 +419,6 @@ static PyStructSequence_Desc struct_time_type_desc = {
405419 9 ,
406420};
407421
408- static int initialized ;
409- static PyTypeObject StructTimeType ;
410-
411422#if defined(MS_WINDOWS )
412423#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
413424 #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
@@ -417,13 +428,13 @@ static DWORD timer_flags = (DWORD)-1;
417428#endif
418429
419430static PyObject *
420- tmtotuple (struct tm * p
431+ tmtotuple (time_module_state * state , struct tm * p
421432#ifndef HAVE_STRUCT_TM_TM_ZONE
422433 , const char * zone , time_t gmtoff
423434#endif
424435)
425436{
426- PyObject * v = PyStructSequence_New (& StructTimeType );
437+ PyObject * v = PyStructSequence_New (state -> struct_time_type );
427438 if (v == NULL )
428439 return NULL ;
429440
@@ -480,7 +491,7 @@ parse_time_t_args(PyObject *args, const char *format, time_t *pwhen)
480491}
481492
482493static PyObject *
483- time_gmtime (PyObject * self , PyObject * args )
494+ time_gmtime (PyObject * module , PyObject * args )
484495{
485496 time_t when ;
486497 struct tm buf ;
@@ -491,10 +502,12 @@ time_gmtime(PyObject *self, PyObject *args)
491502 errno = 0 ;
492503 if (_PyTime_gmtime (when , & buf ) != 0 )
493504 return NULL ;
505+
506+ time_module_state * state = get_time_state (module );
494507#ifdef HAVE_STRUCT_TM_TM_ZONE
495- return tmtotuple (& buf );
508+ return tmtotuple (state , & buf );
496509#else
497- return tmtotuple (& buf , "UTC" , 0 );
510+ return tmtotuple (state , & buf , "UTC" , 0 );
498511#endif
499512}
500513
@@ -522,7 +535,7 @@ If the platform supports the tm_gmtoff and tm_zone, they are available as\n\
522535attributes only." );
523536
524537static PyObject *
525- time_localtime (PyObject * self , PyObject * args )
538+ time_localtime (PyObject * module , PyObject * args )
526539{
527540 time_t when ;
528541 struct tm buf ;
@@ -531,16 +544,18 @@ time_localtime(PyObject *self, PyObject *args)
531544 return NULL ;
532545 if (_PyTime_localtime (when , & buf ) != 0 )
533546 return NULL ;
547+
548+ time_module_state * state = get_time_state (module );
534549#ifdef HAVE_STRUCT_TM_TM_ZONE
535- return tmtotuple (& buf );
550+ return tmtotuple (state , & buf );
536551#else
537552 {
538553 struct tm local = buf ;
539554 char zone [100 ];
540555 time_t gmtoff ;
541556 strftime (zone , sizeof (zone ), "%Z" , & buf );
542557 gmtoff = timegm (& buf ) - when ;
543- return tmtotuple (& local , zone , gmtoff );
558+ return tmtotuple (state , & local , zone , gmtoff );
544559 }
545560#endif
546561}
@@ -560,7 +575,8 @@ When 'seconds' is not passed in, convert the current time instead.");
560575 * an exception and return 0 on error.
561576 */
562577static int
563- gettmarg (PyObject * args , struct tm * p , const char * format )
578+ gettmarg (time_module_state * state , PyObject * args ,
579+ struct tm * p , const char * format )
564580{
565581 int y ;
566582
@@ -588,7 +604,7 @@ gettmarg(PyObject *args, struct tm *p, const char *format)
588604 p -> tm_wday = (p -> tm_wday + 1 ) % 7 ;
589605 p -> tm_yday -- ;
590606#ifdef HAVE_STRUCT_TM_TM_ZONE
591- if (Py_IS_TYPE (args , & StructTimeType )) {
607+ if (Py_IS_TYPE (args , state -> struct_time_type )) {
592608 PyObject * item ;
593609 item = PyStructSequence_GET_ITEM (args , 9 );
594610 if (item != Py_None ) {
@@ -729,7 +745,7 @@ the C library strftime function.\n"
729745#endif
730746
731747static PyObject *
732- time_strftime (PyObject * self , PyObject * args )
748+ time_strftime (PyObject * module , PyObject * args )
733749{
734750 PyObject * tup = NULL ;
735751 struct tm buf ;
@@ -753,12 +769,13 @@ time_strftime(PyObject *self, PyObject *args)
753769 if (!PyArg_ParseTuple (args , "U|O:strftime" , & format_arg , & tup ))
754770 return NULL ;
755771
772+ time_module_state * state = get_time_state (module );
756773 if (tup == NULL ) {
757774 time_t tt = time (NULL );
758775 if (_PyTime_localtime (tt , & buf ) != 0 )
759776 return NULL ;
760777 }
761- else if (!gettmarg (tup , & buf ,
778+ else if (!gettmarg (state , tup , & buf ,
762779 "iiiiiiiii;strftime(): illegal time tuple argument" ) ||
763780 !checktm (& buf ))
764781 {
@@ -941,19 +958,21 @@ _asctime(struct tm *timeptr)
941958}
942959
943960static PyObject *
944- time_asctime (PyObject * self , PyObject * args )
961+ time_asctime (PyObject * module , PyObject * args )
945962{
946963 PyObject * tup = NULL ;
947964 struct tm buf ;
948965
949966 if (!PyArg_UnpackTuple (args , "asctime" , 0 , 1 , & tup ))
950967 return NULL ;
968+
969+ time_module_state * state = get_time_state (module );
951970 if (tup == NULL ) {
952971 time_t tt = time (NULL );
953972 if (_PyTime_localtime (tt , & buf ) != 0 )
954973 return NULL ;
955974 }
956- else if (!gettmarg (tup , & buf ,
975+ else if (!gettmarg (state , tup , & buf ,
957976 "iiiiiiiii;asctime(): illegal time tuple argument" ) ||
958977 !checktm (& buf ))
959978 {
@@ -990,12 +1009,13 @@ not present, current time as returned by localtime() is used.");
9901009
9911010#ifdef HAVE_MKTIME
9921011static PyObject *
993- time_mktime (PyObject * self , PyObject * tm_tuple )
1012+ time_mktime (PyObject * module , PyObject * tm_tuple )
9941013{
9951014 struct tm tm ;
9961015 time_t tt ;
9971016
998- if (!gettmarg (tm_tuple , & tm ,
1017+ time_module_state * state = get_time_state (module );
1018+ if (!gettmarg (state , tm_tuple , & tm ,
9991019 "iiiiiiiii;mktime(): illegal time tuple argument" ))
10001020 {
10011021 return NULL ;
@@ -1888,6 +1908,7 @@ if it is -1, mktime() should guess based on the date and time.\n");
18881908static int
18891909time_exec (PyObject * module )
18901910{
1911+ time_module_state * state = get_time_state (module );
18911912#if defined(__APPLE__ ) && defined(HAVE_CLOCK_GETTIME )
18921913 if (HAVE_CLOCK_GETTIME_RUNTIME ) {
18931914 /* pass: ^^^ cannot use '!' here */
@@ -2001,21 +2022,18 @@ time_exec(PyObject *module)
20012022
20022023#endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
20032024
2004- if (!initialized ) {
2005- if (PyStructSequence_InitType2 (& StructTimeType ,
2006- & struct_time_type_desc ) < 0 ) {
2007- return -1 ;
2008- }
2009- }
20102025 if (PyModule_AddIntConstant (module , "_STRUCT_TM_ITEMS" , 11 )) {
20112026 return -1 ;
20122027 }
2013- Py_INCREF (& StructTimeType );
2014- if (PyModule_AddObject (module , "struct_time" , (PyObject * ) & StructTimeType )) {
2015- Py_DECREF (& StructTimeType );
2028+
2029+ // struct_time type
2030+ state -> struct_time_type = PyStructSequence_NewType (& struct_time_type_desc );
2031+ if (state -> struct_time_type == NULL ) {
2032+ return -1 ;
2033+ }
2034+ if (PyModule_AddType (module , state -> struct_time_type )) {
20162035 return -1 ;
20172036 }
2018- initialized = 1 ;
20192037
20202038#if defined(__linux__ ) && !defined(__GLIBC__ )
20212039 struct tm tm ;
@@ -2044,21 +2062,47 @@ time_exec(PyObject *module)
20442062 return 0 ;
20452063}
20462064
2065+
2066+ static int
2067+ time_module_traverse (PyObject * module , visitproc visit , void * arg )
2068+ {
2069+ time_module_state * state = get_time_state (module );
2070+ Py_VISIT (state -> struct_time_type );
2071+ return 0 ;
2072+ }
2073+
2074+
2075+ static int
2076+ time_module_clear (PyObject * module )
2077+ {
2078+ time_module_state * state = get_time_state (module );
2079+ Py_CLEAR (state -> struct_time_type );
2080+ return 0 ;
2081+ }
2082+
2083+
2084+ static void
2085+ time_module_free (void * module )
2086+ {
2087+ time_module_clear ((PyObject * )module );
2088+ }
2089+
2090+
20472091static struct PyModuleDef_Slot time_slots [] = {
20482092 {Py_mod_exec , time_exec },
20492093 {0 , NULL }
20502094};
20512095
20522096static struct PyModuleDef timemodule = {
20532097 PyModuleDef_HEAD_INIT ,
2054- "time" ,
2055- module_doc ,
2056- 0 ,
2057- time_methods ,
2058- time_slots ,
2059- NULL ,
2060- NULL ,
2061- NULL
2098+ . m_name = "time" ,
2099+ . m_doc = module_doc ,
2100+ . m_size = sizeof ( time_module_state ) ,
2101+ . m_methods = time_methods ,
2102+ . m_slots = time_slots ,
2103+ . m_traverse = time_module_traverse ,
2104+ . m_clear = time_module_clear ,
2105+ . m_free = time_module_free ,
20622106};
20632107
20642108PyMODINIT_FUNC
0 commit comments