Change 12574 by pudge@pudge-mobile on 2001/10/22 18:53:28

        Sync Time::HiRes with bleadperl

Affected files ...

... //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.pm#2 edit
... //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.t#2 edit
... //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.xs#3 edit

Differences ...

==== //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.pm#2 (text) ====
Index: perl/macos/bundled_ext/Time/HiRes/HiRes.pm
--- perl/macos/bundled_ext/Time/HiRes/HiRes.pm.~1~      Mon Oct 22 13:00:07 2001
+++ perl/macos/bundled_ext/Time/HiRes/HiRes.pm  Mon Oct 22 13:00:07 2001
@@ -105,8 +105,9 @@
 
 =item usleep ( $useconds )
 
-Issues a usleep for the number of microseconds specified. See also 
-Time::HiRes::sleep() below.
+Issues a usleep for the number of microseconds specified.  Returns the
+number of microseconds actually slept.  See also Time::HiRes::sleep()
+below.
 
 =item ualarm ( $useconds [, $interval_useconds ] )
 
@@ -127,11 +128,27 @@
 resulting in a nice drop-in replacement for the C<time> provided with perl,
 see the EXAMPLES below.
 
+B<NOTE>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT
+(when the time() seconds since epoch rolled over to 1_000_000_000),
+the default floating point format of Perl and the seconds since epoch
+have conspired to produce an apparent bug: if you print the value of
+Time::HiRes::time() you seem to be getting only five decimals, not six
+as promised (microseconds).  Not to worry, the microseconds are there
+(assuming your platform supports such granularity).  What is going on
+is that the default floating point format of Perl only outputs 15
+digits.  In this case that means ten digits before the decimal
+separator and five after.  To see the microseconds you can use either
+printf/sprintf with C<%.6f>, or the gettimeofday() function in list
+context, which will give you the seconds and microseconds as two
+separate values.
+
 =item sleep ( $floating_seconds )
 
-Converts $floating_seconds to microseconds and issues a usleep for the 
-result.  This function can be imported, resulting in a nice drop-in 
-replacement for the C<sleep> provided with perl, see the EXAMPLES below.
+Converts $floating_seconds to microseconds and issues a usleep for the
+result.  Returns the number of seconds actually slept (a floating
+point value).  This function can be imported, resulting in a nice
+drop-in replacement for the C<sleep> provided with perl, see the
+EXAMPLES below.
 
 =item alarm ( $floating_seconds [, $interval_floating_seconds ] )
 

==== //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.t#2 (text) ====
Index: perl/macos/bundled_ext/Time/HiRes/HiRes.t
--- perl/macos/bundled_ext/Time/HiRes/HiRes.t.~1~       Mon Oct 22 13:00:07 2001
+++ perl/macos/bundled_ext/Time/HiRes/HiRes.t   Mon Oct 22 13:00:07 2001
@@ -3,7 +3,7 @@
     @INC = '../lib';
 }
 
-BEGIN { $| = 1; print "1..19\n"; }
+BEGIN { $| = 1; print "1..21\n"; }
 
 END {print "not ok 1\n" unless $loaded;}
 
@@ -86,7 +86,7 @@
 # Two-arg tv_interval() is always available.
 {
     my $f = tv_interval [5, 100_000], [10, 500_000];
-    ok 9, $f == 5.4, $f;
+    ok 9, abs($f - 5.4) < 0.001, $f;
 }
 
 if (!$have_gettimeofday) {
@@ -133,10 +133,16 @@
 if (!$have_time) {
     skip 14
 } else {
- my $t = time();
- my $tf = Time::HiRes::time();
- ok 14, (abs($tf - $t) <= 1),
-  "time $t differs from Time::HiRes::time $tf";
+ my ($t1, $tf, $t2);
+ for my $i (1 .. 9) {
+     $t1 = time();
+     $tf = Time::HiRes::time();
+     $t2 = 1 + time();
+     last if (($t2 - $t1) <= 1);
+ }
+ ok 14, (($t1 <= $tf) && ($tf <= $t2)),
+      "Time::HiRes::time $tf not bracketed by $t1 - $t2";
+
 }
 
 unless (defined &Time::HiRes::gettimeofday
@@ -217,3 +223,9 @@
     $SIG{VTALRM} = 'DEFAULT';
 }
 
+$a = abs(sleep(1.5)                    - 1.5);
+print $a < 0.1 ? "ok 20 # $a\n" : "not ok 20 # $a\n";
+
+$a = abs(usleep(1_500_000) / 1_500_000 - 1.0);
+print $a < 0.1 ? "ok 21 # $a\n" : "not ok 21 # $a\n";
+

==== //depot/maint-5.6/macperl/macos/bundled_ext/Time/HiRes/HiRes.xs#3 (text) ====
Index: perl/macos/bundled_ext/Time/HiRes/HiRes.xs
--- perl/macos/bundled_ext/Time/HiRes/HiRes.xs.~1~      Mon Oct 22 13:00:07 2001
+++ perl/macos/bundled_ext/Time/HiRes/HiRes.xs  Mon Oct 22 13:00:07 2001
@@ -63,31 +63,38 @@
 }
 */
 
+typedef union {
+    unsigned __int64   ft_i64;
+    FILETIME           ft_val;
+} FT_t;
+
+/* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
+#define EPOCH_BIAS  116444736000000000i64
+
+/* NOTE: This does not compute the timezone info (doing so can be expensive,
+ * and appears to be unsupported even by glibc) */
 int
-gettimeofday (struct timeval *tp, int nothing)
+gettimeofday (struct timeval *tp, void *not_used)
 {
- SYSTEMTIME st;
- time_t tt;
- struct tm tmtm;
- /* mktime converts local to UTC */
- GetLocalTime (&st);
- tmtm.tm_sec = st.wSecond;
- tmtm.tm_min = st.wMinute;
- tmtm.tm_hour = st.wHour;
- tmtm.tm_mday = st.wDay;
- tmtm.tm_mon = st.wMonth - 1;
- tmtm.tm_year = st.wYear - 1900;
- tmtm.tm_isdst = -1;
- tt = mktime (&tmtm);
- tp->tv_sec = tt;
- tp->tv_usec = st.wMilliseconds * 1000;
- return 0;
+    FT_t ft;
+
+    /* this returns time in 100-nanosecond units  (i.e. tens of usecs) */
+    GetSystemTimeAsFileTime(&ft.ft_val);
+
+    /* seconds since epoch */
+    tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / 10000000i64);
+
+    /* microseconds remaining */
+    tp->tv_usec = (long)((ft.ft_i64 / 10i64) % 1000000i64);
+
+    return 0;
 }
 #endif
 
 #if !defined(HAS_GETTIMEOFDAY) && defined(VMS)
 #define HAS_GETTIMEOFDAY
 
+#include <lnmdef.h>
 #include <time.h> /* gettimeofday */
 #include <stdlib.h> /* qdiv */
 #include <starlet.h> /* sys$gettim */
@@ -116,6 +123,90 @@
 static __int64 base_adjust=0;
 #endif
 
+/* 
+
+   If we don't have gettimeofday, then likely we are on a VMS machine that
+   operates on local time rather than UTC...so we have to zone-adjust.
+   This code gleefully swiped from VMS.C 
+
+*/
+/* method used to handle UTC conversions:
+ *   1 == CRTL gmtime();  2 == SYS$TIMEZONE_DIFFERENTIAL;  3 == no correction
+ */
+static int gmtime_emulation_type;
+/* number of secs to add to UTC POSIX-style time to get local time */
+static long int utc_offset_secs;
+static struct dsc$descriptor_s fildevdsc = 
+  { 12, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$FILE_DEV" };
+static struct dsc$descriptor_s *fildev[] = { &fildevdsc, NULL };
+
+static time_t toutc_dst(time_t loc) {
+  struct tm *rsltmp;
+
+  if ((rsltmp = localtime(&loc)) == NULL) return -1;
+  loc -= utc_offset_secs;
+  if (rsltmp->tm_isdst) loc -= 3600;
+  return loc;
+}
+
+static time_t toloc_dst(time_t utc) {
+  struct tm *rsltmp;
+
+  utc += utc_offset_secs;
+  if ((rsltmp = localtime(&utc)) == NULL) return -1;
+  if (rsltmp->tm_isdst) utc += 3600;
+  return utc;
+}
+
+#define _toutc(secs)  ((secs) == (time_t) -1 ? (time_t) -1 : \
+       ((gmtime_emulation_type || timezone_setup()), \
+       (gmtime_emulation_type == 1 ? toutc_dst(secs) : \
+       ((secs) - utc_offset_secs))))
+
+#define _toloc(secs)  ((secs) == (time_t) -1 ? (time_t) -1 : \
+       ((gmtime_emulation_type || timezone_setup()), \
+       (gmtime_emulation_type == 1 ? toloc_dst(secs) : \
+       ((secs) + utc_offset_secs))))
+
+static int
+timezone_setup(void) 
+{
+  struct tm *tm_p;
+
+  if (gmtime_emulation_type == 0) {
+    int dstnow;
+    time_t base = 15 * 86400; /* 15jan71; to avoid month/year ends between    */
+                              /* results of calls to gmtime() and localtime() */
+                              /* for same &base */
+
+    gmtime_emulation_type++;
+    if ((tm_p = gmtime(&base)) == NULL) { /* CRTL gmtime() is a fake */
+      char off[LNM$C_NAMLENGTH+1];;
+
+      gmtime_emulation_type++;
+      if (!Perl_vmstrnenv("SYS$TIMEZONE_DIFFERENTIAL",off,0,fildev,0)) {
+        gmtime_emulation_type++;
+        utc_offset_secs = 0;
+        Perl_warn(aTHX_ "no UTC offset information; assuming local time is UTC");
+      }
+      else { utc_offset_secs = atol(off); }
+    }
+    else { /* We've got a working gmtime() */
+      struct tm gmt, local;
+
+      gmt = *tm_p;
+      tm_p = localtime(&base);
+      local = *tm_p;
+      utc_offset_secs  = (local.tm_mday - gmt.tm_mday) * 86400;
+      utc_offset_secs += (local.tm_hour - gmt.tm_hour) * 3600;
+      utc_offset_secs += (local.tm_min  - gmt.tm_min)  * 60;
+      utc_offset_secs += (local.tm_sec  - gmt.tm_sec);
+    }
+  }
+  return 1;
+}
+
+
 int
 gettimeofday (struct timeval *tp, void *tpz)
 {
@@ -175,6 +266,13 @@
         tp->tv_sec = ret;
         return -1;
  }
+# ifdef VMSISH_TIME
+# ifdef RTL_USES_UTC
+  if (VMSISH_TIME) tp->tv_sec = _toloc(tp->tv_sec);
+# else
+  if (!VMSISH_TIME) tp->tv_sec = _toutc(tp->tv_sec);
+# endif
+# endif
  return 0;
 }
 #endif
@@ -269,18 +367,54 @@
        char *          name
        int             arg
 
-#ifdef HAS_USLEEP
+#if defined(HAS_USLEEP) && defined(HAS_GETTIMEOFDAY)
 
-void
+NV
 usleep(useconds)
-        int useconds 
+        NV useconds
+       PREINIT:
+       struct timeval Ta, Tb;
+       CODE:
+       gettimeofday(&Ta, NULL);
+       if (items > 0) {
+           if (useconds > 1E6) {
+               IV seconds = (IV) (useconds / 1E6);
+               sleep(seconds);
+               useconds -= 1E6 * seconds;
+           }
+           usleep((UV)useconds);
+       } else
+           PerlProc_pause();
+       gettimeofday(&Tb, NULL);
+#if 0
+       printf("[%ld %ld] [%ld %ld]\n", Tb.tv_sec, Tb.tv_usec, Ta.tv_sec, Ta.tv_usec);
+#endif
+       RETVAL = 1E6*(Tb.tv_sec-Ta.tv_sec)+(NV)((IV)Tb.tv_usec-(IV)Ta.tv_usec);
+
+       OUTPUT:
+       RETVAL
 
-void
-sleep(fseconds)
-        NV fseconds 
+NV
+sleep(...)
+       PREINIT:
+       struct timeval Ta, Tb;
        CODE:
-       int useconds = fseconds * 1000000;
-       usleep (useconds);
+       gettimeofday(&Ta, NULL);
+       if (items > 0) {
+           NV seconds  = SvNV(ST(0));
+           IV useconds = 1E6 * (seconds - (IV)seconds);
+           sleep(seconds);
+           usleep(useconds);
+       } else
+           PerlProc_pause();
+       gettimeofday(&Tb, NULL);
+#if 0
+       printf("[%ld %ld] [%ld %ld]\n", Tb.tv_sec, Tb.tv_usec, Ta.tv_sec, Ta.tv_usec);
+#endif
+       RETVAL = (NV)(Tb.tv_sec-Ta.tv_sec)+0.000001*(NV)(Tb.tv_usec-Ta.tv_usec);
+
+       OUTPUT:
+       RETVAL
 
 #endif
 
End of Patch.

Reply via email to