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����������������������������... 다운로드