Use thread-safe functions where possible.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36418 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Neis
2005-12-17 22:01:43 +00:00
parent 120edd5dbd
commit a452689b23
3 changed files with 69 additions and 24 deletions

View File

@@ -547,10 +547,21 @@ Returns the current time.
\membersection{wxDateTime::GetTmNow}\label{wxdatetimegettmnow} \membersection{wxDateTime::GetTmNow}\label{wxdatetimegettmnow}
\func{static struct tm *}{GetTmNow}{\param{struct tm *}{tm}}
Returns the current time broken down, uses the buffer whose adress is
passed to the function via {\it tm} to store the result.
\membersection{wxDateTime::GetTmNow}
\func{static struct tm *}{GetTmNow}{\void} \func{static struct tm *}{GetTmNow}{\void}
Returns the current time broken down. Returns the current time broken down. Note that this function returns a
pointer to a static buffer that's reused by calls to this function and
certain C library functions (e.g. localtime). If there is any chance your
code might be used in a multi-threaded application, you really should use
the flavour of function \helpref{wxDateTime::GetTmNow}{wxdatetimegettmnow}
taking a parameter.
\membersection{wxDateTime::GetWeekDayName}\label{wxdatetimegetweekdayname} \membersection{wxDateTime::GetWeekDayName}\label{wxdatetimegetweekdayname}

View File

@@ -52,6 +52,21 @@ class WXDLLIMPEXP_BASE wxDateSpan;
* 5. wxDateTimeHolidayAuthority for Easter and other christian feasts * 5. wxDateTimeHolidayAuthority for Easter and other christian feasts
*/ */
/* Two wrapper functions for thread safety */
#ifdef HAVE_LOCALTIME_R
#define wxLocaltime_r localtime_r
#else
struct tm *wxLocaltime_r(const time_t*, struct tm*)
#warning using pseudo thread-safe wrapper for localtime to emulate localtime_r
#endif
#ifdef HAVE_GMTIME_R
#define wxGmtime_r gmtime_r
#else
struct tm *wxGmtime_r(const time_t*, struct tm*)
#warning using pseudo thread-safe wrapper for gmtime to emulate gmtime_r
#endif
/* /*
The three (main) classes declared in this header represent: The three (main) classes declared in this header represent:
@@ -1055,6 +1070,9 @@ public:
return localtime(&t); return localtime(&t);
} }
// get current time using thread-safe function
static struct tm *GetTmNow(struct tm *tmstruct);
private: private:
// the current country - as it's the same for all program objects (unless // the current country - as it's the same for all program objects (unless
// it runs on a _really_ big cluster system :-), this is a static member: // it runs on a _really_ big cluster system :-), this is a static member:
@@ -1537,7 +1555,8 @@ inline bool wxDateTime::IsInStdRange() const
/* static */ /* static */
inline wxDateTime wxDateTime::Now() inline wxDateTime wxDateTime::Now()
{ {
return wxDateTime(*GetTmNow()); struct tm tmstruct;
return wxDateTime(*GetTmNow(&tmstruct));
} }
/* static */ /* static */

View File

@@ -307,15 +307,16 @@ static int GetTimeZone()
static bool s_timezoneSet = false; static bool s_timezoneSet = false;
static long gmtoffset = LONG_MAX; // invalid timezone static long gmtoffset = LONG_MAX; // invalid timezone
// ensure that the timezone variable is set by calling localtime // ensure that the timezone variable is set by calling wxLocaltime_r
if ( !s_timezoneSet ) if ( !s_timezoneSet )
{ {
// just call localtime() instead of figuring out whether this system // just call wxLocaltime_r() instead of figuring out whether this
// supports tzset(), _tzset() or something else // system supports tzset(), _tzset() or something else
time_t t = 0; time_t t = 0;
struct tm *tm; struct tm *tm;
struct tm tmstruct;
tm = localtime(&t); tm = wxLocaltime_r(&t, &tmstruct);
s_timezoneSet = true; s_timezoneSet = true;
// note that GMT offset is the opposite of time zone and so to return // note that GMT offset is the opposite of time zone and so to return
@@ -430,10 +431,11 @@ static void ReplaceDefaultYearMonthWithCurrent(int *year,
wxDateTime::Month *month) wxDateTime::Month *month)
{ {
struct tm *tmNow = NULL; struct tm *tmNow = NULL;
struct tm tmstruct;
if ( *year == wxDateTime::Inv_Year ) if ( *year == wxDateTime::Inv_Year )
{ {
tmNow = wxDateTime::GetTmNow(); tmNow = wxDateTime::GetTmNow(&tmstruct);
*year = 1900 + tmNow->tm_year; *year = 1900 + tmNow->tm_year;
} }
@@ -441,7 +443,7 @@ static void ReplaceDefaultYearMonthWithCurrent(int *year,
if ( *month == wxDateTime::Inv_Month ) if ( *month == wxDateTime::Inv_Month )
{ {
if ( !tmNow ) if ( !tmNow )
tmNow = wxDateTime::GetTmNow(); tmNow = wxDateTime::GetTmNow(&tmstruct);
*month = (wxDateTime::Month)tmNow->tm_mon; *month = (wxDateTime::Month)tmNow->tm_mon;
} }
@@ -522,6 +524,13 @@ static wxDateTime::WeekDay GetWeekDayFromName(const wxString& name, int flags)
return wd; return wd;
} }
/* static */
struct tm *wxDateTime::GetTmNow(struct tm *tmstruct)
{
time_t t = GetTimeNow();
return wxLocaltime_r(&t, tmstruct);
}
// scans all digits (but no more than len) and returns the resulting number // scans all digits (but no more than len) and returns the resulting number
static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number) static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number)
{ {
@@ -988,7 +997,8 @@ wxDateTime::Country wxDateTime::GetCountry()
{ {
// try to guess from the time zone name // try to guess from the time zone name
time_t t = time(NULL); time_t t = time(NULL);
struct tm *tm = localtime(&t); struct tm tmstruct;
struct tm *tm = wxLocaltime_r(&t, &tmstruct);
wxString tz = CallStrftime(_T("%Z"), tm); wxString tz = CallStrftime(_T("%Z"), tm);
if ( tz == _T("WET") || tz == _T("WEST") ) if ( tz == _T("WET") || tz == _T("WEST") )
@@ -1311,9 +1321,10 @@ wxDateTime& wxDateTime::Set(wxDateTime_t hour,
_T("Invalid time in wxDateTime::Set()") ); _T("Invalid time in wxDateTime::Set()") );
// get the current date from system // get the current date from system
struct tm *tm = GetTmNow(); struct tm tmstruct;
struct tm *tm = GetTmNow(&tmstruct);
wxDATETIME_CHECK( tm, _T("localtime() failed") ); wxDATETIME_CHECK( tm, _T("wxLocaltime_r() failed") );
// make a copy so it isn't clobbered by the call to mktime() below // make a copy so it isn't clobbered by the call to mktime() below
struct tm tm1(*tm); struct tm tm1(*tm);
@@ -1479,7 +1490,8 @@ unsigned long wxDateTime::GetAsDOS() const
{ {
unsigned long ddt; unsigned long ddt;
time_t ticks = GetTicks(); time_t ticks = GetTicks();
struct tm *tm = localtime(&ticks); struct tm tmstruct;
struct tm *tm = wxLocaltime_r(&ticks, &tmstruct);
long year = tm->tm_year; long year = tm->tm_year;
year -= 80; year -= 80;
@@ -1517,14 +1529,15 @@ wxDateTime::Tm wxDateTime::GetTm(const TimeZone& tz) const
if ( time != (time_t)-1 ) if ( time != (time_t)-1 )
{ {
// use C RTL functions // use C RTL functions
struct tm tmstruct;
tm *tm; tm *tm;
if ( tz.GetOffset() == -GetTimeZone() ) if ( tz.GetOffset() == -GetTimeZone() )
{ {
// we are working with local time // we are working with local time
tm = localtime(&time); tm = wxLocaltime_r(&time, &tmstruct);
// should never happen // should never happen
wxCHECK_MSG( tm, Tm(), _T("localtime() failed") ); wxCHECK_MSG( tm, Tm(), _T("wxLocaltime_r() failed") );
} }
else else
{ {
@@ -1536,10 +1549,10 @@ wxDateTime::Tm wxDateTime::GetTm(const TimeZone& tz) const
if ( time >= 0 ) if ( time >= 0 )
#endif #endif
{ {
tm = gmtime(&time); tm = wxGmtime_r(&time, &tmstruct);
// should never happen // should never happen
wxCHECK_MSG( tm, Tm(), _T("gmtime() failed") ); wxCHECK_MSG( tm, Tm(), _T("wxGmtime_r() failed") );
} }
else else
{ {
@@ -2120,9 +2133,10 @@ int wxDateTime::IsDST(wxDateTime::Country country) const
time_t timet = GetTicks(); time_t timet = GetTicks();
if ( timet != (time_t)-1 ) if ( timet != (time_t)-1 )
{ {
tm *tm = localtime(&timet); struct tm tmstruct;
tm *tm = wxLocaltime_r(&timet, &tmstruct);
wxCHECK_MSG( tm, -1, _T("localtime() failed") ); wxCHECK_MSG( tm, -1, _T("wxLocaltime_r() failed") );
return tm->tm_isdst; return tm->tm_isdst;
} }
@@ -2184,14 +2198,15 @@ wxString wxDateTime::Format(const wxChar *format, const TimeZone& tz) const
if ( (time != (time_t)-1) && !wxStrstr(format, _T("%l")) ) if ( (time != (time_t)-1) && !wxStrstr(format, _T("%l")) )
{ {
// use strftime() // use strftime()
tm *tm; struct tm tmstruct;
struct tm *tm;
if ( tz.GetOffset() == -GetTimeZone() ) if ( tz.GetOffset() == -GetTimeZone() )
{ {
// we are working with local time // we are working with local time
tm = localtime(&time); tm = wxLocaltime_r(&time, &tmstruct);
// should never happen // should never happen
wxCHECK_MSG( tm, wxEmptyString, _T("localtime() failed") ); wxCHECK_MSG( tm, wxEmptyString, _T("wxLocaltime_r() failed") );
} }
else else
{ {
@@ -2204,10 +2219,10 @@ wxString wxDateTime::Format(const wxChar *format, const TimeZone& tz) const
if ( time >= 0 ) if ( time >= 0 )
#endif #endif
{ {
tm = gmtime(&time); tm = wxGmtime_r(&time, &tmstruct);
// should never happen // should never happen
wxCHECK_MSG( tm, wxEmptyString, _T("gmtime() failed") ); wxCHECK_MSG( tm, wxEmptyString, _T("wxGmtime_r() failed") );
} }
else else
{ {