Tcl Source Code

Check-in [a2b3bcbdc7]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:free tz.was (in exit handler)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dgp-bug-167e0635db
Files: files | file ages | folders
SHA3-256: a2b3bcbdc7957b0470cbd40dbac2f378a3c087046efee999b03996166bdccf4b
User & Date: sebres 2024-04-14 14:41:35
Context
2024-04-15
13:21
clean clock mutex Closed-Leaf check-in: 2484b0ade8 user: sebres tags: dgp-bug-167e0635db
2024-04-14
14:41
free tz.was (in exit handler) check-in: a2b3bcbdc7 user: sebres tags: dgp-bug-167e0635db
13:47
merge trunk (bug-fix for tclHash with mistaken direct compare) check-in: 98994dc843 user: sebres tags: dgp-bug-167e0635db
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclClock.c.

111
112
113
114
115
116
117

118
119
120
121
122
123
124
static Tcl_ObjCmdProc	ClockAddObjCmd;
static int		ClockValidDate(DateInfo *,
			    ClockFmtScnCmdArgs *, int stage);
static struct tm *	ThreadSafeLocalTime(const time_t *);
static size_t		TzsetIfNecessary(void);
static void		ClockDeleteCmdProc(void *);
static Tcl_ObjCmdProc	ClockSafeCatchCmd;

/*
 * Structure containing description of "native" clock commands to create.
 */

struct ClockCommand {
    const char *name;		/* The tail of the command name. The full name
				 * is "::tcl::clock::<name>". When NULL marks







>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
static Tcl_ObjCmdProc	ClockAddObjCmd;
static int		ClockValidDate(DateInfo *,
			    ClockFmtScnCmdArgs *, int stage);
static struct tm *	ThreadSafeLocalTime(const time_t *);
static size_t		TzsetIfNecessary(void);
static void		ClockDeleteCmdProc(void *);
static Tcl_ObjCmdProc	ClockSafeCatchCmd;
static void		ClockFinalize(void *);
/*
 * Structure containing description of "native" clock commands to create.
 */

struct ClockCommand {
    const char *name;		/* The tail of the command name. The full name
				 * is "::tcl::clock::<name>". When NULL marks
175
176
177
178
179
180
181









182
183
184
185
186
187
188
    const struct ClockCommand *clockCmdPtr;
    char cmdName[50];		/* Buffer large enough to hold the string
				 *::tcl::clock::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */
    Command *cmdPtr;
    ClockClientData *data;
    int i;










    /*
     * Safe interps get [::clock] as alias to a parent, so do not need their
     * own copies of the support routines.
     */

    if (Tcl_IsSafe(interp)) {







>
>
>
>
>
>
>
>
>







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    const struct ClockCommand *clockCmdPtr;
    char cmdName[50];		/* Buffer large enough to hold the string
				 *::tcl::clock::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */
    Command *cmdPtr;
    ClockClientData *data;
    int i;

    static int initialized = 0;	/* global clock engine initialized (in process) */
    /*
     * Register handler to finalize clock on exit.
     */
    if (!initialized) {
	Tcl_CreateExitHandler(ClockFinalize, NULL);
	initialized = 1;
    }

    /*
     * Safe interps get [::clock] as alias to a parent, so do not need their
     * own copies of the support routines.
     */

    if (Tcl_IsSafe(interp)) {
4635
4636
4637
4638
4639
4640
4641












4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
#else
#define WCHAR char
#define wcslen strlen
#define wcscmp strcmp
#define wcscpy strcpy
#endif
#define TZ_INIT_MARKER	((WCHAR *) INT2PTR(-1))













static size_t
TzsetIfNecessary(void)
{
    typedef struct ClockTzStatic {
	WCHAR *was;		/* Previous value of TZ. */
	long long lastRefresh;	/* Used for latency before next refresh. */
	size_t epoch;		/* Epoch, signals that TZ changed. */
	size_t envEpoch;	/* Last env epoch, for faster signaling,
				 * that TZ changed via TCL */
    } ClockTzStatic;
    static ClockTzStatic tz = {	/* Global timezone info; protected by
				 * clockMutex.*/
	TZ_INIT_MARKER, 0, 0, 0
    };
    const WCHAR *tzNow;		/* Current value of TZ. */
    Tcl_Time now;		/* Current time. */
    size_t epoch;		/* The tz.epoch that the TZ was read at. */

    /*
     * Prevent performance regression on some platforms by resolving of system time zone:
     * small latency for check whether environment was changed (once per second)







>
>
>
>
>
>
>
>
>
>
>
>




<
<
<
<
<
<
<
<
<
<
<







4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667











4668
4669
4670
4671
4672
4673
4674
#else
#define WCHAR char
#define wcslen strlen
#define wcscmp strcmp
#define wcscpy strcpy
#endif
#define TZ_INIT_MARKER	((WCHAR *) INT2PTR(-1))

typedef struct ClockTzStatic {
    WCHAR *was;			/* Previous value of TZ. */
    long long lastRefresh;	/* Used for latency before next refresh. */
    size_t epoch;		/* Epoch, signals that TZ changed. */
    size_t envEpoch;		/* Last env epoch, for faster signaling,
				 * that TZ changed via TCL */
} ClockTzStatic;
static ClockTzStatic tz = {	/* Global timezone info; protected by
				 * clockMutex.*/
    TZ_INIT_MARKER, 0, 0, 0
};

static size_t
TzsetIfNecessary(void)
{











    const WCHAR *tzNow;		/* Current value of TZ. */
    Tcl_Time now;		/* Current time. */
    size_t epoch;		/* The tz.epoch that the TZ was read at. */

    /*
     * Prevent performance regression on some platforms by resolving of system time zone:
     * small latency for check whether environment was changed (once per second)
4697
4698
4699
4700
4701
4702
4703











4704
4705
4706
4707
4708
4709
4710
4711
    } else {
	epoch = tz.epoch;
    }
    Tcl_MutexUnlock(&clockMutex);

    return epoch;
}












/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>








4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
    } else {
	epoch = tz.epoch;
    }
    Tcl_MutexUnlock(&clockMutex);

    return epoch;
}

static void
ClockFinalize(
    TCL_UNUSED(void *))
{
    ClockFrmScnFinalize();

    if (tz.was && tz.was != TZ_INIT_MARKER) {
	Tcl_Free(tz.was);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclClockFmt.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static void		ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr);
static int		ClockFmtObj_SetFromAny(Tcl_Interp *, Tcl_Obj *objPtr);
static void		ClockFmtObj_UpdateString(Tcl_Obj *objPtr);

TCL_DECLARE_MUTEX(ClockFmtMutex);	/* Serializes access to common format list. */

static void		ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);
static void		ClockFrmScnFinalize(void *);

/*
 * Derivation of tclStringHashKeyType with another allocEntryProc
 */

static Tcl_HashKeyType ClockFmtScnStorageHashKeyType;








<







22
23
24
25
26
27
28

29
30
31
32
33
34
35
static void		ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr);
static int		ClockFmtObj_SetFromAny(Tcl_Interp *, Tcl_Obj *objPtr);
static void		ClockFmtObj_UpdateString(Tcl_Obj *objPtr);

TCL_DECLARE_MUTEX(ClockFmtMutex);	/* Serializes access to common format list. */

static void		ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);


/*
 * Derivation of tclStringHashKeyType with another allocEntryProc
 */

static Tcl_HashKeyType ClockFmtScnStorageHashKeyType;

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
	ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;

	/* initialize hash table */
	Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
		&ClockFmtScnStorageHashKeyType);

	initialized = 1;
	Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
    }

    /* get or create entry (and alocate storage) */
    hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
    if (hPtr != NULL) {
	fss = FmtScn4HashEntry(hPtr);








<







827
828
829
830
831
832
833

834
835
836
837
838
839
840
	ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;

	/* initialize hash table */
	Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
		&ClockFmtScnStorageHashKeyType);

	initialized = 1;

    }

    /* get or create entry (and alocate storage) */
    hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
    if (hPtr != NULL) {
	fss = FmtScn4HashEntry(hPtr);

3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547



3548
3549
3550
3551
3552
3553
3554
ClockFrmScnClearCaches(void)
{
    Tcl_MutexLock(&ClockFmtMutex);
    /* clear caches ... */
    Tcl_MutexUnlock(&ClockFmtMutex);
}

static void
ClockFrmScnFinalize(
    TCL_UNUSED(void *))
{



    Tcl_MutexLock(&ClockFmtMutex);
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
    /* clear GC */
    ClockFmtScnStorage_GC.stackPtr = NULL;
    ClockFmtScnStorage_GC.stackBound = NULL;
    ClockFmtScnStorage_GC.count = 0;
#endif







|
|
<

>
>
>







3535
3536
3537
3538
3539
3540
3541
3542
3543

3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
ClockFrmScnClearCaches(void)
{
    Tcl_MutexLock(&ClockFmtMutex);
    /* clear caches ... */
    Tcl_MutexUnlock(&ClockFmtMutex);
}

void
ClockFrmScnFinalize()

{
    if (!initialized) {
	return;
    }
    Tcl_MutexLock(&ClockFmtMutex);
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
    /* clear GC */
    ClockFmtScnStorage_GC.stackPtr = NULL;
    ClockFmtScnStorage_GC.stackBound = NULL;
    ClockFmtScnStorage_GC.count = 0;
#endif

Changes to generic/tclDate.h.

556
557
558
559
560
561
562

563
564
			    Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Obj *	ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockScan(DateInfo *info, Tcl_Obj *strObj,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockFormat(DateFormat *dateFmt,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE void	ClockFrmScnClearCaches(void);


#endif /* _TCLCLOCK_H */







>


556
557
558
559
560
561
562
563
564
565
			    Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Obj *	ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockScan(DateInfo *info, Tcl_Obj *strObj,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockFormat(DateFormat *dateFmt,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE void	ClockFrmScnClearCaches(void);
MODULE_SCOPE void	ClockFrmScnFinalize();

#endif /* _TCLCLOCK_H */