From: <ai...@us...> - 2009-02-20 19:43:17
|
Revision: 9564 http://plplot.svn.sourceforge.net/plplot/?rev=9564&view=rev Author: airwin Date: 2009-02-20 19:43:15 +0000 (Fri, 20 Feb 2009) Log Message: ----------- Convert to a thread-safe libqsastime where qsasconfig is carried as an extra argument to configqsas, closeqsas, btimeqsas, ctimeqsas, and strfqsas rather than as a global library variable. Thanks to Andrew Ross for this suggestiong for making libqsastime thread safe. Modified Paths: -------------- trunk/lib/qsastime/README.qsastime_API trunk/lib/qsastime/qsastime.c trunk/lib/qsastime/qsastime.h trunk/src/plbox.c Modified: trunk/lib/qsastime/README.qsastime_API =================================================================== --- trunk/lib/qsastime/README.qsastime_API 2009-02-20 19:38:15 UTC (rev 9563) +++ trunk/lib/qsastime/README.qsastime_API 2009-02-20 19:43:15 UTC (rev 9564) @@ -1,10 +1,11 @@ -The desired API for libqsastime should consist of just five functions that -are actually publicly visible. The names of these five functions are -subject to change, but I hope we can finalize those names shortly. +The desired API for libqsastime should consist of just five functions +that are actually publicly visible. ========================= -void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec); +void configqsas(double scale, double offset1, double offset2, int +ccontrol, int ifbtime_offset, int year, int month, int day, int hour, +int min, double sec, QSASCONFIG **qsasconfig); Within this routine if ifbtime_offset is false, then the broken-down time arguments are ignored. If ifbtime_offset is true, then the input @@ -12,17 +13,20 @@ time values are used to calculate offset1 and offset2 with the help of an internal call to setFromUT. -This routine allocates memory for the global qsasconfig pointer to -a QSASConfig struct. It initializes the four variables encapsulated -in QSASConfig with scale, offset1, offset2, and ccontrol. Further -details of the meaning of these four variables is contained in -qsastime.h. +If *qsasconfig is NULL, this routine allocates memory for a QSASCONFIG +struct and points *qsaconfig to that memory location. It initializes +the four variables encapsulated in that struct with scale, offset1, +offset2, and ccontrol. Further details of the meaning of these four +variables is contained in qsastime.h. The special pointer to a +pointer QSASCONFIG argument is required so that the external pointer +can be changed if/when the memory is allocated. -Although this API gives the user a large degree of flexibility in choosing -the transformation between broken-down time and continuous time, a number of -combinations of offset1, offset2, scale, and ccontrol are documented -below for some common time system transformations to guide the user. -(Some of these are currently just placeholders.) +Although this API gives the user a large degree of flexibility in +choosing the transformation between broken-down time and continuous +time, a number of combinations of offset1, offset2, scale, and +ccontrol are documented below for some common time system +transformations to guide the user. (Some of these are currently just +placeholders.) Broken- Contin- offset1 offset2 scale correction Notes down uous @@ -39,76 +43,87 @@ 1. These offset1, offset2, scale, and correction values are the library default if the user does not call time_config at all. -2. We define civil time as the civil time on the prime meridian. (The user -is responsible for converting their local time to civil time using their -locale data for time zone and daylight savings time adjustment). Currently, -our civil time corresponds to UTC as defined in note 3. +2. We define civil time as the civil time on the prime meridian. (The +user is responsible for converting their local time to civil time +using their locale data for time zone and daylight savings time +adjustment). Currently, our civil time corresponds to UTC as defined +in note 3. -3. We use the file at http://maia.usno.navy.mil/ser7/tai-utc.dat to define -the relationship between UTC and TAI (and thus TT) for correction = 1. +3. We use the file at http://maia.usno.navy.mil/ser7/tai-utc.dat to +define the relationship between UTC and TAI (and thus TT) for +correction = 1. For epochs prior to the starting date of that file (1961-01-01 = JD -2437300.5 UTC) we assume the same TAI-UTC offset of 1.422818 seconds as for -the starting date of that file. This assumption of no variation in the -earth rotation rate prior to 1961 is obviously not correct so that the TT -derived from our code will not be reliable prior to that date. That is, if -you use GMT (a historical backwards extension of UTC corresponding to civil -time for the prime meridian) for broken down time prior to 1961, the TT -result you will get will not produce a good approximation to the historical -ephemeris time that is the correct backwards extension of TT, see -http://en.wikipedia.org/wiki/Ephemeris_time. +2437300.5 UTC) we assume the same TAI-UTC offset of 1.422818 seconds +as for the starting date of that file. This assumption of no +variation in the earth rotation rate prior to 1961 is obviously not +correct so that the TT derived from our code will not be reliable +prior to that date. That is, if you use GMT (a historical backwards +extension of UTC corresponding to civil time for the prime meridian) +for broken down time prior to 1961, the TT result you will get will +not produce a good approximation to the historical ephemeris time that +is the correct backwards extension of TT, see +http://en.wikipedia.org/wiki/Ephemeris_time. -For epochs after the ending date of that file (currently 2009-01-01 = JD -2454832.5 UTC) we assume the same TAI-UTC offset (currently 34 seconds) as -for the ending date of that file, i.e., we assume no leap seconds after the -ending date of the file. Insertion of leap seconds cannot be predicted years -in advance (because future predictions of the earth rotation rate are not -reliable on such time scales) so the transformation between civil time (UTC) -and TT cannot be known years in advance. However, the approximation of -assuming no leap seconds after the end of the file should be correct on time -scales less than roughly a year so when a decision is made in advance to -insert an official leap second, there should be plenty of time for that -decision to propagate to http://maia.usno.navy.mil/ser7/tai-utc.dat and -ultimately our code releases. Thus, so long as we make releases on a timely -basis, our calculation of TT for current epochs should always be reliable. +For epochs after the ending date of that file (currently 2009-01-01 = +JD 2454832.5 UTC) we assume the same TAI-UTC offset (currently 34 +seconds) as for the ending date of that file, i.e., we assume no leap +seconds after the ending date of the file. Insertion of leap seconds +cannot be predicted years in advance (because future predictions of +the earth rotation rate are not reliable on such time scales) so the +transformation between civil time (UTC) and TT cannot be known years +in advance. However, the approximation of assuming no leap seconds +after the end of the file should be correct on time scales less than +roughly a year so when a decision is made in advance to insert an +official leap second, there should be plenty of time for that decision +to propagate to http://maia.usno.navy.mil/ser7/tai-utc.dat and +ultimately our code releases. Thus, so long as we make releases on a +timely basis, our calculation of TT for current epochs should always +be reliable. -2. I haven't checked the code yet, but I assume this relationship holds for -all transformations between broken-down time and continuous time in MJD -when the broken-down time and continuous time are defined on the same -continuous time scale (TT in this case). All other relationships are -derived from the known offsets with respect to TT and differences between -MJD epochs and native (TT, TAI, etc.) epochs. +2. I haven't checked the code yet, but I assume this relationship +holds for all transformations between broken-down time and continuous +time in MJD when the broken-down time and continuous time are defined +on the same continuous time scale (TT in this case). All other +relationships are derived from the known offsets with respect to TT +and differences between MJD epochs and native (TT, TAI, etc.) epochs. -3. Offset derived from definition TT = TAI + 32.184 s = TAI + 0.0003725 d +3. Offset derived from definition TT = TAI + 32.184 s = TAI + +0.0003725 d -4. Continuous times (e.g., TT) without further designation are in seconds -since the native (e.g., TT) epoch. NEEDS WORK to figure out offset. +4. Continuous times (e.g., TT) without further designation are in +seconds since the native (e.g., TT) epoch. NEEDS WORK to figure out +offset. 5. the POSIX time standard of seconds since the Unix epoch is actually -discontinuous (see remarks in http://en.wikipedia.org/wiki/Unix_Time). So -our "Unix (TAI)" continuous time scale (NOT YET IN THE TABLE) corresponds to -the continuous "International Atomic Time-based variant" discussed in the -above article. NEEDS FURTHER INVESTIGATION. +discontinuous (see remarks in http://en.wikipedia.org/wiki/Unix_Time). +So our "Unix (TAI)" continuous time scale (NOT YET IN THE TABLE) +corresponds to the continuous "International Atomic Time-based +variant" discussed in the above article. NEEDS FURTHER INVESTIGATION. -dTT/dTCG = 1-LG, where LG = 6.969290134D-10, -IAU Resolution B1.9 Re-definition of Terrestrial Time TT, +dTT/dTCG = 1-LG, where LG = 6.969290134D-10, IAU Resolution B1.9 +Re-definition of Terrestrial Time TT, http://syrte.obspm.fr/IAU_resolutions/Resol-UAI.htm -Time ephemeris reference is Irwin and -Fukushima, 1999, http://adsabs.harvard.edu/full/1999A&A...348..642I). +Time ephemeris reference is Irwin and Fukushima, 1999, +http://adsabs.harvard.edu/full/1999A&A...348..642I). ========================= -void closeqsas (void): +void closeqsas (QSASCONFIG **qsasconfig): -Closes library by freeing memory allocated for qsasconfig. +This routine closes the library by freeing memory allocated for +qsasconfig if *qsaconfig is non-NULL and sets *qsasconfig to NULL. +The special pointer to a pointer QSASCONFIG argument is required in +order to change the external pointer. + ========================= void ctimeqsas (int year, int month, int day, int hour, int min, -double sec, double *ctime); +double sec, double *ctime, QSASCONFIG *qsasconfig); Determine continuous time (ctime). Wraps the existing internal (not -visible by default) setFromUT to use the four global variables +visible by default) setFromUT to use the four variables in qsasconfig discussed above in the transformation from broken-down-time to ctime. Note, because of the transformation implied by the four variables mentioned above, the ctime result can be stored in just a double @@ -119,26 +134,28 @@ ========================= void btimeqsas (int *year, int *month, int *day, int *hour, int *min, -double *sec, double ctime); +double *sec, double ctime, QSASCONFIG *qsasconfig); -Determine broken-down time (btime). This is the inverse of ctimeqsas. It -wraps the existing internal (not visible by default) breakDownMJD to use the -four global variables discussed above in the transformation from ctime to -btime. Note, because of the transformation implied by the four variables -mentioned above, the input ctime can be just a double assuming the user has -picked a reasonable epoch that is not so distant from his plotted range of -times that it causes a noticable loss of numerical precision. +Determine broken-down time (btime). This is the inverse of ctimeqsas. +It wraps the existing internal (not visible by default) breakDownMJD +to use the four variables in qsasconfig discussed above in the +transformation from ctime to btime. Note, because of the +transformation implied by the four variables, the input ctime can be +just a double assuming the user has picked a reasonable epoch that is +not so distant from his plotted range of times that it causes a +noticable loss of numerical precision. ========================= -size_t strfqsas (char * buf, size_t len, const char * format, const -double ctime); +size_t strfqsas (char * buf, size_t len, const char * format, const +double ctime, QSASCONFIG *qsasconfig); -This wraps the existing internal (not visible by default) strfMJD to use the -four global variables discussed above in the transformation from ctime to -btime. Note, because of the transformation implied by the four variables -mentioned above, the input ctime can be just a double assuming the user has -picked a reasonable epoch that is not so distant from his plotted range of -times that it causes a noticable loss of numerical precision. +This wraps the existing internal (not visible by default) strfMJD to +use the four variables in qsasconfig discussed above in the +transformation from ctime to btime. Note, because of the +transformation implied by the four variables, the input ctime can be +just a double assuming the user has picked a reasonable epoch that is +not so distant from his plotted range of times that it causes a +noticable loss of numerical precision. ========================= Modified: trunk/lib/qsastime/qsastime.c =================================================================== --- trunk/lib/qsastime/qsastime.c 2009-02-20 19:38:15 UTC (rev 9563) +++ trunk/lib/qsastime/qsastime.c 2009-02-20 19:43:15 UTC (rev 9564) @@ -859,18 +859,18 @@ return posn; } -void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec) +void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec, QSASConfig **qsasconfig) { /* Configure the transformation between continuous time and broken-down time that is used for ctimeqsas, btimeqsas, and strfqsas. */ int forceJulian, ret; MJDtime MJD_value, *MJD=&MJD_value; - /* Allocate memory for qsasconfig if that hasn't been done by a + /* Allocate memory for *qsasconfig if that hasn't been done by a previous call. */ - if(qsasconfig == NULL) { - qsasconfig = (QSASConfig *) malloc((size_t) sizeof(QSASConfig)); - if (qsasconfig == NULL) { + if(*qsasconfig == NULL) { + *qsasconfig = (QSASConfig *) malloc((size_t) sizeof(QSASConfig)); + if (*qsasconfig == NULL) { fprintf(stderr, "configqsas: out of memory\n"); exit(EXIT_FAILURE); } @@ -890,32 +890,32 @@ offset1 = (double)MJD->base_day; offset2 = MJD->time_sec/(double)SecInDay; } - qsasconfig->scale = scale; - qsasconfig->offset1 = offset1; - qsasconfig->offset2 = offset2; - qsasconfig->ccontrol = ccontrol; + (*qsasconfig)->scale = scale; + (*qsasconfig)->offset1 = offset1; + (*qsasconfig)->offset2 = offset2; + (*qsasconfig)->ccontrol = ccontrol; } else { /* if scale is 0., then use default values. Currently, that default is continuous time (stored as a double) is seconds since 1970-01-01 while broken-down time is Gregorian with no other additional corrections. */ - qsasconfig->scale = 1./(double)SecInDay; - qsasconfig->offset1 = (double) MJD_1970; - qsasconfig->offset2 = 0.; - qsasconfig->ccontrol = 0x0; + (*qsasconfig)->scale = 1./(double)SecInDay; + (*qsasconfig)->offset1 = (double) MJD_1970; + (*qsasconfig)->offset2 = 0.; + (*qsasconfig)->ccontrol = 0x0; } } -void closeqsas(void) +void closeqsas(QSASConfig **qsasconfig) { /* Close library if it has been opened. */ - if(qsasconfig != NULL) { - free((void *) qsasconfig); - qsasconfig = NULL; + if(*qsasconfig != NULL) { + free((void *) *qsasconfig); + *qsasconfig = NULL; } } -int ctimeqsas(int year, int month, int day, int hour, int min, double sec, double * ctime){ +int ctimeqsas(int year, int month, int day, int hour, int min, double sec, double * ctime, QSASConfig *qsasconfig){ MJDtime MJD_value, *MJD=&MJD_value; int forceJulian, ret; double integral_offset1, integral_offset2, integral_scaled_ctime; @@ -938,7 +938,7 @@ } -void btimeqsas(int *year, int *month, int *day, int *hour, int *min, double *sec, double ctime){ +void btimeqsas(int *year, int *month, int *day, int *hour, int *min, double *sec, double ctime, QSASConfig *qsasconfig){ MJDtime MJD_value, *MJD=&MJD_value; int forceJulian; double integral_offset1, integral_offset2, integral_scaled_ctime; @@ -959,7 +959,8 @@ breakDownMJD(year, month, day, hour, min, sec, MJD, forceJulian); } -size_t strfqsas(char * buf, size_t len, const char *format, double ctime){ +size_t strfqsas(char * buf, size_t len, const char *format, double ctime, QSASConfig *qsasconfig) +{ MJDtime MJD_value, *MJD=&MJD_value; int forceJulian; double integral_offset1, integral_offset2, integral_scaled_ctime; Modified: trunk/lib/qsastime/qsastime.h =================================================================== --- trunk/lib/qsastime/qsastime.h 2009-02-20 19:38:15 UTC (rev 9563) +++ trunk/lib/qsastime/qsastime.h 2009-02-20 19:43:15 UTC (rev 9564) @@ -98,13 +98,15 @@ }QSASConfig; -QSASTIMEDLLIMPEXP_DATA(QSASConfig) *qsasconfig; - /* externally accessible functions */ -QSASTIMEDLLIMPEXP void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec); -QSASTIMEDLLIMPEXP void closeqsas(void); -QSASTIMEDLLIMPEXP int ctimeqsas(int year, int month, int day, int hour, int min, double sec, double * ctime); -QSASTIMEDLLIMPEXP void btimeqsas(int *year, int *month, int *day, int *hour, int *min, double *sec, double ctime); -QSASTIMEDLLIMPEXP size_t strfqsas(char * buf, size_t len, const char *format, double ctime); +QSASTIMEDLLIMPEXP void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec, QSASConfig **qsasconfig); +QSASTIMEDLLIMPEXP void closeqsas(QSASConfig **qsasconfig); + +QSASTIMEDLLIMPEXP int ctimeqsas(int year, int month, int day, int hour, int min, double sec, double * ctime, QSASConfig *qsasconfig); + +QSASTIMEDLLIMPEXP void btimeqsas(int *year, int *month, int *day, int *hour, int *min, double *sec, double ctime, QSASConfig *qsasconfig); + +QSASTIMEDLLIMPEXP size_t strfqsas(char * buf, size_t len, const char *format, double ctime, QSASConfig *qsasconfig); + #endif Modified: trunk/src/plbox.c =================================================================== --- trunk/src/plbox.c 2009-02-20 19:38:15 UTC (rev 9563) +++ trunk/src/plbox.c 2009-02-20 19:43:15 UTC (rev 9564) @@ -1206,6 +1206,7 @@ const char *timefmt; double tm; double t; + QSASConfig *qsasconfig = NULL; /* Set plot options from input */ @@ -1252,10 +1253,10 @@ for (tn = tp; BETW(tn, vpwxmi, vpwxma); tn += xtick1) { if (ldx) { t = (double) tn; - configqsas(1./86400., 0., 0., 0x0, 1, 1970, 0, 1, 0, 0, 0.); - ctimeqsas(1970,0,1,0,0,t,&tm); - strfqsas(string, STRING_LEN, timefmt, tm); - closeqsas(); + configqsas(1./86400., 0., 0., 0x0, 1, 1970, 0, 1, 0, 0, 0., &qsasconfig); + ctimeqsas(1970,0,1,0,0,t,&tm, qsasconfig); + strfqsas(string, STRING_LEN, timefmt, tm, qsasconfig); + closeqsas(&qsasconfig); } else { plform(tn, xscale, xprec, string, STRING_LEN, llx, lfx); @@ -1303,10 +1304,10 @@ for (tn = tp; BETW(tn, vpwymi, vpwyma); tn += ytick1) { if (ldy) { t = (double) tn; - configqsas(1./86400., 0., 0., 0x0, 1, 1970, 0, 1, 0, 0, 0.); - ctimeqsas(1970,0,1,0,0,t,&tm); - strfqsas(string, STRING_LEN, timefmt, tm); - closeqsas(); + configqsas(1./86400., 0., 0., 0x0, 1, 1970, 0, 1, 0, 0, 0., &qsasconfig); + ctimeqsas(1970,0,1,0,0,t,&tm, qsasconfig); + strfqsas(string, STRING_LEN, timefmt, tm, qsasconfig); + closeqsas(&qsasconfig); } else { plform(tn, yscale, yprec, string, STRING_LEN, lly, lfy); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |