From 92235fb259b0ebdfc99859c2c95fe1f8c163f411 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <tullivan99@gmail.com>
Date: Tue, 8 Nov 2016 20:09:05 -0500
Subject: trying out distortos

---
 include/distortos/ConditionVariable.hpp | 304 ++++++++++++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 include/distortos/ConditionVariable.hpp

(limited to 'include/distortos/ConditionVariable.hpp')

diff --git a/include/distortos/ConditionVariable.hpp b/include/distortos/ConditionVariable.hpp
new file mode 100644
index 0000000..6b7f869
--- /dev/null
+++ b/include/distortos/ConditionVariable.hpp
@@ -0,0 +1,304 @@
+/**
+ * \file
+ * \brief ConditionVariable class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
+#define INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
+
+#include "distortos/internal/scheduler/ThreadList.hpp"
+
+#include "distortos/TickClock.hpp"
+
+namespace distortos
+{
+
+class Mutex;
+
+/**
+ * \brief ConditionVariable is an advanced synchronization primitive
+ *
+ * Similar to std::condition_variable - http://en.cppreference.com/w/cpp/thread/condition_variable
+ * Similar to POSIX pthread_cond_t
+ *
+ * \ingroup synchronization
+ */
+
+class ConditionVariable
+{
+public:
+
+	/**
+	 * \brief ConditionVariable constructor
+	 *
+	 * Similar to std::condition_variable::condition_variable() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/condition_variable
+	 * Similar to pthread_cond_init() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_init.html
+	 */
+
+	constexpr ConditionVariable() :
+			blockedList_{}
+	{
+
+	}
+
+	/**
+	 * \brief Notifies all waiting threads.
+	 *
+	 * Similar to std::condition_variable::notify_all() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
+	 * Similar to pthread_cond_broadcast() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html
+	 *
+	 * Unblocks all threads waiting on this condition variable. The notifying thread does not need to hold the same
+	 * mutex as the one held by the waiting thread(s).
+	 */
+
+	void notifyAll();
+
+	/**
+	 * \brief Notifies one waiting thread.
+	 *
+	 * Similar to std::condition_variable::notify_one() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/notify_one
+	 * Similar to pthread_cond_signal() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html
+	 *
+	 * Unblocks one thread waiting on this condition variable. The notifying thread does not need to hold the same
+	 * mutex as the one held by the waiting thread(s).
+	 */
+
+	void notifyOne();
+
+	/**
+	 * \brief Waits for notification.
+	 *
+	 * Similar to std::condition_variable::wait() - http://en.cppreference.com/w/cpp/thread/condition_variable/wait
+	 * Similar to pthread_cond_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html
+	 *
+	 * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+	 * will be unblocked when notifyAll() or notifyOne() is executed. It may also be unblocked spuriously. When
+	 * unblocked, regardless of the reason, lock is reacquired and wait exits.
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 */
+
+	int wait(Mutex& mutex);
+
+	/**
+	 * \brief Waits for predicate to become true.
+	 *
+	 * Similar to std::condition_variable::wait() - http://en.cppreference.com/w/cpp/thread/condition_variable/wait
+	 * Similar to pthread_cond_wait() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html
+	 *
+	 * Overload for wait() which also checks the predicate. This function will return only if the predicate is true.
+	 *
+	 * \tparam Predicate is a type of functor to check the predicate
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] predicate is the predicate that will be checked
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 */
+
+	template<typename Predicate>
+	int wait(Mutex& mutex, Predicate predicate);
+
+	/**
+	 * \brief Waits for notification for given duration of time.
+	 *
+	 * Similar to std::condition_variable::wait_for() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+	 * will be unblocked when notifyAll() or notifyOne() is executed or when given duration of time expires. It may also
+	 * be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits.
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] duration is the duration after which the wait for notification will be terminated
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	int waitFor(Mutex& mutex, TickClock::duration duration);
+
+	/**
+	 * \brief Waits for notification for given duration of time.
+	 *
+	 * Similar to std::condition_variable::wait_for() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Template variant of waitFor(Mutex& mutex, TickClock::duration duration).
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] duration is the duration after which the wait for notification will be terminated
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	template<typename Rep, typename Period>
+	int waitFor(Mutex& mutex, const std::chrono::duration<Rep, Period> duration)
+	{
+		return waitFor(mutex, std::chrono::duration_cast<TickClock::duration>(duration));
+	}
+
+	/**
+	 * \brief Waits for predicate to become true for given duration of time.
+	 *
+	 * Similar to std::condition_variable::wait_for() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Overload for waitFor() which also checks the predicate. This function will return only if the predicate is true
+	 * or when given duration of time expires.
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 * \tparam Predicate is a type of functor to check the predicate
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] duration is the duration after which the wait for notification will be terminated
+	 * \param [in] predicate is the predicate that will be checked
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	template<typename Rep, typename Period, typename Predicate>
+	int waitFor(Mutex& mutex, const std::chrono::duration<Rep, Period> duration, Predicate predicate)
+	{
+		return waitUntil(mutex, TickClock::now() + duration + TickClock::duration{1}, std::move(predicate));
+	}
+
+	/**
+	 * \brief Waits for notification until given time point.
+	 *
+	 * Similar to std::condition_variable::wait_until() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Atomically releases supplied mutex and blocks current thread until the condition variable is notified. The thread
+	 * will be unblocked when notifyAll() or notifyOne() is executed or when given time point is reached. It may also be
+	 * unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits.
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] timePoint is the time point at which the wait for notification will be terminated
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	int waitUntil(Mutex& mutex, TickClock::time_point timePoint);
+
+	/**
+	 * \brief Waits for notification until given time point.
+	 *
+	 * Similar to std::condition_variable::wait_until() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Template variant of waitUntil(Mutex& mutex, TickClock::time_point timePoint).
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] timePoint is the time point at which the wait for notification will be terminated
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	template<typename Duration>
+	int waitUntil(Mutex& mutex, const std::chrono::time_point<TickClock, Duration> timePoint)
+	{
+		return waitUntil(mutex, std::chrono::time_point_cast<TickClock::duration>(timePoint));
+	}
+
+	/**
+	 * \brief Waits for predicate to become true until given time point.
+	 *
+	 * Similar to std::condition_variable::wait_until() -
+	 * http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
+	 * Similar to pthread_cond_timedwait() -
+	 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
+	 *
+	 * Overload for waitUntil() which also checks the predicate. This function will return only if the predicate is true
+	 * or when given time point is reached.
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 * \tparam Predicate is a type of functor to check the predicate
+	 *
+	 * \param [in] mutex is a reference to mutex which must be owned by calling thread
+	 * \param [in] timePoint is the time point at which the wait for notification will be terminated
+	 * \param [in] predicate is the predicate that will be checked
+	 *
+	 * \return zero if the wait was completed successfully, error code otherwise:
+	 * - EPERM - the mutex type is ErrorChecking or Recursive, and the current thread does not own the mutex;
+	 * - ETIMEDOUT - no notification was received before the specified timeout expired;
+	 */
+
+	template<typename Duration, typename Predicate>
+	int waitUntil(Mutex& mutex, std::chrono::time_point<TickClock, Duration> timePoint, Predicate predicate);
+
+private:
+
+	/// ThreadControlBlock objects blocked on this condition variable
+	internal::ThreadList blockedList_;
+};
+
+template<typename Predicate>
+int ConditionVariable::wait(Mutex& mutex, Predicate predicate)
+{
+	while (predicate() == false)
+	{
+		const auto ret = wait(mutex);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+template<typename Duration, typename Predicate>
+int ConditionVariable::waitUntil(Mutex& mutex, const std::chrono::time_point<TickClock, Duration> timePoint, Predicate predicate)
+{
+	while (predicate() == false)
+	{
+		const auto ret = waitUntil(mutex, timePoint);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+}	// namespace distortos
+
+#endif	// INCLUDE_DISTORTOS_CONDITIONVARIABLE_HPP_
-- 
cgit v1.2.3