distortos  v0.7.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 
57  using ValueType = T;
58 
61 
64  std::unique_ptr<ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type>;
65 
76  MessageQueue(EntryStorageUniquePointer&& entryStorageUniquePointer,
77  ValueStorageUniquePointer&& valueStorageUniquePointer, const size_t maxElements) :
78  messageQueueBase_{std::move(entryStorageUniquePointer),
79  {valueStorageUniquePointer.release(), valueStorageUniquePointer.get_deleter()},
80  sizeof(*valueStorageUniquePointer.get()), maxElements}
81  {
82 
83  }
84 
91  ~MessageQueue();
92 
112  template<typename... Args>
113  int emplace(const uint8_t priority, Args&&... args)
114  {
115  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
116  return emplaceInternal(semaphoreWaitFunctor, priority, std::forward<Args>(args)...);
117  }
118 
123  size_t getCapacity() const
124  {
126  }
127 
144  int pop(uint8_t& priority, T& value)
145  {
146  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
147  return popInternal(semaphoreWaitFunctor, priority, value);
148  }
149 
165  int push(const uint8_t priority, const T& value)
166  {
167  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
168  return pushInternal(semaphoreWaitFunctor, priority, value);
169  }
170 
187  int push(const uint8_t priority, T&& value)
188  {
189  const internal::SemaphoreWaitFunctor semaphoreWaitFunctor;
190  return pushInternal(semaphoreWaitFunctor, priority, std::move(value));
191  }
192 
210  template<typename... Args>
211  int tryEmplace(const uint8_t priority, Args&&... args)
212  {
213  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
214  return emplaceInternal(semaphoreTryWaitFunctor, priority, std::forward<Args>(args)...);
215  }
216 
237  template<typename... Args>
238  int tryEmplaceFor(const TickClock::duration duration, const uint8_t priority, Args&&... args)
239  {
240  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
241  return emplaceInternal(semaphoreTryWaitForFunctor, priority, std::forward<Args>(args)...);
242  }
243 
266  template<typename Rep, typename Period, typename... Args>
267  int tryEmplaceFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, Args&&... args)
268  {
269  return tryEmplaceFor(std::chrono::duration_cast<TickClock::duration>(duration), priority,
270  std::forward<Args>(args)...);
271  }
272 
293  template<typename... Args>
294  int tryEmplaceUntil(const TickClock::time_point timePoint, const uint8_t priority, Args&&... args)
295  {
296  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
297  return emplaceInternal(semaphoreTryWaitUntilFunctor, priority, std::forward<Args>(args)...);
298  }
299 
321  template<typename Duration, typename... Args>
322  int tryEmplaceUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
323  Args&&... args)
324  {
325  return tryEmplaceUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority,
326  std::forward<Args>(args)...);
327  }
328 
343  int tryPop(uint8_t& priority, T& value)
344  {
345  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
346  return popInternal(semaphoreTryWaitFunctor, priority, value);
347  }
348 
366  int tryPopFor(const TickClock::duration duration, uint8_t& priority, T& value)
367  {
368  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
369  return popInternal(semaphoreTryWaitForFunctor, priority, value);
370  }
371 
392  template<typename Rep, typename Period>
393  int tryPopFor(const std::chrono::duration<Rep, Period> duration, uint8_t& priority, T& value)
394  {
395  return tryPopFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
396  }
397 
415  int tryPopUntil(const TickClock::time_point timePoint, uint8_t& priority, T& value)
416  {
417  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
418  return popInternal(semaphoreTryWaitUntilFunctor, priority, value);
419  }
420 
440  template<typename Duration>
441  int tryPopUntil(const std::chrono::time_point<TickClock, Duration> timePoint, uint8_t& priority, T& value)
442  {
443  return tryPopUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
444  }
445 
459  int tryPush(const uint8_t priority, const T& value)
460  {
461  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
462  return pushInternal(semaphoreTryWaitFunctor, priority, value);
463  }
464 
479  int tryPush(const uint8_t priority, T&& value)
480  {
481  const internal::SemaphoreTryWaitFunctor semaphoreTryWaitFunctor;
482  return pushInternal(semaphoreTryWaitFunctor, priority, std::move(value));
483  }
484 
501  int tryPushFor(const TickClock::duration duration, const uint8_t priority, const T& value)
502  {
503  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
504  return pushInternal(semaphoreTryWaitForFunctor, priority, value);
505  }
506 
526  template<typename Rep, typename Period>
527  int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, const T& value)
528  {
529  return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, value);
530  }
531 
549  int tryPushFor(const TickClock::duration duration, const uint8_t priority, T&& value)
550  {
551  const internal::SemaphoreTryWaitForFunctor semaphoreTryWaitForFunctor {duration};
552  return pushInternal(semaphoreTryWaitForFunctor, priority, std::move(value));
553  }
554 
575  template<typename Rep, typename Period>
576  int tryPushFor(const std::chrono::duration<Rep, Period> duration, const uint8_t priority, T&& value)
577  {
578  return tryPushFor(std::chrono::duration_cast<TickClock::duration>(duration), priority, std::move(value));
579  }
580 
597  int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, const T& value)
598  {
599  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
600  return pushInternal(semaphoreTryWaitUntilFunctor, priority, value);
601  }
602 
621  template<typename Duration>
622  int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority,
623  const T& value)
624  {
625  return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, value);
626  }
627 
645  int tryPushUntil(const TickClock::time_point timePoint, const uint8_t priority, T&& value)
646  {
647  const internal::SemaphoreTryWaitUntilFunctor semaphoreTryWaitUntilFunctor {timePoint};
648  return pushInternal(semaphoreTryWaitUntilFunctor, priority, std::move(value));
649  }
650 
670  template<typename Duration>
671  int tryPushUntil(const std::chrono::time_point<TickClock, Duration> timePoint, const uint8_t priority, T&& value)
672  {
673  return tryPushUntil(std::chrono::time_point_cast<TickClock::duration>(timePoint), priority, std::move(value));
674  }
675 
676 private:
677 
696  template<typename... Args>
697  int emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, Args&&... args);
698 
714  int popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value);
715 
730  int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, const T& value);
731 
747  int pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t priority, T&& value);
748 
751 };
752 
753 template<typename T>
755 {
756  uint8_t priority;
757  T value;
758  while (tryPop(priority, value) == 0);
759 }
760 
761 template<typename T>
762 template<typename... Args>
763 int MessageQueue<T>::emplaceInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
764  Args&&... args)
765 {
766  const auto emplaceFunctor = internal::makeBoundQueueFunctor(
767  [&args...](void* const storage)
768  {
769  new (storage) T{std::forward<Args>(args)...};
770  });
771  return messageQueueBase_.push(waitSemaphoreFunctor, priority, emplaceFunctor);
772 }
773 
774 template<typename T>
775 int MessageQueue<T>::popInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, uint8_t& priority, T& value)
776 {
777  const internal::SwapPopQueueFunctor<T> swapPopQueueFunctor {value};
778  return messageQueueBase_.pop(waitSemaphoreFunctor, priority, swapPopQueueFunctor);
779 }
780 
781 template<typename T>
782 int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
783  const T& value)
784 {
785  const internal::CopyConstructQueueFunctor<T> copyConstructQueueFunctor {value};
786  return messageQueueBase_.push(waitSemaphoreFunctor, priority, copyConstructQueueFunctor);
787 }
788 
789 template<typename T>
790 int MessageQueue<T>::pushInternal(const internal::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
791  T&& value)
792 {
793  const internal::MoveConstructQueueFunctor<T> moveConstructQueueFunctor {std::move(value)};
794  return messageQueueBase_.push(waitSemaphoreFunctor, priority, moveConstructQueueFunctor);
795 }
796 
797 } // namespace distortos
798 
799 #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:441
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:501
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:165
int tryPop(uint8_t &priority, T &value)
Tries to pop oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:343
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:322
int emplaceInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t priority, Args &&... args)
Emplaces the element in the queue.
Definition: MessageQueue.hpp:763
size_t getCapacity() const
Definition: MessageQueue.hpp:123
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:393
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:366
int tryPush(const uint8_t priority, T &&value)
Tries to push the element to the queue.
Definition: MessageQueue.hpp:479
SemaphoreTryWaitFunctor class is a SemaphoreFunctor which calls Semaphore::tryWait()
Definition: SemaphoreTryWaitFunctor.hpp:24
~MessageQueue()
MessageQueue's destructor.
Definition: MessageQueue.hpp:754
MessageQueueBase class implements basic functionality of MessageQueue template class.
Definition: MessageQueueBase.hpp:31
size_t getCapacity() const
Definition: MessageQueueBase.hpp:151
internal::MessageQueueBase::ValueStorage< T > 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:187
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:645
int emplace(const uint8_t priority, Args &&... args)
Emplaces the element in the queue.
Definition: MessageQueue.hpp:113
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:238
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:549
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:267
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:597
Definition: SemaphoreTryWaitUntilFunctor.hpp:27
Definition: SwapPopQueueFunctor.hpp:32
CopyConstructQueueFunctor class header.
T ValueType
type of data in queue
Definition: MessageQueue.hpp:57
int popInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t &priority, T &value)
Pops oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:775
BoundQueueFunctor class header.
int tryPush(const uint8_t priority, const T &value)
Tries to push the element to the queue.
Definition: MessageQueue.hpp:459
std::unique_ptr< ValueStorage[], internal::MessageQueueBase::ValueStorageUniquePointer::deleter_type > ValueStorageUniquePointer
unique_ptr (with deleter) to ValueStorage[]
Definition: MessageQueue.hpp:64
Top-level namespace of distortos project.
Definition: buttons.hpp:33
Definition: CopyConstructQueueFunctor.hpp:30
internal::MessageQueueBase messageQueueBase_
contained internal::MessageQueueBase object which implements whole functionality
Definition: MessageQueue.hpp:750
int pop(uint8_t &priority, T &value)
Pops oldest element with highest priority from the queue.
Definition: MessageQueue.hpp:144
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:576
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:527
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:294
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:671
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:622
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:415
internal::MessageQueueBase::EntryStorageUniquePointer EntryStorageUniquePointer
import EntryStorageUniquePointer type from internal::MessageQueueBase class
Definition: MessageQueue.hpp:60
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's constructor.
Definition: MessageQueue.hpp:76
int tryEmplace(const uint8_t priority, Args &&... args)
Tries to emplace the element in the queue.
Definition: MessageQueue.hpp:211
int pushInternal(const internal::SemaphoreFunctor &waitSemaphoreFunctor, uint8_t priority, const T &value)
Pushes the element to the queue.
Definition: MessageQueue.hpp:782
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