SuperTinyKernel™ RTOS 1.08.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 SyncObjectBase, 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
113 EWaitResult WaitEx(Timeout timeout_ticks = WAIT_INFINITE);
114
122 bool Wait(Timeout timeout_ticks = WAIT_INFINITE) { return (WaitEx(timeout_ticks) == WAIT_RESULT_SIGNAL); }
123
132 bool TryWait();
133
143 void Pulse();
144
145private:
147
148 void RemoveWaitObject(IWaitObject *wobj) override;
149
152};
153
154// ---------------------------------------------------------------------------
155// Set
156// ---------------------------------------------------------------------------
157
158inline bool Event::Set()
159{
160 const ScopedCriticalSection cs_;
161 bool status = true;
162
163 if (m_signaled)
164 {
165 status = false;
166 }
167 else
168 {
169 m_signaled = true;
170 __stk_full_memfence();
171
172 if (m_manual_reset)
173 {
174 WakeAll();
175 }
176 else
177 {
178 WakeOne(); // auto-reset is applied in RemoveWaitObject when the waiter is removed
179 }
180 }
181
182 return status;
183}
184
185// ---------------------------------------------------------------------------
186// Reset
187// ---------------------------------------------------------------------------
188
189inline bool Event::Reset()
190{
191 const ScopedCriticalSection cs_;
192
193 const bool prev = m_signaled;
194
195 m_signaled = false;
196 __stk_full_memfence();
197
198 return prev;
199}
200
201// ---------------------------------------------------------------------------
202// Pulse
203// ---------------------------------------------------------------------------
204
205inline void Event::Pulse()
206{
207 const ScopedCriticalSection cs_;
208
209 // transition to signaled so that WakeOne/WakeAll can release waiters:
210 // m_signaled is only visible as true while this critical section is held —
211 // any woken task will have the event auto-reset in RemoveWaitObject before
212 // it can observe m_signaled via Wait() or TryWait()
213 m_signaled = true;
214 __stk_full_memfence();
215
216 if (!m_wait_list.IsEmpty())
217 {
218 if (m_manual_reset)
219 {
220 WakeAll();
221 }
222 else
223 {
224 WakeOne(); // auto-reset applied in RemoveWaitObject
225 }
226 }
227
228 // force return to non-signaled regardless of whether anyone was waiting
229 m_signaled = false;
230 __stk_full_memfence();
231}
232
233// ---------------------------------------------------------------------------
234// Wait
235// ---------------------------------------------------------------------------
236
237inline EWaitResult Event::WaitEx(Timeout timeout_ticks)
238{
240
241 // NO_WAIT on a non-signaled event is reported as an immediately-expired timeout
243
244 // fast path: already signaled
245 if (m_signaled)
246 {
247 if (!m_manual_reset)
248 {
249 m_signaled = false;
250 __stk_full_memfence();
251 }
252
253 result = WAIT_RESULT_SIGNAL;
254 }
255 // slow path: block until Set() signals the event or timeout expires
256 else if (timeout_ticks != NO_WAIT)
257 {
258 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR if timeout_ticks!=NO_WAIT
259
260 result = IKernelService::GetInstance()->Wait(this, &cs_, timeout_ticks);
261 }
262 else
263 {
264 // non-blocking poll: event not signaled, return immediately
265 // result is WAIT_RESULT_TIMEOUT already, so noop
266 }
267
268 return result;
269}
270
271// ---------------------------------------------------------------------------
272// TryWait
273// ---------------------------------------------------------------------------
274
275inline bool Event::TryWait()
276{
277 const ScopedCriticalSection cs_;
278 bool result = false;
279
280 if (m_signaled)
281 {
282 if (!m_manual_reset)
283 {
284 m_signaled = false;
285 __stk_full_memfence();
286 }
287
288 result = true;
289 }
290
291 return result;
292}
293
294// ---------------------------------------------------------------------------
295// RemoveWaitObject
296// ---------------------------------------------------------------------------
297
299{
301
302 // kernel invariant: auto-reset is applied here, not at the Set()/Pulse() call site,
303 // when a task wakes due to a signal (not a timeout), the event transitions back to
304 // non-signaled so that subsequent Wait() calls block until the next Set()
306 {
308 {
309 m_signaled = false;
310 __stk_full_memfence();
311 }
312 }
313}
314
315} // namespace sync
316} // namespace stk
317
318#endif /* STK_SYNC_EVENT_H_ */
#define STK_NONCOPYABLE_CLASS(TYPE)
Disables copy construction and assignment for a class.
Definition stk_defs.h:708
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:261
Implementation of synchronization primitive: stk::sync::ScopedCriticalSection.
Namespace of STK package.
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:220
EWaitResult
Wait result (see IKernelService::Wait).
Definition stk_common.h:123
@ WAIT_RESULT_TIMEOUT
The wake was caused by a timeout expiry.
Definition stk_common.h:126
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:125
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:156
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:214
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:471
@ STATE_SIGNALED
Wake signaled.
Definition stk_common.h:490
virtual EState GetState() const =0
Get current state.
Traceable object.
Definition stk_common.h:533
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.
void WakeAll() override
Wake all tasks currently in the wait list.
Definition stk_helper.h:288
SyncObjectBase()
Constructor.
Definition stk_helper.h:275
void RemoveWaitObject(IWaitObject *wobj) override
Called by kernel when a waiting task is being removed (timeout expired, wait aborted,...
Definition stk_helper.h:261
IWaitObject::ListHeadType m_wait_list
Tasks blocked on this object.
Definition stk_helper.h:298
void WakeOne() override
Wake the first task in the wait list (FIFO order).
Definition stk_helper.h:283
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.
EWaitResult WaitEx(Timeout timeout_ticks=WAIT_INFINITE)
Wait until event becomes signaled or the timeout expires, preserving the full wait outcome.
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