SuperTinyKernel™ RTOS 1.06.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_sync_event.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#ifndef STK_SYNC_EVENT_H_
11#define STK_SYNC_EVENT_H_
12
13#include "stk_sync_cs.h"
14
18
19namespace stk {
20namespace sync {
21
61class Event final : private ISyncObject, public ITraceable
62{
63public:
69 explicit Event(bool manual_reset = false, bool initial_state = false)
70 : m_manual_reset(manual_reset), m_signaled(initial_state)
71 {}
72
79 {
80 STK_ASSERT(m_wait_list.IsEmpty()); // API contract: must not be destroyed with waiting tasks
81 }
82
94 bool Set();
95
103 bool Reset();
104
111 bool Wait(Timeout timeout_ticks = WAIT_INFINITE);
112
121 bool TryWait();
122
132 void Pulse();
133
134private:
136
137 void RemoveWaitObject(IWaitObject *wobj) override;
138
141};
142
143// ---------------------------------------------------------------------------
144// Set
145// ---------------------------------------------------------------------------
146
147inline bool Event::Set()
148{
149 const ScopedCriticalSection cs_;
150 bool status = true;
151
152 if (m_signaled)
153 {
154 status = false;
155 }
156 else
157 {
158 m_signaled = true;
159 __stk_full_memfence();
160
161 if (m_manual_reset)
162 {
163 WakeAll();
164 }
165 else
166 {
167 WakeOne(); // auto-reset is applied in RemoveWaitObject when the waiter is removed
168 }
169 }
170
171 return status;
172}
173
174// ---------------------------------------------------------------------------
175// Reset
176// ---------------------------------------------------------------------------
177
178inline bool Event::Reset()
179{
180 const ScopedCriticalSection cs_;
181
182 const bool prev = m_signaled;
183
184 m_signaled = false;
185 __stk_full_memfence();
186
187 return prev;
188}
189
190// ---------------------------------------------------------------------------
191// Pulse
192// ---------------------------------------------------------------------------
193
194inline void Event::Pulse()
195{
196 const ScopedCriticalSection cs_;
197
198 // transition to signaled so that WakeOne/WakeAll can release waiters:
199 // m_signaled is only visible as true while this critical section is held —
200 // any woken task will have the event auto-reset in RemoveWaitObject before
201 // it can observe m_signaled via Wait() or TryWait()
202 m_signaled = true;
203 __stk_full_memfence();
204
205 if (!m_wait_list.IsEmpty())
206 {
207 if (m_manual_reset)
208 {
209 WakeAll();
210 }
211 else
212 {
213 WakeOne(); // auto-reset applied in RemoveWaitObject
214 }
215 }
216
217 // force return to non-signaled regardless of whether anyone was waiting
218 m_signaled = false;
219 __stk_full_memfence();
220}
221
222// ---------------------------------------------------------------------------
223// Wait
224// ---------------------------------------------------------------------------
225
226inline bool Event::Wait(Timeout timeout_ticks)
227{
228 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR
229
231 bool success = false;
232
233 // fast path: already signaled
234 if (m_signaled)
235 {
236 if (!m_manual_reset)
237 {
238 m_signaled = false;
239 __stk_full_memfence();
240 }
241
242 success = true;
243 }
244 // slow path: block until Set() signals the event or timeout expires
245 else if (timeout_ticks != NO_WAIT)
246 {
247 success = (IKernelService::GetInstance()->Wait(this, &cs_, timeout_ticks) == WAIT_RESULT_SIGNAL);
248 }
249 else
250 {
251 // non-blocking poll: event not signaled, return immediately
252 // success is already false, so noop
253 }
254
255 return success;
256}
257
258// ---------------------------------------------------------------------------
259// TryWait
260// ---------------------------------------------------------------------------
261
262inline bool Event::TryWait()
263{
264 const ScopedCriticalSection cs_;
265 bool result = false;
266
267 if (m_signaled)
268 {
269 if (!m_manual_reset)
270 {
271 m_signaled = false;
272 __stk_full_memfence();
273 }
274
275 result = true;
276 }
277
278 return result;
279}
280
281// ---------------------------------------------------------------------------
282// RemoveWaitObject
283// ---------------------------------------------------------------------------
284
286{
288
289 // kernel invariant: auto-reset is applied here, not at the Set()/Pulse() call site,
290 // when a task wakes due to a signal (not a timeout), the event transitions back to
291 // non-signaled so that subsequent Wait() calls block until the next Set().
293 {
294 if (!wobj->IsTimeout())
295 {
296 m_signaled = false;
297 __stk_full_memfence();
298 }
299 }
300}
301
302} // namespace sync
303} // namespace stk
304
305#endif /* STK_SYNC_EVENT_H_ */
#define STK_NONCOPYABLE_CLASS(TYPE)
Disables copy construction and assignment for a class.
Definition stk_defs.h:601
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:409
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:159
Implementation of synchronization primitive: stk::sync::ScopedCriticalSection.
Namespace of STK package.
constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:210
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:146
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:125
constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:204
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Synchronization primitives for task coordination and resource protection.
Wait object.
Definition stk_common.h:362
virtual bool IsTimeout() const =0
Check if task woke up due to a timeout.
Traceable object.
Definition stk_common.h:410
IWaitObject::ListHeadType m_wait_list
tasks blocked on this object
Definition stk_common.h:605
virtual void WakeOne()
Wake the first task in the wait list (FIFO order).
Definition stk_common.h:576
ISyncObject()
Constructor.
Definition stk_common.h:562
virtual void WakeAll()
Wake all tasks currently in the wait list.
Definition stk_common.h:591
static void RemoveWaitObject(IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
Called by kernel when a waiting task is being removed (timeout expired, wait aborted,...
Definition stk_common.h:494
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.
virtual EWaitResult Wait(ISyncObject *sobj, IMutex *mutex, Timeout timeout)=0
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Definition stk_sync_cs.h:54
~Event()
Destructor.
bool Set()
Set event to signaled state.
void Pulse()
Pulse event: attempt to release waiters and then reset (Win32 PulseEvent() semantics).
bool TryWait()
Poll event state without blocking.
bool Reset()
Reset event to non-signaled state.
bool Wait(Timeout timeout_ticks=WAIT_INFINITE)
Wait until event becomes signaled or the timeout expires.
bool m_signaled
current signaled state of the event
void RemoveWaitObject(IWaitObject *wobj) override
Called by kernel when a waiting task is being removed (timeout expired, wait aborted,...
Event(bool manual_reset=false, bool initial_state=false)
Constructor.
bool m_manual_reset
true = manual-reset event, false = auto-reset