distortos  v0.5.0
object-oriented C++ RTOS for microcontrollers
MessageQueue.hpp
Go to the documentation of this file.
1 
12 #ifndef INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
13 #define INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
14 
24 
25 #if __GNUC_PREREQ(5, 1) != 1
26 // GCC 4.8 doesn't support parameter pack expansion in lambdas
27 #error "GCC 5.1 is the minimum version supported by distortos"
28 #endif
29 
30 namespace distortos
31 {
32 
45 template<typename T>
47 {
48 public:
49 
52 
55 
58 
61  std::unique_ptr<ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type>;
62 
73  MessageQueue(EntryStorageUniquePointer&& entryStorageUniquePointer,
74  ValueStorageUniquePointer&& valueStorageUniquePointer, const size_t maxElements) :
75  messageQueueBase_{std::move(entryStorageUniquePointer),
76  {valueStorageUniquePointer.release(), valueStorageUniquePointer.get_deleter()},
77  sizeof(*valueStorageUniquePointer.get()), maxElements}
78  {
79 
80  }
81 
88  ~MessageQueue();
89 
109  template<typename... Args>
110  int emplace(const uint8_t priority, Args&&... args)
111  {
112  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
113  return emplaceInternal(semaphoreWaitFunctor, priority, std::forward<Args>(args)...);
114  }
115 
132  int pop(uint8_t& priority, T& value)
133  {
134  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
135  return popInternal(semaphoreWaitFunctor, priority, value);
136  }
137 
153  int push(const uint8_t priority, const T& value)
154  {
155  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
156  return pushInternal(semaphoreWaitFunctor, priority, value);
157  }
158 
175  int push(const uint8_t priority, T&& value)
176  {
177  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
178  return pushInternal(semaphoreWaitFunctor, priority, std::move(value));
179  }
180 
198  template<typename... Args>
199  int tryEmplace(const uint8_t priority, Args&&... args)
200  {
201  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
202  return emplaceInternal(semaphoreTryWaitFunctor, priority, std::forward<Args>(args)...);
203  }
204 
225  template<typename... Args>
226  int tryEmplaceFor(const TickClock::duration duration, const uint8_t priority, Args&&... args)
227  {
228  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
229  return emplaceInternal(semaphoreTryWaitForFunctor, priority, std::forward<Args>(args)...);
230  }
231 
254  template<typename Rep, typename Period, typename... Args>
255  int tryEmplaceFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, Args&&... args)
256  {
257  return tryEmplaceFor(std::chrono::duration_cast<TickClock::duration>(duration), priority,
258  std::forward<Args>(args)...);
259  }
260 
281  template<typename... Args>
282  int tryEmplaceUntil(const TickClock::time_point timePoint, const uint8_t priority, Args&&... args)
283  {
284  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
285  return emplaceInternal(semaphoreTryWaitUntilFunctor, priority, std::forward<Args>(args)...);
286  }
287 
309  template<typename Duration, typename... Args>
310  int tryEmplaceUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
311  Args&&... args)
312  {
313  return tryEmplaceUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority,
314  std::forward<Args>(args)...);
315  }
316 
331  int tryPop(uint8_t& priority, T& value)
332  {
333  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
334  return popInternal(semaphoreTryWaitFunctor, priority, value);
335  }
336 
354  int tryPopFor(const TickClock::duration duration, uint8_t& priority, T& value)
355  {
356  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
357  return popInternal(semaphoreTryWaitForFunctor, priority, value);
358  }
359 
380  template<typename Rep, typename Period>
381  int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, T& value)
382  {
383  return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
384  }
385 
403  int tryPopUntil(const TickClock::time_point timePoint, uint8_t& priority, T& value)
404  {
405  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
406  return popInternal(semaphoreTryWaitUntilFunctor, priority, value);
407  }
408 
428  template<typename Duration>
429  int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, T& value)
430  {
431  return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
432  }
433 
447  int tryPush(const uint8_t priority, const T& value)
448  {
449  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
450  return pushInternal(semaphoreTryWaitFunctor, priority, value);
451  }
452 
467  int tryPush(const uint8_t priority, T&& value)
468  {
469  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
470  return pushInternal(semaphoreTryWaitFunctor, priority, std::move(value));
471  }
472 
489  int tryPushFor(const TickClock::duration duration, const uint8_t priority, const T& value)
490  {
491  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
492  return pushInternal(semaphoreTryWaitForFunctor, priority, value);
493  }
494 
514  template<typename Rep, typename Period>
515  int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const T& value)
516  {
517  return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
518  }
519 
537  int tryPushFor(const TickClock::duration duration, const uint8_t priority, T&& value)
538  {
539  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
540  return pushInternal(semaphoreTryWaitForFunctor, priority, std::move(value));
541  }
542 
563  template<typename Rep, typename Period>
564  int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, T&& value)
565  {
566  return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, std::move(value));
567  }
568 
585  int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, const T& value)
586  {
587  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
588  return pushInternal(semaphoreTryWaitUntilFunctor, priority, value);
589  }
590 
609  template<typename Duration>
610  int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
611  const T& value)
612  {
613  return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
614  }
615 
633  int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, T&& value)
634  {
635  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
636  return pushInternal(semaphoreTryWaitUntilFunctor, priority, std::move(value));
637  }
638 
658  template<typename Duration>
659  int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority, T&& value)
660  {
661  return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, std::move(value));
662  }
663 
664 private:
665 
684  template<typename... Args>
685  int emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, Args&&... args);
686 
702  int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value);
703 
718  int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const T& value);
719 
735  int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, T&& value);
736 
739 };
740 
741 template<typename T>
743 {
744  uint8_t priority;
745  T value;
746  while (tryPop(priority, value) == 0);
747 }
748 
749 template<typename T>
750 template<typename... Args>
751 int MessageQueue<T>::emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
752  Args&&... args)
753 {
754  const auto emplaceFunctor = internal::makeBoundQueueFunctor(
755  [&args...](void* const storage)
756  {
757  new (storage) T{std::forward<Args>(args)...};
758  });
759  return messageQueueBase_.push(waitSemaphoreFunctor, priority, emplaceFunctor);
760 }
761 
762 template<typename T>
763 int MessageQueue<T>::popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value)
764 {
765  const internal::SwapPopQueueFunctor<T> swapPopQueueFunctor {value};
766  return messageQueueBase_.pop(waitSemaphoreFunctor, priority, swapPopQueueFunctor);
767 }
768 
769 template<typename T>
770 int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
771  const T& value)
772 {
773  const internal::CopyConstructQueueFunctor<T> copyConstructQueueFunctor {value};
774  return messageQueueBase_.push(waitSemaphoreFunctor, priority, copyConstructQueueFunctor);
775 }
776 
777 template<typename T>
778 int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
779  T&& value)
780 {
781  const internal::MoveConstructQueueFunctor<T> moveConstructQueueFunctor {std::move(value)};
782  return messageQueueBase_.push(waitSemaphoreFunctor, priority, moveConstructQueueFunctor);
783 }
784 
785 } // namespace distortos
786 
787 #endif // INCLUDE_DISTORTOS_MESSAGEQUEUE_HPP_
int tryPopUntil(const std::chrono::time_point< TickClock, Duration > timePoint, uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue until a given time point...
Definition: MessageQueue.hpp:429
int tryPushFor(const TickClock::duration duration, const uint8_t priority, const T &value)
Tries to push the element to the queue for a given duration of time.
Definition: MessageQueue.hpp:489
constexpr BoundQueueFunctor< F > makeBoundQueueFunctor(F &&boundFunctor)
Helper factory function to make BoundQueueFunctor object with deduced template arguments.
Definition: BoundQueueFunctor.hpp:79
int push(const uint8_t priority, const T &value)
Pushes the element to the queue.
Definition: MessageQueue.hpp:153
int pop(const SemaphoreFunctor &waitSemaphoreFunctor, uint8_t &priority, const QueueFunctor &functor)
Implementation of pop() using type-erased functor.
Definition: MessageQueueBase.cpp:157
int tryPop(uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:331
SemaphoreTryWaitFunctor class header.
int tryEmplaceUntil(const std::chrono::time_point< TickClock, Duration > timePoint, const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue until a given time point.
Definition: MessageQueue.hpp:310
int emplaceInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t priority, Args &&... args)
Emplaces the element in the queue.
Definition: MessageQueue.hpp:751
int tryPopFor(const std::chrono::duration< Rep, Period > duration, uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue for a given duration of time...
Definition: MessageQueue.hpp:381
MessageQueue class is a message queue for thread-thread, thread-interrupt or interrupt-interrupt comm...
Definition: MessageQueue.hpp:46
int tryPopFor(const TickClock::duration duration, uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue for a given duration of time...
Definition: MessageQueue.hpp:354
int tryPush(const uint8_t priority, T &&value)
Tries to push the element to the queue.
Definition: MessageQueue.hpp:467
SemaphoreTryWaitFunctor class is a SemaphoreFunctor which calls Semaphore::tryWait() ...
Definition: SemaphoreTryWaitFunctor.hpp:24
~MessageQueue()
MessageQueue&#39;s destructor.
Definition: MessageQueue.hpp:742
int push(const SemaphoreFunctor &waitSemaphoreFunctor, uint8_t priority, const QueueFunctor &functor)
Implementation of push() using type-erased functor.
Definition: MessageQueueBase.cpp:163
MessageQueueBase class implements basic functionality of MessageQueue template class.
Definition: MessageQueueBase.hpp:31
internal::MessageQueueBase::ValueStorage< OperationCountingType > ValueStorage
type of uninitialized storage for value
Definition: MessageQueue.hpp:54
int push(const uint8_t priority, T &&value)
Pushes the element to the queue.
Definition: MessageQueue.hpp:175
int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, T &&value)
Tries to push the element to the queue until a given time point.
Definition: MessageQueue.hpp:633
int emplace(const uint8_t priority, Args &&... args)
Emplaces the element in the queue.
Definition: MessageQueue.hpp:110
std::chrono::time_point< TickClock > time_point
basic time_point type of clock
Definition: TickClock.hpp:42
int tryEmplaceFor(const TickClock::duration duration, const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue for a given duration of time.
Definition: MessageQueue.hpp:226
int tryPushFor(const TickClock::duration duration, const uint8_t priority, T &&value)
Tries to push the element to the queue for a given duration of time.
Definition: MessageQueue.hpp:537
int tryEmplaceFor(const std::chrono::duration< Rep, Period > duration, const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue for a given duration of time.
Definition: MessageQueue.hpp:255
SemaphoreTryWaitUntilFunctor class header.
int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, const T &value)
Tries to push the element to the queue until a given time point.
Definition: MessageQueue.hpp:585
Definition: SemaphoreTryWaitUntilFunctor.hpp:27
Definition: SwapPopQueueFunctor.hpp:32
CopyConstructQueueFunctor class header.
int popInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t &priority, T &value)
Pops oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:763
BoundQueueFunctor class header.
int tryPush(const uint8_t priority, const T &value)
Tries to push the element to the queue.
Definition: MessageQueue.hpp:447
std::unique_ptr< ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type > ValueStorageUniquePointer
unique_ptr (with deleter) to ValueStorage[]
Definition: MessageQueue.hpp:61
Top-level namespace of distortos project.
Definition: CopyConstructQueueFunctor.hpp:30
internal::MessageQueueBase messageQueueBase_
contained internal::MessageQueueBase object which implements whole functionality
Definition: MessageQueue.hpp:738
int pop(uint8_t &priority, T &value)
Pops oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:132
internal::MessageQueueBase::EntryStorage EntryStorage
type of uninitialized storage for Entry with link
Definition: MessageQueue.hpp:51
typename std::aligned_storage< sizeof(T), alignof(T)>::type ValueStorage
Definition: MessageQueueBase.hpp:76
MessageQueueBase class header.
int tryPushFor(const std::chrono::duration< Rep, Period > duration, const uint8_t priority, T &&value)
Tries to push the element to the queue for a given duration of time.
Definition: MessageQueue.hpp:564
int tryPushFor(const std::chrono::duration< Rep, Period > duration, const uint8_t priority, const T &value)
Tries to push the element to the queue for a given duration of time.
Definition: MessageQueue.hpp:515
SemaphoreFunctor is a type-erased interface for functors which execute some action on semaphore (wait...
Definition: SemaphoreFunctor.hpp:34
SemaphoreTryWaitForFunctor class header.
std::chrono::duration< rep, period > duration
basic duration type of clock
Definition: TickClock.hpp:39
SwapPopQueueFunctor class header.
int tryEmplaceUntil(const TickClock::time_point timePoint, const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue until a given time point.
Definition: MessageQueue.hpp:282
int tryPushUntil(const std::chrono::time_point< TickClock, Duration > timePoint, const uint8_t priority, T &&value)
Tries to push the element to the queue until a given time point.
Definition: MessageQueue.hpp:659
int tryPushUntil(const std::chrono::time_point< TickClock, Duration > timePoint, const uint8_t priority, const T &value)
Tries to push the element to the queue until a given time point.
Definition: MessageQueue.hpp:610
std::unique_ptr< EntryStorage[], void(&)(EntryStorage *)> EntryStorageUniquePointer
unique_ptr (with deleter) to EntryStorage[]
Definition: MessageQueueBase.hpp:67
int tryPopUntil(const TickClock::time_point timePoint, uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue until a given time point...
Definition: MessageQueue.hpp:403
internal::MessageQueueBase::EntryStorageUniquePointer EntryStorageUniquePointer
import EntryStorageUniquePointer type from internal::MessageQueueBase class
Definition: MessageQueue.hpp:57
SemaphoreWaitFunctor class header.
typename std::aligned_storage< sizeof(Entry), alignof(Entry)>::type EntryStorage
type of uninitialized storage for Entry
Definition: MessageQueueBase.hpp:64
MessageQueue(EntryStorageUniquePointer &&entryStorageUniquePointer, ValueStorageUniquePointer &&valueStorageUniquePointer, const size_t maxElements)
MessageQueue&#39;s constructor.
Definition: MessageQueue.hpp:73
int tryEmplace(const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue.
Definition: MessageQueue.hpp:199
int pushInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t priority, const T &value)
Pushes the element to the queue.
Definition: MessageQueue.hpp:770
MoveConstructQueueFunctor class header.
SemaphoreTryWaitForFunctor class is a SemaphoreFunctor which calls Semaphore::tryWaitFor() with bound...
Definition: SemaphoreTryWaitForFunctor.hpp:26
SemaphoreWaitFunctor class is a SemaphoreFunctor which calls Semaphore::wait()
Definition: SemaphoreWaitFunctor.hpp:24
Definition: MoveConstructQueueFunctor.hpp:32