IntrOS
Loading...
Searching...
No Matches
osonceflag.h
1/******************************************************************************
2
3 @file IntrOS: osonceflag.h
4 @author Rajmund Szymanski
5 @date 17.11.2025
6 @brief This file contains definitions for IntrOS.
7
8 ******************************************************************************
9
10 Copyright (c) 2018-2022 Rajmund Szymanski. All rights reserved.
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to
14 deal in the Software without restriction, including without limitation the
15 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 sell copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 IN THE SOFTWARE.
29
30 ******************************************************************************/
31
32#ifndef __INTROS_ONE_H
33#define __INTROS_ONE_H
34
35#include "oskernel.h"
36#include "oscriticalsection.h"
37
43
47
48typedef uint_fast8_t one_t;
49typedef uint_fast8_t one_id [];
50
51/******************************************************************************
52 *
53 * Name : _ONE_INIT
54 *
55 * Description : once flag state after initialization
56 *
57 * Parameters : none
58 *
59 * Return : once flag object
60 *
61 * Note : for internal use
62 *
63 ******************************************************************************/
64
65#define _ONE_INIT() 0
66
67/******************************************************************************
68 *
69 * Name : _ONE_DONE
70 *
71 * Description : once flag state after use
72 *
73 * Parameters : none
74 *
75 * Return : once flag object
76 *
77 * Note : for internal use
78 *
79 ******************************************************************************/
80
81#define _ONE_DONE() 1
82
89#define OS_ONE( one ) \
90 one_t one[] = { _ONE_INIT() }
91
92/** static alias of OS_ONE() */
93#define static_ONE( one ) \
94 static one_t one[] = { _ONE_INIT() }
95
103
104#ifndef __cplusplus
105#define ONE_INIT() \
106 _ONE_INIT()
107#endif
108
116
117#ifndef __cplusplus
118#define ONE_CREATE() \
119 { ONE_INIT () }
120/** alias of ONE_CREATE() */
121#define ONE_NEW \
122 ONE_CREATE
123#endif
124
125#ifdef __cplusplus
126extern "C" {
127#endif
128
134
135__STATIC_INLINE
136void one_init( one_t *one ) { *one = 0; }
137
150
151__STATIC_INLINE
152void one_call( one_t *one, fun_t *fun )
153{
154 one_t flag;
155 assert(one);
156 assert(fun);
157#if OS_ATOMICS
158 flag = __STD atomic_exchange((__STD atomic_uint_fast8_t *)one, _ONE_DONE());
159#else
160 sys_lock(); flag = *one; *one = _ONE_DONE(); sys_unlock();
161#endif
162 if (flag == _ONE_INIT()) fun();
163}
164
165#ifdef __cplusplus
166}
167#endif
168
169/* -------------------------------------------------------------------------- */
170
171#if defined(__cplusplus)
172namespace intros {
173
182struct OnceFlag
183{
185 constexpr
186 OnceFlag(): flg_{_ONE_INIT()} {}
187
189 OnceFlag( OnceFlag&& ) = default;
190 OnceFlag( const OnceFlag& ) = delete;
191 OnceFlag& operator=( OnceFlag&& ) = delete;
192 OnceFlag& operator=( const OnceFlag& ) = delete;
193
194#if __cplusplus >= 201402L
196 template<typename Callable, typename... Args>
197 void call( Callable&& _fun, Args&&... _args )
198 {
199 one_t flag;
200 #if OS_ATOMICS
201 flag = std::atomic_exchange((std::atomic_uint_fast8_t *)&flg_, _ONE_DONE());
202 #else
203 { CriticalSection cri; flag = flg_; flg_ = _ONE_DONE(); }
204 #endif
205 if (flag == _ONE_INIT()) _fun(std::forward<Args>(_args)...);
206 }
207#else
208 void call( fun_t *_fun )
209 {
210 one_call(&flg_, _fun);
211 }
212#endif
213
214 private:
215 one_t flg_;
216};
217
218} // namespace
219#endif//__cplusplus
220
221/* -------------------------------------------------------------------------- */
222
224
225#endif//__INTROS_ONE_H
void fun_t(void)
timer/task procedure
Definition osbase.h:142
#define sys_unlock()
restore saved interrupts state / exit from critical section
Definition oscriticalsection.h:148
#define sys_lock()
save interrupts state then disable interrupts / enter into critical section
Definition oscriticalsection.h:140
void one_init(one_t *one)
initialize a once flag object
Definition osonceflag.h:135
void one_call(one_t *one, fun_t *fun)
try to execute given function
Definition osonceflag.h:151
uint_fast8_t one_t
once flag
Definition osonceflag.h:48
create and initialize a critical section guard object
Definition oscriticalsection.h:165
constexpr OnceFlag()
constructor, see the constructor parameters of the class
Definition osonceflag.h:185
void call(Callable &&_fun, Args &&... _args)
call _fun(_args...) once, like std::call_once (one_call())
Definition osonceflag.h:196