Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
BlockOrWakeUp.hxx
Go to the documentation of this file.
1
34#ifndef _FREERTOS_DRIVERS_COMMON_BLOCKORWAKEUP_HXX_
35#define _FREERTOS_DRIVERS_COMMON_BLOCKORWAKEUP_HXX_
36
37#include "os/OS.hxx"
39
65template <class Critical> class BlockOrWakeUp : protected Critical
66{
67public:
71 template <class T>
72 BlockOrWakeUp(const T &t)
73 : Critical(t)
74 , notifiable_(nullptr)
75 {
76 }
77
78 class LockHolder;
79 class CriticalHolder;
80 friend class LockHolder;
81 friend class CriticalHolder;
82
85 {
87 {
88 if (parent_)
89 parent_->unlock();
90 }
91
94 : parent_(o.parent_)
95 {
96 o.parent_ = nullptr;
97 }
98
99 private:
100 friend class LockHolder;
105 : parent_(parent)
106 {
107 parent_->lock();
108 }
109
112 };
113
117 {
121 : parent_(parent)
122 {
123 parent_->single_lock();
124 }
125
128 : parent_(o.parent_)
129 {
130 o.parent_ = nullptr;
131 }
132
134 {
135 if (parent_)
136 {
137 parent_->single_unlock();
138 }
139 }
140
143 CriticalHolder critical() __attribute__((warn_unused_result))
144 {
145 auto h = CriticalHolder(parent_);
146 return h;
147 }
148
152 {
153 parent_->single_unlock();
154 parent_->s_.wait();
155 parent_->single_lock();
156 }
157
160 {
161 parent_->s_.post();
162 Notifiable* n = nullptr;
163 if (parent_->notifiable_) {
164 n = parent_->notifiable_;
165 parent_->notifiable_ = nullptr;
166 }
167 parent_->single_unlock();
168 parent_ = nullptr;
169 if (n) n->notify();
170 }
171
172 private:
174
177 };
178
182 LockHolder holder() __attribute__((warn_unused_result)) {
183 return LockHolder(this);
184 }
185
189 {
190 int woken = 0;
191 s_.post_from_isr(&woken);
192 if (notifiable_) {
193 notifiable_->notify_from_isr();
194 notifiable_ = nullptr;
195 }
196 os_isr_exit_yield_test(true);
197 }
198
206 {
208 notifiable_ = n;
209 return r;
210 }
211
212private:
215 {
216 m_.lock();
217 }
220 {
221 m_.unlock();
222 }
223
230};
231
232#endif // _FREERTOS_DRIVERS_COMMON_BLOCKORWAKEUP_HXX_
A synchronization primitive for device drivers, where execution has to happen in an interrupt context...
OSSem s_
Semaphore used to wake up callers.
Notifiable * register_notifiable(Notifiable *n)
Sets the notifiable that will be called from the ISR (or regular) context when there is more data to ...
BlockOrWakeUp(const T &t)
Constructor.
LockHolder holder()
Acquires a lock (not critical) and returns an RAII holder object.
OSMutex m_
Mutex holding non-criticla lock.
void single_unlock()
Unlocks the mutex (not the critical).
Notifiable * notifiable_
Notifiable to be woken up when an ISR event happens.
void single_lock()
Locks the mutex (not the critical).
void notify_from_isr()
Called from ISR context to wake up a regular context or a caller waiting.
An object that can schedule itself on an executor to run.
virtual void notify()=0
Generic callback.
This class provides a mutex API.
Definition OS.hxx:427
void lock()
Lock a mutex.
Definition OS.hxx:446
void unlock()
Unlock a mutex.
Definition OS.hxx:453
This class provides a counting semaphore API.
Definition OS.hxx:243
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
RAII class for holding a critical section lock.
CriticalHolder(BlockOrWakeUp< Critical > *parent)
Upgrades a lock to a critical section.
CriticalHolder(CriticalHolder &&o)
Move constructor for the RAII object.
BlockOrWakeUp< Critical > * parent_
Pointer to parent.
RAII class for holding a mutex lock that can be upgraded to a critical section lock.
void wait_for_notification()
Waits for the core condition to be true (i.e.
LockHolder(LockHolder &&o)
Move constructor.
BlockOrWakeUp< Critical > * parent_
Parent object whose lock we are holding.
void notify_next()
Hands over the core condition to a next someone waiting in line.
LockHolder(BlockOrWakeUp< Critical > *parent)
Constructor.
CriticalHolder critical()
upgrades a regular lock to a critical section.