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/MessageQueue.hpp | 762 +++++++++++++++++++++++++++++++++++++
 1 file changed, 762 insertions(+)
 create mode 100644 include/distortos/MessageQueue.hpp

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

diff --git a/include/distortos/MessageQueue.hpp b/include/distortos/MessageQueue.hpp
new file mode 100644
index 0000000..0f44d8f
--- /dev/null
+++ b/include/distortos/MessageQueue.hpp
@@ -0,0 +1,762 @@
+/**
+ * \file
+ * \brief MessageQueue class header
+ *
+ * \author Copyright (C) 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_MESSAGEQUEUE_HPP_
+#define INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
+
+#include "distortos/internal/synchronization/MessageQueueBase.hpp"
+#include "distortos/internal/synchronization/BoundQueueFunctor.hpp"
+#include "distortos/internal/synchronization/CopyConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/MoveConstructQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SwapPopQueueFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitForFunctor.hpp"
+#include "distortos/internal/synchronization/SemaphoreTryWaitUntilFunctor.hpp"
+
+namespace distortos
+{
+
+/// GCC 4.9 is needed for all MessageQueue::*emplace*() functions - earlier versions don't support parameter pack
+/// expansion in lambdas
+#define DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED	__GNUC_PREREQ(4, 9)
+
+/**
+ * \brief MessageQueue class is a message queue for thread-thread, thread-interrupt or interrupt-interrupt
+ * communication. It supports multiple readers and multiple writers. It is implemented as a wrapper for
+ * internal::MessageQueueBase.
+ *
+ * Similar to POSIX mqd_t - http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html
+ *
+ * \tparam T is the type of data in queue
+ *
+ * \ingroup queues
+ */
+
+template<typename T>
+class MessageQueue
+{
+public:
+
+	/// type of uninitialized storage for Entry with link
+	using EntryStorage = internal::MessageQueueBase::EntryStorage;
+
+	/// type of uninitialized storage for value
+	using ValueStorage = internal::MessageQueueBase::ValueStorage<T>;
+
+	/// import EntryStorageUniquePointer type from internal::MessageQueueBase class
+	using EntryStorageUniquePointer = internal::MessageQueueBase::EntryStorageUniquePointer;
+
+	/// unique_ptr (with deleter) to ValueStorage[]
+	using ValueStorageUniquePointer =
+			std::unique_ptr<ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type>;
+
+	/**
+	 * \brief MessageQueue's constructor
+	 *
+	 * \param [in] entryStorageUniquePointer is a rvalue reference to EntryStorageUniquePointer with storage for queue
+	 * entries (sufficiently large for \a maxElements EntryStorage objects) and appropriate deleter
+	 * \param [in] valueStorageUniquePointer is a rvalue reference to ValueStorageUniquePointer with storage for queue
+	 * elements (sufficiently large for \a maxElements, each sizeof(T) bytes long) and appropriate deleter
+	 * \param [in] maxElements is the number of elements in \a entryStorage and \a valueStorage arrays
+	 */
+
+	MessageQueue(EntryStorageUniquePointer&& entryStorageUniquePointer,
+			ValueStorageUniquePointer&& valueStorageUniquePointer, const size_t maxElements) :
+			messageQueueBase_{std::move(entryStorageUniquePointer),
+					{valueStorageUniquePointer.release(), valueStorageUniquePointer.get_deleter()},
+					sizeof(*valueStorageUniquePointer.get()), maxElements}
+	{
+
+	}
+
+	/**
+	 * \brief MessageQueue's destructor
+	 *
+	 * Pops all remaining elements from the queue.
+	 */
+
+	~MessageQueue();
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Emplaces the element in the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::wait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename... Args>
+	int emplace(const uint8_t priority, Args&&... args)
+	{
+		const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+		return emplaceInternal(semaphoreWaitFunctor, priority, std::forward<Args>(args)...);
+	}
+
+#endif	// DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Pops oldest element with highest priority from the queue.
+	 *
+	 * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+	 *
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::wait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int pop(uint8_t& priority, T& value)
+	{
+		const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+		return popInternal(semaphoreWaitFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Pushes the element to the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::wait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int push(const uint8_t priority, const T& value)
+	{
+		const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+		return pushInternal(semaphoreWaitFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Pushes the element to the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::wait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int push(const uint8_t priority, T&& value)
+	{
+		const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
+		return pushInternal(semaphoreWaitFunctor, priority, std::move(value));
+	}
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Tries to emplace the element in the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename... Args>
+	int tryEmplace(const uint8_t priority, Args&&... args)
+	{
+		const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+		return emplaceInternal(semaphoreTryWaitFunctor, priority, std::forward<Args>(args)...);
+	}
+
+	/**
+	 * \brief Tries to emplace the element in the queue for a given duration of time.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename... Args>
+	int tryEmplaceFor(const TickClock::duration duration, const uint8_t priority, Args&&... args)
+	{
+		const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+		return emplaceInternal(semaphoreTryWaitForFunctor, priority, std::forward<Args>(args)...);
+	}
+
+	/**
+	 * \brief Tries to emplace the element in the queue for a given duration of time.
+	 *
+	 * Template variant of MessageQueue::tryEmplaceFor(TickClock::duration, uint8_t, Args&&...).
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] duration is the duration after which the wait will be terminated without emplacing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Rep, typename Period, typename... Args>
+	int tryEmplaceFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, Args&&... args)
+	{
+		return tryEmplaceFor(std::chrono::duration_cast<TickClock::duration>(duration), priority,
+				std::forward<Args>(args)...);
+	}
+
+	/**
+	 * \brief Tries to emplace the element in the queue until a given time point.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename... Args>
+	int tryEmplaceUntil(const TickClock::time_point timePoint, const uint8_t priority, Args&&... args)
+	{
+		const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+		return emplaceInternal(semaphoreTryWaitUntilFunctor, priority, std::forward<Args>(args)...);
+	}
+
+	/**
+	 * \brief Tries to emplace the element in the queue until a given time point.
+	 *
+	 * Template variant of FifoQueue::tryEmplaceUntil(TickClock::time_point, uint8_t, Args&&...).
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without emplacing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Duration, typename... Args>
+	int tryEmplaceUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+			Args&&... args)
+	{
+		return tryEmplaceUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority,
+				std::forward<Args>(args)...);
+	}
+
+#endif	// DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Tries to pop oldest element with highest priority from the queue.
+	 *
+	 * Similar to mq_receive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+	 *
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPop(uint8_t& priority, T& value)
+	{
+		const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+		return popInternal(semaphoreTryWaitFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to pop oldest element with highest priority from the queue for a given duration of time.
+	 *
+	 * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+	 *
+	 * \param [in] duration is the duration after which the call will be terminated without popping the element
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPopFor(const TickClock::duration duration, uint8_t& priority, T& value)
+	{
+		const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+		return popInternal(semaphoreTryWaitForFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to pop oldest element with highest priority from the queue for a given duration of time.
+	 *
+	 * Template variant of tryPopFor(TickClock::duration, uint8_t&, T&).
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 *
+	 * \param [in] duration is the duration after which the call will be terminated without popping the element
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Rep, typename Period>
+	int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, T& value)
+	{
+		return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
+	}
+
+	/**
+	 * \brief Tries to pop oldest element with highest priority from the queue until a given time point.
+	 *
+	 * Similar to mq_timedreceive() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html#
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPopUntil(const TickClock::time_point timePoint, uint8_t& priority, T& value)
+	{
+		const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+		return popInternal(semaphoreTryWaitUntilFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to pop oldest element with highest priority from the queue until a given time point.
+	 *
+	 * Template variant of tryPopUntil(TickClock::time_point, uint8_t&, T&).
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without popping the element
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Duration>
+	int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, T& value)
+	{
+		return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPush(const uint8_t priority, const T& value)
+	{
+		const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+		return pushInternal(semaphoreTryWaitFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue.
+	 *
+	 * Similar to mq_send() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWait();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPush(const uint8_t priority, T&& value)
+	{
+		const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
+		return pushInternal(semaphoreTryWaitFunctor, priority, std::move(value));
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue for a given duration of time.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPushFor(const TickClock::duration duration, const uint8_t priority, const T& value)
+	{
+		const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+		return pushInternal(semaphoreTryWaitForFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue for a given duration of time.
+	 *
+	 * Template variant of tryPushFor(TickClock::duration, uint8_t, const T&).
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 *
+	 * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Rep, typename Period>
+	int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const T& value)
+	{
+		return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue for a given duration of time.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] duration is the duration after which the wait will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPushFor(const TickClock::duration duration, const uint8_t priority, T&& value)
+	{
+		const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
+		return pushInternal(semaphoreTryWaitForFunctor, priority, std::move(value));
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue for a given duration of time.
+	 *
+	 * Template variant of tryPushFor(TickClock::duration, uint8_t, T&&).
+	 *
+	 * \tparam Rep is type of tick counter
+	 * \tparam Period is std::ratio type representing the tick period of the clock, in seconds
+	 *
+	 * \param [in] duration is the duration after which the call will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitFor();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Rep, typename Period>
+	int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, T&& value)
+	{
+		return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, std::move(value));
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue until a given time point.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, const T& value)
+	{
+		const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+		return pushInternal(semaphoreTryWaitUntilFunctor, priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue until a given time point.
+	 *
+	 * Template variant of tryPushUntil(TickClock::time_point, uint8_t, const T&).
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Duration>
+	int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
+			const T& value)
+	{
+		return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue until a given time point.
+	 *
+	 * Similar to mq_timedsend() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html#
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, T&& value)
+	{
+		const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
+		return pushInternal(semaphoreTryWaitUntilFunctor, priority, std::move(value));
+	}
+
+	/**
+	 * \brief Tries to push the element to the queue until a given time point.
+	 *
+	 * Template variant of tryPushUntil(TickClock::time_point, uint8_t, T&&).
+	 *
+	 * \tparam Duration is a std::chrono::duration type used to measure duration
+	 *
+	 * \param [in] timePoint is the time point at which the call will be terminated without pushing the element
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by Semaphore::tryWaitUntil();
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename Duration>
+	int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority, T&& value)
+	{
+		return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, std::move(value));
+	}
+
+private:
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Emplaces the element in the queue.
+	 *
+	 * Internal version - builds the Functor object.
+	 *
+	 * \note This function requires GCC 4.9.
+	 *
+	 * \tparam Args are types of arguments for constructor of T
+	 *
+	 * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+	 * \param [in] priority is the priority of new element
+	 * \param [in] args are arguments for constructor of T
+	 *
+	 * \return zero if element was emplaced successfully, error code otherwise:
+	 * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	template<typename... Args>
+	int emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, Args&&... args);
+
+#endif	// DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+	/**
+	 * \brief Pops oldest element with highest priority from the queue.
+	 *
+	 * Internal version - builds the Functor object.
+	 *
+	 * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a popSemaphore_
+	 * \param [out] priority is a reference to variable that will be used to return priority of popped value
+	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
+	 * with the value in the queue's storage and destructed when no longer needed
+	 *
+	 * \return zero if element was popped successfully, error code otherwise:
+	 * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value);
+
+	/**
+	 * \brief Pushes the element to the queue.
+	 *
+	 * Internal version - builds the Functor object.
+	 *
+	 * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const T& value);
+
+	/**
+	 * \brief Pushes the element to the queue.
+	 *
+	 * Internal version - builds the Functor object.
+	 *
+	 * \param [in] waitSemaphoreFunctor is a reference to SemaphoreFunctor which will be executed with \a pushSemaphore_
+	 * \param [in] priority is the priority of new element
+	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
+	 * move-constructed
+	 *
+	 * \return zero if element was pushed successfully, error code otherwise:
+	 * - error codes returned by \a waitSemaphoreFunctor's operator() call;
+	 * - error codes returned by Semaphore::post();
+	 */
+
+	int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, T&& value);
+
+	/// contained internal::MessageQueueBase object which implements whole functionality
+	internal::MessageQueueBase messageQueueBase_;
+};
+
+template<typename T>
+MessageQueue<T>::~MessageQueue()
+{
+	uint8_t priority;
+	T value;
+	while (tryPop(priority, value) == 0);
+}
+
+#if DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+template<typename... Args>
+int MessageQueue<T>::emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+		Args&&... args)
+{
+	const auto emplaceFunctor = internal::makeBoundQueueFunctor(
+			[&args...](void* const storage)
+			{
+				new (storage) T{std::forward<Args>(args)...};
+			});
+	return messageQueueBase_.push(waitSemaphoreFunctor, priority, emplaceFunctor);
+}
+
+#endif	// DISTORTOS_MESSAGEQUEUE_EMPLACE_SUPPORTED == 1 || DOXYGEN == 1
+
+template<typename T>
+int MessageQueue<T>::popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value)
+{
+	const internal::SwapPopQueueFunctor<T> swapPopQueueFunctor {value};
+	return messageQueueBase_.pop(waitSemaphoreFunctor, priority, swapPopQueueFunctor);
+}
+
+template<typename T>
+int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+		const T& value)
+{
+	const internal::CopyConstructQueueFunctor<T> copyConstructQueueFunctor {value};
+	return messageQueueBase_.push(waitSemaphoreFunctor, priority, copyConstructQueueFunctor);
+}
+
+template<typename T>
+int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
+		T&& value)
+{
+	const internal::MoveConstructQueueFunctor<T> moveConstructQueueFunctor {std::move(value)};
+	return messageQueueBase_.push(waitSemaphoreFunctor, priority, moveConstructQueueFunctor);
+}
+
+}	// namespace distortos
+
+#endif	// INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
-- 
cgit v1.2.3