[Groonga-commit] groonga/grnxx [master] Implement grnxx::PeriodicClock.

Back to archive index

susumu.yata null+****@clear*****
Fri Mar 22 21:46:17 JST 2013


susumu.yata	2013-03-22 21:46:17 +0900 (Fri, 22 Mar 2013)

  New Revision: 7d7d8744369fb0bade6e78397e96e43d11d16623
  https://github.com/groonga/grnxx/commit/7d7d8744369fb0bade6e78397e96e43d11d16623

  Message:
    Implement grnxx::PeriodicClock.
    
    Also, merge time-related tests.

  Removed files:
    test/test_broken_down_time.cpp
    test/test_internal_clock.cpp
    test/test_stopwatch.cpp
  Modified files:
    .gitignore
    lib/grnxx/time/periodic_clock.cpp
    lib/grnxx/time/periodic_clock.hpp
    test/Makefile.am
    test/test_time.cpp

  Modified: .gitignore (+0 -4)
===================================================================
--- .gitignore    2013-03-22 20:18:02 +0900 (ce0d5e5)
+++ .gitignore    2013-03-22 21:46:17 +0900 (5e4063b)
@@ -29,7 +29,6 @@ stamp-h1
 temp/
 test/test_alpha_double_array
 test/test_backtrace
-test/test_broken_down_time
 test/test_charset
 test/test_db_blob_vector
 test/test_db_vector
@@ -38,9 +37,7 @@ test/test_error
 test/test_exception
 test/test_features
 test/test_grnxx
-test/test_internal_clock
 test/test_intrinsic
-test/test_io_alpha_pool
 test/test_io_file
 test/test_io_file_info
 test/test_io_path
@@ -55,7 +52,6 @@ test/test_mutex
 test/test_os
 test/test_recycler
 test/test_slice
-test/test_stopwatch
 test/test_string
 test/test_string_builder
 test/test_string_format

  Modified: lib/grnxx/time/periodic_clock.cpp (+45 -3)
===================================================================
--- lib/grnxx/time/periodic_clock.cpp    2013-03-22 20:18:02 +0900 (9b63257)
+++ lib/grnxx/time/periodic_clock.cpp    2013-03-22 21:46:17 +0900 (744ad32)
@@ -17,21 +17,63 @@
 */
 #include "grnxx/time/periodic_clock.hpp"
 
+#include <thread>
+
+#include "grnxx/intrinsic.hpp"
+#include "grnxx/thread.hpp"
+
 namespace grnxx {
 namespace {
 
-// TODO
+// Accuracy of the periodic clock. Note that a short sleep may lead to a
+// busy-wait loop, which exhausts CPU resources.
+constexpr Duration UPDATE_INTERVAL = Duration::milliseconds(100);
+
+volatile uint32_t ref_count = 0;
+std::thread thread;
 
 }  // namespace
 
 Time PeriodicClock::now_ = Time::min();
 
 PeriodicClock::PeriodicClock() {
-  // TODO
+  for ( ; ; ) {
+    const uint32_t count = ref_count;
+    if (atomic_compare_and_swap(count, count + 1, &ref_count)) {
+      if (count == 0) {
+        // Start the internal thread.
+        try {
+          thread = std::thread(routine);
+          now_ = SystemClock::now();
+        } catch (...) {
+          // Do nothing on failure.
+        }
+      }
+      break;
+    }
+  }
 }
 
 PeriodicClock::~PeriodicClock() {
-  // TODO
+  for ( ; ; ) {
+    const uint32_t count = ref_count;
+    if (atomic_compare_and_swap(count, count - 1, &ref_count)) {
+      if (count == 1) {
+        // Stop the internal thread.
+        thread.join();
+        now_ = Time::min();
+      }
+      break;
+    }
+  }
+}
+
+// Periodically update the internal time variable.
+void PeriodicClock::routine() {
+  while (ref_count != 0) {
+    Thread::sleep_for(UPDATE_INTERVAL);
+    now_ = SystemClock::now();
+  }
 }
 
 }  // namespace grnxx

  Modified: lib/grnxx/time/periodic_clock.hpp (+3 -1)
===================================================================
--- lib/grnxx/time/periodic_clock.hpp    2013-03-22 20:18:02 +0900 (556e07e)
+++ lib/grnxx/time/periodic_clock.hpp    2013-03-22 21:46:17 +0900 (a71ea52)
@@ -28,12 +28,14 @@ class PeriodicClock {
   PeriodicClock();
   ~PeriodicClock();
 
-  Time now() const {
+  static Time now() {
     return (now_ == Time::min()) ? SystemClock::now() : now_;
   }
 
  private:
   static Time now_;
+
+  static void routine();
 };
 
 }  // namespace grnxx

  Modified: test/Makefile.am (+0 -12)
===================================================================
--- test/Makefile.am    2013-03-22 20:18:02 +0900 (80e291a)
+++ test/Makefile.am    2013-03-22 21:46:17 +0900 (0f970c0)
@@ -3,7 +3,6 @@ AM_CXXFLAGS = @AM_CXXFLAGS@
 TESTS =					\
 	test_alpha_double_array		\
 	test_backtrace			\
-	test_broken_down_time		\
 	test_charset			\
 	test_db_blob_vector		\
 	test_db_vector			\
@@ -12,7 +11,6 @@ TESTS =					\
 	test_exception			\
 	test_features			\
 	test_grnxx			\
-	test_internal_clock		\
 	test_intrinsic			\
 	test_io_file			\
 	test_io_file_info		\
@@ -28,7 +26,6 @@ TESTS =					\
 	test_os				\
 	test_recycler			\
 	test_slice			\
-	test_stopwatch			\
 	test_string			\
 	test_string_builder		\
 	test_string_format		\
@@ -43,9 +40,6 @@ test_alpha_double_array_LDADD = ../lib/grnxx/libgrnxx.la
 test_backtrace_SOURCES = test_backtrace.cpp
 test_backtrace_LDADD = ../lib/grnxx/libgrnxx.la
 
-test_broken_down_time_SOURCES = test_broken_down_time.cpp
-test_broken_down_time_LDADD = ../lib/grnxx/libgrnxx.la
-
 test_charset_SOURCES = test_charset.cpp
 test_charset_LDADD = ../lib/grnxx/libgrnxx.la
 
@@ -70,9 +64,6 @@ test_features_LDADD = ../lib/grnxx/libgrnxx.la
 test_grnxx_SOURCES = test_grnxx.cpp
 test_grnxx_LDADD = ../lib/grnxx/libgrnxx.la
 
-test_internal_clock_SOURCES = test_internal_clock.cpp
-test_internal_clock_LDADD = ../lib/grnxx/libgrnxx.la
-
 test_intrinsic_SOURCES = test_intrinsic.cpp
 test_intrinsic_LDADD = ../lib/grnxx/libgrnxx.la
 
@@ -118,9 +109,6 @@ test_recycler_LDADD = ../lib/grnxx/libgrnxx.la
 test_slice_SOURCES = test_slice.cpp
 test_slice_LDADD = ../lib/grnxx/libgrnxx.la
 
-test_stopwatch_SOURCES = test_stopwatch.cpp
-test_stopwatch_LDADD = ../lib/grnxx/libgrnxx.la
-
 test_string_SOURCES = test_string.cpp
 test_string_LDADD = ../lib/grnxx/libgrnxx.la
 

  Deleted: test/test_broken_down_time.cpp (+0 -55) 100644
===================================================================
--- test/test_broken_down_time.cpp    2013-03-22 20:18:02 +0900 (400f760)
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-  Copyright (C) 2013  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include <cassert>
-
-#include "grnxx/logger.hpp"
-#include "grnxx/time/stopwatch.hpp"
-#include "grnxx/time/system_clock.hpp"
-
-int main() {
-  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
-                           grnxx::LOGGER_ENABLE_COUT);
-  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
-
-  GRNXX_NOTICE() << "grnxx::SystemClock::now().universal_time(): "
-                 << grnxx::SystemClock::now().universal_time();
-  GRNXX_NOTICE() << "grnxx::SystemClock::now().local_time(): "
-                 << grnxx::SystemClock::now().local_time();
-
-  enum { LOOP_COUNT = 1 << 16 };
-
-  grnxx::Time now = grnxx::SystemClock::now();
-
-  grnxx::Stopwatch stopwatch(true);
-  for (int i = 0; i < LOOP_COUNT; ++i) {
-    now.universal_time();
-  }
-  grnxx::Duration elapsed = stopwatch.elapsed();
-  GRNXX_NOTICE() << "grnxx::Time::universal_time(): average elapsed [ns] = "
-                 << (1000.0 * elapsed.count() / LOOP_COUNT);
-
-  stopwatch.reset();
-  for (int i = 0; i < LOOP_COUNT; ++i) {
-    now.local_time();
-  }
-  elapsed = stopwatch.elapsed();
-  GRNXX_NOTICE() << "grnxx::Time::local_time(): average elapsed [ns] = "
-                 << (1000.0 * elapsed.count() / LOOP_COUNT);
-
-  return 0;
-}

  Deleted: test/test_internal_clock.cpp (+0 -67) 100644
===================================================================
--- test/test_internal_clock.cpp    2013-03-22 20:18:02 +0900 (2d64472)
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-  Copyright (C) 2012-2013  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include <unistd.h>
-
-#include <cassert>
-
-#include "grnxx/logger.hpp"
-#include "grnxx/thread.hpp"
-#include "grnxx/time/internal_clock.hpp"
-#include "grnxx/time/stopwatch.hpp"
-
-int main() {
-  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
-                           grnxx::LOGGER_ENABLE_COUT);
-  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
-
-  grnxx::Time time = grnxx::InternalClock::now();
-  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
-  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
-                 << time.local_time();
-
-  time = grnxx::InternalClock::now();
-  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
-  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
-                 << time.local_time();
-
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(500));
-
-  time = grnxx::InternalClock::now();
-  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
-  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
-                 << time.local_time();
-
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(500));
-
-  time = grnxx::InternalClock::now();
-  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
-  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
-                 << time.local_time();
-
-  enum { LOOP_COUNT = 1 << 20 };
-
-  grnxx::Stopwatch stopwatch(true);
-  for (int i = 0; i < LOOP_COUNT; ++i) {
-    grnxx::InternalClock::now();
-  }
-  grnxx::Duration elapsed = stopwatch.elapsed();
-  GRNXX_NOTICE() << "grnxx::InternalClock::now: average elapsed [ns] = "
-                 << (1000.0 * elapsed.count() / LOOP_COUNT);
-
-  return 0;
-}

  Deleted: test/test_stopwatch.cpp (+0 -66) 100644
===================================================================
--- test/test_stopwatch.cpp    2013-03-22 20:18:02 +0900 (700e230)
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-  Copyright (C) 2013  Brazil, Inc.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include <cassert>
-
-#include "grnxx/logger.hpp"
-#include "grnxx/thread.hpp"
-#include "grnxx/time/stopwatch.hpp"
-
-int main() {
-  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
-                           grnxx::LOGGER_ENABLE_COUT);
-  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
-
-  grnxx::Stopwatch stopwatch(false);
-  assert(stopwatch.elapsed() == grnxx::Duration(0));
-
-  stopwatch.start();
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  grnxx::Duration elapsed = stopwatch.elapsed();
-  assert(elapsed > grnxx::Duration(0));
-
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  assert(stopwatch.elapsed() > elapsed);
-
-  stopwatch.stop();
-  elapsed = stopwatch.elapsed();
-
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  assert(stopwatch.elapsed() == elapsed);
-
-  stopwatch.start();
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  assert(stopwatch.elapsed() > elapsed);
-
-  GRNXX_NOTICE() << "stopwatch.elapsed() = " << stopwatch.elapsed();
-
-  elapsed = stopwatch.elapsed();
-  stopwatch.reset();
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  assert(stopwatch.elapsed() < elapsed);
-  assert(stopwatch.elapsed() > grnxx::Duration(0));
-
-  stopwatch.stop();
-  stopwatch.reset();
-  assert(stopwatch.elapsed() == grnxx::Duration(0));
-
-  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
-  assert(stopwatch.elapsed() == grnxx::Duration(0));
-
-  return 0;
-}

  Modified: test/test_time.cpp (+160 -5)
===================================================================
--- test/test_time.cpp    2013-03-22 20:18:02 +0900 (aff19e7)
+++ test/test_time.cpp    2013-03-22 21:46:17 +0900 (12cefa7)
@@ -18,19 +18,49 @@
 #include <cassert>
 
 #include "grnxx/logger.hpp"
+#include "grnxx/thread.hpp"
+#include "grnxx/time/broken_down_time.hpp"
+#include "grnxx/time/internal_clock.hpp"
+#include "grnxx/time/periodic_clock.hpp"
 #include "grnxx/time/stopwatch.hpp"
 #include "grnxx/time/system_clock.hpp"
+#include "grnxx/time/time.hpp"
 
-int main() {
-  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
-                           grnxx::LOGGER_ENABLE_COUT);
-  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
-
+void test_time() {
   assert(grnxx::Time::max().count() ==
          std::numeric_limits<std::int64_t>::max());
   assert(grnxx::Time::min().count() ==
          std::numeric_limits<std::int64_t>::min());
+}
+
+void test_broken_down_time() {
+  GRNXX_NOTICE() << "grnxx::SystemClock::now().universal_time(): "
+                 << grnxx::SystemClock::now().universal_time();
+  GRNXX_NOTICE() << "grnxx::SystemClock::now().local_time(): "
+                 << grnxx::SystemClock::now().local_time();
+
+  enum { LOOP_COUNT = 1 << 16 };
 
+  grnxx::Time now = grnxx::SystemClock::now();
+
+  grnxx::Stopwatch stopwatch(true);
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    now.universal_time();
+  }
+  grnxx::Duration elapsed = stopwatch.elapsed();
+  GRNXX_NOTICE() << "grnxx::Time::universal_time(): average elapsed [ns] = "
+                 << (1000.0 * elapsed.count() / LOOP_COUNT);
+
+  stopwatch.reset();
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    now.local_time();
+  }
+  elapsed = stopwatch.elapsed();
+  GRNXX_NOTICE() << "grnxx::Time::local_time(): average elapsed [ns] = "
+                 << (1000.0 * elapsed.count() / LOOP_COUNT);
+}
+
+void test_system_clock() {
   grnxx::Time time = grnxx::SystemClock::now();
   GRNXX_NOTICE() << "grnxx::SystemClock::now(): " << time;
   GRNXX_NOTICE() << "grnxx::SystemClock::now().local_time(): "
@@ -45,6 +75,131 @@ int main() {
   grnxx::Duration elapsed = stopwatch.elapsed();
   GRNXX_NOTICE() << "grnxx::SystemClock::now: average elapsed [ns] = "
                  << (1000.0 * elapsed.count() / LOOP_COUNT);
+}
+
+void test_internal_clock() {
+  grnxx::Time time = grnxx::InternalClock::now();
+  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
+                 << time.local_time();
+
+  time = grnxx::InternalClock::now();
+  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
+                 << time.local_time();
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(310));
+
+  time = grnxx::InternalClock::now();
+  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
+                 << time.local_time();
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(310));
+
+  time = grnxx::InternalClock::now();
+  GRNXX_NOTICE() << "grnxx::InternalClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::InternalClock::now().local_time(): "
+                 << time.local_time();
+
+  enum { LOOP_COUNT = 1 << 20 };
+
+  grnxx::Stopwatch stopwatch(true);
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    grnxx::InternalClock::now();
+  }
+  grnxx::Duration elapsed = stopwatch.elapsed();
+  GRNXX_NOTICE() << "grnxx::InternalClock::now: average elapsed [ns] = "
+                 << (1000.0 * elapsed.count() / LOOP_COUNT);
+}
+
+void test_periodic_clock() {
+  grnxx::PeriodicClock clock;
+
+  grnxx::Time time = grnxx::PeriodicClock::now();
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now().local_time(): "
+                 << time.local_time();
+
+  time = grnxx::PeriodicClock::now();
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now().local_time(): "
+                 << time.local_time();
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(310));
+
+  time = grnxx::PeriodicClock::now();
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now().local_time(): "
+                 << time.local_time();
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(310));
+
+  time = grnxx::PeriodicClock::now();
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now(): " << time;
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now().local_time(): "
+                 << time.local_time();
+
+  enum { LOOP_COUNT = 1 << 20 };
+
+  grnxx::Stopwatch stopwatch(true);
+  for (int i = 0; i < LOOP_COUNT; ++i) {
+    grnxx::PeriodicClock::now();
+  }
+  grnxx::Duration elapsed = stopwatch.elapsed();
+  GRNXX_NOTICE() << "grnxx::PeriodicClock::now: average elapsed [ns] = "
+                 << (1000.0 * elapsed.count() / LOOP_COUNT);
+}
+
+void test_stopwatch() {
+  grnxx::Stopwatch stopwatch(false);
+  assert(stopwatch.elapsed() == grnxx::Duration(0));
+
+  stopwatch.start();
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  grnxx::Duration elapsed = stopwatch.elapsed();
+  assert(elapsed > grnxx::Duration(0));
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  assert(stopwatch.elapsed() > elapsed);
+
+  stopwatch.stop();
+  elapsed = stopwatch.elapsed();
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  assert(stopwatch.elapsed() == elapsed);
+
+  stopwatch.start();
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  assert(stopwatch.elapsed() > elapsed);
+
+  GRNXX_NOTICE() << "stopwatch.elapsed() = " << stopwatch.elapsed();
+
+  elapsed = stopwatch.elapsed();
+  stopwatch.reset();
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  assert(stopwatch.elapsed() < elapsed);
+  assert(stopwatch.elapsed() > grnxx::Duration(0));
+
+  stopwatch.stop();
+  stopwatch.reset();
+  assert(stopwatch.elapsed() == grnxx::Duration(0));
+
+  grnxx::Thread::sleep_for(grnxx::Duration::milliseconds(1));
+  assert(stopwatch.elapsed() == grnxx::Duration(0));
+}
+
+int main() {
+  grnxx::Logger::set_flags(grnxx::LOGGER_WITH_ALL |
+                           grnxx::LOGGER_ENABLE_COUT);
+  grnxx::Logger::set_max_level(grnxx::NOTICE_LOGGER);
+
+  test_time();
+  test_broken_down_time();
+  test_system_clock();
+  test_internal_clock();
+  test_periodic_clock();
+  test_stopwatch();
 
   return 0;
 }
-------------- next part --------------
HTML����������������������������...
다운로드 



More information about the Groonga-commit mailing list
Back to archive index