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