Mercurial > code
changeset 536:f7af45aeb197
Timer: make header only, add tests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 07 Jun 2016 13:16:42 +0200 |
parents | 819a14133f2e |
children | 3831c92d3b1f |
files | CMakeLists.txt modules/timer/CMakeLists.txt modules/timer/test/main.cpp modules/timer/timer.cpp modules/timer/timer.hpp |
diffstat | 5 files changed, 138 insertions(+), 78 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Fri Jun 03 14:02:17 2016 +0200 +++ b/CMakeLists.txt Tue Jun 07 13:16:42 2016 +0200 @@ -52,6 +52,7 @@ add_subdirectory(modules/json) add_subdirectory(modules/net) add_subdirectory(modules/options) +add_subdirectory(modules/timer) add_subdirectory(modules/unicode) add_subdirectory(modules/xdg) # add_subdirectory(modules/zip)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/timer/CMakeLists.txt Tue Jun 07 13:16:42 2016 +0200 @@ -0,0 +1,22 @@ +# +# CMakeLists.txt -- code building for common code +# +# Copyright (c) 2016 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +code_define_module( + NAME timer + SOURCES timer.hpp +) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/timer/test/main.cpp Tue Jun 07 13:16:42 2016 +0200 @@ -0,0 +1,66 @@ +/* + * main.cpp -- test irccd timer + * + * Copyright (c) 2016 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <gtest/gtest.h> + +#include "timer.hpp" + +using namespace std::chrono_literals; + +TEST(Basic, repeat) +{ + Timer timer(Timer::Repeat, 500); + int max = 0; + + timer.setHandler([&] () { + max ++; + }); + timer.start(); + + // Should be at least 5 + std::this_thread::sleep_for(3s); + + ASSERT_GE(max, 5); +} + +TEST(Basic, restart) +{ + Timer timer(Timer::Repeat, 500); + int max = 0; + + timer.setHandler([&] () { + max ++; + }); + + timer.start(); + std::this_thread::sleep_for(3s); + timer.stop(); + std::this_thread::sleep_for(3s); + timer.start(); + std::this_thread::sleep_for(3s); + + ASSERT_GE(max, 10); + ASSERT_LT(max, 15); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}
--- a/modules/timer/timer.cpp Fri Jun 03 14:02:17 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * timer.cpp -- threaded timers - * - * Copyright (c) 2016 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <cassert> -#include <chrono> - -#include "timer.hpp" - -void Timer::call() -{ - if (m_alive && m_handler) - m_handler(); -} - -void Timer::wait() -{ - std::unique_lock<std::mutex> lock(m_mutex); - - m_condition.wait_for(lock, std::chrono::milliseconds(m_delay), [&] () { - return static_cast<bool>(!m_alive); - }); -} - -void Timer::runOne() -{ - wait(); - call(); -} - -void Timer::runForever() -{ - while (m_alive) { - wait(); - call(); - } -} - -void Timer::start() -{ - assert(!m_thread.joinable()); - - m_alive = true; - - if (m_type == Single) - m_thread = std::thread(std::bind(&Timer::runOne, this)); - else - m_thread = std::thread(std::bind(&Timer::runForever, this)); -} - -void Timer::stop() -{ - if (m_thread.joinable()) { - m_alive = false; - m_condition.notify_one(); - m_thread.join(); - } -} \ No newline at end of file
--- a/modules/timer/timer.hpp Fri Jun 03 14:02:17 2016 +0200 +++ b/modules/timer/timer.hpp Tue Jun 07 13:16:42 2016 +0200 @@ -25,7 +25,9 @@ */ #include <atomic> +#include <cassert> #include <condition_variable> +#include <chrono> #include <cstdint> #include <functional> #include <mutex> @@ -55,10 +57,34 @@ std::function<void ()> m_handler; std::uint32_t m_delay; - void call(); - void wait(); - void runOne(); - void runForever(); + inline void call() + { + if (m_alive && m_handler) + m_handler(); + } + + inline void wait() + { + std::unique_lock<std::mutex> lock(m_mutex); + + m_condition.wait_for(lock, std::chrono::milliseconds(m_delay), [&] () { + return static_cast<bool>(!m_alive); + }); + } + + inline void runOne() + { + wait(); + call(); + } + + inline void runForever() + { + while (m_alive) { + wait(); + call(); + } + } public: /** @@ -129,14 +155,31 @@ * * \pre the timer must not be running */ - void start(); + void start() + { + assert(!m_thread.joinable()); + + m_alive = true; + + if (m_type == Single) + m_thread = std::thread(std::bind(&Timer::runOne, this)); + else + m_thread = std::thread(std::bind(&Timer::runForever, this)); + } /** * Stop the timer. * * Can be safely called multiple times. */ - void stop(); + void stop() + { + if (m_thread.joinable()) { + m_alive = false; + m_condition.notify_one(); + m_thread.join(); + } + } }; #endif // !TIMER_HPP \ No newline at end of file