[前][次][番号順一覧][スレッド一覧]

ruby-changes:30425

From: akr <ko1@a...>
Date: Sun, 11 Aug 2013 11:59:44 +0900 (JST)
Subject: [ruby-changes:30425] akr:r42504 (trunk): * process.c (rb_clock_gettime): New method.

akr	2013-08-11 11:59:30 +0900 (Sun, 11 Aug 2013)

  New Revision: 42504

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42504

  Log:
    * process.c (rb_clock_gettime): New method.
      This is accepted in the meeting:
      https://bugs.ruby-lang.org/projects/ruby/wiki/DevelopersMeeting20130809
      This method is accepted as a CRuby feature.
      I.e. Other Ruby implementations don't need to implement it.

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/configure.in
    trunk/process.c
    trunk/test/ruby/test_process.rb
Index: configure.in
===================================================================
--- configure.in	(revision 42503)
+++ configure.in	(revision 42504)
@@ -1262,6 +1262,7 @@ RUBY_REPLACE_TYPE(rlim_t, [int long "lon https://github.com/ruby/ruby/blob/trunk/configure.in#L1262
 @%:@include <sys/resource.h>
 ])
 RUBY_REPLACE_TYPE(off_t, [], OFFT)
+RUBY_REPLACE_TYPE(clockid_t, [], CLOCKID)
 
 AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
   [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42503)
+++ ChangeLog	(revision 42504)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Aug 11 11:54:38 2013  Tanaka Akira  <akr@f...>
+
+	* process.c (rb_clock_gettime): New method.
+	  This is accepted in the meeting:
+	  https://bugs.ruby-lang.org/projects/ruby/wiki/DevelopersMeeting20130809
+	  This method is accepted as a CRuby feature.
+	  I.e. Other Ruby implementations don't need to implement it.
+
 Sun Aug 11 10:40:48 2013  Zachary Scott  <e@z...>
 
 	* lib/time.rb: [DOC] Correcting rdoc visibility of time.rb constants
Index: process.c
===================================================================
--- process.c	(revision 42503)
+++ process.c	(revision 42504)
@@ -68,7 +68,9 @@ https://github.com/ruby/ruby/blob/trunk/process.c#L68
 # include "nacl/unistd.h"
 #endif
 
-
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
 #ifdef HAVE_SYS_TIMES_H
 #include <sys/times.h>
 #endif
@@ -6635,6 +6637,161 @@ rb_proc_times(VALUE obj) https://github.com/ruby/ruby/blob/trunk/process.c#L6637
 #define rb_proc_times rb_f_notimplement
 #endif
 
+/*
+ *  call-seq:
+ *     Process.clock_gettime(clk_id [, unit])   -> number
+ *
+ *  Returns a time returned by POSIX clock_gettime() function.
+ *
+ *  _clk_id_ specifies a kind of clock.
+ *  It is specifed as a constant which begins with <code>Process::CLOCK_</code>
+ *  such like <code>Process::CLOCK_REALTIME</code> and
+ *  <code>Process::CLOCK_MONOTONIC</code>.
+ *  The supported constants depends on OS and version.
+ *  Ruby provides following type of _clk_id_ if available.
+ *
+ *  [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1
+ *  [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4
+ *  [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63
+ *  [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63
+ *  [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1
+ *  [CLOCK_PROF] FreeBSD 3.0, OpenBSD 2.1
+ *  [CLOCK_REALTIME_FAST] FreeBSD 8.1
+ *  [CLOCK_REALTIME_PRECISE] FreeBSD 8.1
+ *  [CLOCK_MONOTONIC_FAST] FreeBSD 8.1
+ *  [CLOCK_MONOTONIC_PRECISE] FreeBSD 8.1
+ *  [CLOCK_MONOTONIC_RAW] Linux 2.6.28
+ *  [CLOCK_UPTIME] FreeBSD 7.0
+ *  [CLOCK_UPTIME_FAST] FreeBSD 8.1
+ *  [CLOCK_UPTIME_PRECISE] FreeBSD 8.1
+ *  [CLOCK_SECOND] FreeBSD 8.1
+ *
+ *  If the given _clk_id_ is not supported, Errno::EINVAL is raised.
+ *
+ *  _unit_ specifies a type of the return value.
+ *
+ *  [:float_seconds] number of seconds as a float (default)
+ *  [:float_milliseconds] number of milliseconds as a float
+ *  [:float_microseconds] number of microseconds as a float
+ *  [:milliseconds] number of milliseconds as an integer
+ *  [:microseconds] number of microseconds as an integer
+ *  [:nanoseconds] number of nanoseconds as an integer
+ *
+ *  The underlying function, clock_gettime(), returns a number of nanoseconds.
+ *  Float object (IEEE 754 double) is not enough to represent
+ *  the return value for CLOCK_REALTIME.
+ *  If the exact nanoseconds value is required, use :nanoseconds as _unit_.
+ *
+ *  The origin (zero) of the returned value varies.
+ *  For example, system start up time, process start up time, the Epoch, etc.
+ *
+ *  The origin in CLOCK_REALTIME is defined as the Epoch
+ *  (1970-01-01 00:00:00 UTC).
+ *  But some systems count leap seconds and others doesn't.
+ *  So the result can be interpreted differently across systems.
+ *  Time.now is recommended over CLOCK_REALTIME.
+ *
+ *    p Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ *    #=> 896053.968060096
+ *
+ */
+VALUE
+rb_clock_gettime(int argc, VALUE *argv)
+{
+    struct timespec ts;
+    VALUE clk_id, unit;
+    int ret;
+    long factor;
+
+    rb_scan_args(argc, argv, "11", &clk_id, &unit);
+
+    if (SYMBOL_P(clk_id)) {
+        /*
+         * Non-clock_gettime clocks are provided by symbol clk_id.
+         *
+         * gettimeofday is always available on platforms supported by Ruby.
+         * POSIX_GETTIMEOFDAY_CLOCK_REALTIME is used for
+         * CLOCK_REALTIME if clock_gettime is not available.
+         */
+#define RUBY_POSIX_GETTIMEOFDAY_CLOCK_REALTIME ID2SYM(rb_intern("POSIX_GETTIMEOFDAY_CLOCK_REALTIME"))
+        if (clk_id == RUBY_POSIX_GETTIMEOFDAY_CLOCK_REALTIME) {
+            struct timeval tv;
+            ret = gettimeofday(&tv, 0);
+            if (ret != 0)
+                rb_sys_fail("gettimeofday");
+            ts.tv_sec = tv.tv_sec;
+            ts.tv_nsec = tv.tv_usec * 1000;
+            goto success;
+        }
+
+#define RUBY_POSIX_TIME_CLOCK_REALTIME ID2SYM(rb_intern("POSIX_TIME_CLOCK_REALTIME"))
+        if (clk_id == RUBY_POSIX_TIME_CLOCK_REALTIME) {
+            time_t t;
+            t = time(NULL);
+            if (t == (time_t)-1)
+                rb_sys_fail("time");
+            ts.tv_sec = t;
+            ts.tv_nsec = 0;
+            goto success;
+        }
+    }
+    else {
+#if defined(HAVE_CLOCK_GETTIME)
+        clockid_t c;
+        c = NUM2CLOCKID(clk_id);
+        ret = clock_gettime(c, &ts);
+        if (ret == -1)
+            rb_sys_fail("clock_gettime");
+        goto success;
+#endif
+    }
+    /* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
+    errno = EINVAL;
+    rb_sys_fail(0);
+
+  success:
+    if (unit == ID2SYM(rb_intern("nanoseconds"))) {
+        factor = 1000000000;
+        goto return_integer;
+    }
+    else if (unit == ID2SYM(rb_intern("microseconds"))) {
+        factor = 1000000;
+        goto return_integer;
+    }
+    else if (unit == ID2SYM(rb_intern("milliseconds"))) {
+        factor = 1000;
+        goto return_integer;
+    }
+    else if (unit == ID2SYM(rb_intern("float_microseconds"))) {
+        factor = 1000000;
+        goto return_float;
+    }
+    else if (unit == ID2SYM(rb_intern("float_milliseconds"))) {
+        factor = 1000;
+        goto return_float;
+    }
+    else if (NIL_P(unit) || unit == ID2SYM(rb_intern("float_seconds"))) {
+        factor = 1;
+        goto return_float;
+    }
+    else {
+        rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
+    }
+
+  return_float:
+    return DBL2NUM((ts.tv_sec + 1e-9 * (double)ts.tv_nsec) / factor);
+
+  return_integer:
+#if defined(HAVE_LONG_LONG)
+    if (!MUL_OVERFLOW_SIGNED_INTEGER_P(factor, (LONG_LONG)ts.tv_sec,
+                LLONG_MIN, LLONG_MAX-(factor-1))) {
+        return LL2NUM(ts.tv_nsec/(1000000000/factor) + factor * (LONG_LONG)ts.tv_sec);
+    }
+#endif
+    return rb_funcall(LONG2FIX(ts.tv_nsec/(1000000000/factor)), '+', 1,
+            rb_funcall(LONG2FIX(factor), '*', 1, TIMET2NUM(ts.tv_sec)));
+}
+
 VALUE rb_mProcess;
 VALUE rb_mProcUID;
 VALUE rb_mProcGID;
@@ -6893,6 +7050,55 @@ Init_process(void) https://github.com/ruby/ruby/blob/trunk/process.c#L7050
 
     rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
 
+#ifdef CLOCK_REALTIME
+    rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
+#elif defined(RUBY_POSIX_GETTIMEOFDAY_CLOCK_REALTIME)
+    rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_POSIX_GETTIMEOFDAY_CLOCK_REALTIME);
+#endif
+#ifdef CLOCK_MONOTONIC
+    rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+    rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+    rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
+#endif
+#ifdef CLOCK_VIRTUAL
+    rb_define_const(rb_mProcess, "CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
+#endif
+#ifdef CLOCK_PROF
+    rb_define_const(rb_mProcess, "CLOCK_PROF", CLOCKID2NUM(CLOCK_PROF));
+#endif
+#ifdef CLOCK_REALTIME_FAST
+    rb_define_const(rb_mProcess, "CLOCK_REALTIME_FAST", CLOCKID2NUM(CLOCK_REALTIME_FAST));
+#endif
+#ifdef CLOCK_REALTIME_PRECISE
+    rb_define_const(rb_mProcess, "CLOCK_REALTIME_PRECISE", CLOCKID2NUM(CLOCK_REALTIME_PRECISE));
+#endif
+#ifdef CLOCK_MONOTONIC_FAST
+    rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_FAST", CLOCKID2NUM(CLOCK_MONOTONIC_FAST));
+#endif
+#ifdef CLOCK_MONOTONIC_PRECISE
+    rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_PRECISE", CLOCKID2NUM(CLOCK_MONOTONIC_PRECISE));
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+    rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW", CLOCKID2NUM(CLOCK_MONOTONIC_RAW));
+#endif
+#ifdef CLOCK_UPTIME
+    rb_define_const(rb_mProcess, "CLOCK_UPTIME", CLOCKID2NUM(CLOCK_UPTIME));
+#endif
+#ifdef CLOCK_UPTIME_FAST
+    rb_define_const(rb_mProcess, "CLOCK_UPTIME_FAST", CLOCKID2NUM(CLOCK_UPTIME_FAST));
+#endif
+#ifdef CLOCK_UPTIME_PRECISE
+    rb_define_const(rb_mProcess, "CLOCK_UPTIME_PRECISE", CLOCKID2NUM(CLOCK_UPTIME_PRECISE));
+#endif
+#ifdef CLOCK_SECOND
+    rb_define_const(rb_mProcess, "CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
+#endif
+    rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
+
 #if defined(HAVE_TIMES) || defined(_WIN32)
     rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
 #endif
Index: NEWS
===================================================================
--- NEWS	(revision 42503)
+++ NEWS	(revision 42504)
@@ -57,9 +57,11 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L57
     * Mutex#owned? is no longer experimental.
 
 * Process
-  * New alternative methods to $0/$0=:
-    * Process.argv0() returns the original value of $0.
-    * Process.setproctitle() sets the process title without affecting $0.
+  * New methods:
+    * alternative methods to $0/$0=:
+      * Process.argv0() returns the original value of $0.
+      * Process.setproctitle() sets the process title without affecting $0.
+    * Process.clock_gettime
 
 * String
   * New methods:
Index: test/ruby/test_process.rb
===================================================================
--- test/ruby/test_process.rb	(revision 42503)
+++ test/ruby/test_process.rb	(revision 42504)
@@ -1660,4 +1660,13 @@ EOS https://github.com/ruby/ruby/blob/trunk/test/ruby/test_process.rb#L1660
     end
   end if windows?
 
+  def test_clock_gettime
+    t1 = Process.clock_gettime(Process::CLOCK_REALTIME, :nanoseconds)
+    t2 = Time.now; t2 = t2.tv_sec * 1000000000 + t2.tv_nsec
+    t3 = Process.clock_gettime(Process::CLOCK_REALTIME, :nanoseconds)
+    assert_operator(t1, :<=, t2)
+    assert_operator(t2, :<=, t3)
+    assert_raise(Errno::EINVAL) { Process.clock_gettime(:foo) }
+  end
+
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]