1 /*
2  * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #ifndef ZEPHYR_INCLUDE_ZBUS_H_
7 #define ZEPHYR_INCLUDE_ZBUS_H_
8 
9 #include <string.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/iterable_sections.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Zbus API
20  * @defgroup zbus_apis Zbus APIs
21  * @ingroup os_services
22  * @{
23  */
24 
25 /**
26  * @brief Type used to represent a channel.
27  *
28  * Every channel has a zbus_channel structure associated used to control the channel
29  * access and usage.
30  */
31 struct zbus_channel {
32 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
33 	/** Channel name. */
34 	const char *const name;
35 #endif
36 	/** Message size. Represents the channel's message size. */
37 	const uint16_t message_size;
38 
39 	/** User data available to extend zbus features. The channel must be claimed before
40 	 * using this field.
41 	 */
42 	void *const user_data;
43 
44 	/** Message reference. Represents the message's reference that points to the actual
45 	 * shared memory region.
46 	 */
47 	void *const message;
48 
49 	/** Message validator. Stores the reference to the function to check the message
50 	 * validity before actually performing the publishing. No invalid messages can be
51 	 * published. Every message is valid when this field is empty.
52 	 */
53 	bool (*const validator)(const void *msg, size_t msg_size);
54 
55 	/** Access control mutex. Points to the mutex used to avoid race conditions
56 	 * for accessing the channel.
57 	 */
58 	struct k_mutex *mutex;
59 #if (CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0) || defined(__DOXYGEN__)
60 	/** Dynamic channel observer list. Represents the channel's observers list, it can be empty
61 	 * or have listeners and subscribers mixed in any sequence. It can be changed in runtime.
62 	 */
63 	sys_slist_t *runtime_observers;
64 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE  */
65 
66 	/** Channel observer list. Represents the channel's observers list, it can be empty or
67 	 * have listeners and subscribers mixed in any sequence.
68 	 */
69 	const struct zbus_observer *const *observers;
70 };
71 
72 /**
73  * @brief Type used to represent an observer.
74  *
75  * Every observer has an representation structure containing the relevant information.
76  * An observer is a code portion interested in some channel. The observer can be notified
77  * synchronously or asynchronously and it is called listener and subscriber respectively.
78  * The observer can be enabled or disabled during runtime by change the enabled boolean
79  * field of the structure. The listeners have a callback function that is executed by the
80  * bus with the index of the changed channel as argument when the notification is sent.
81  * The subscribers have a message queue where the bus enqueues the index of the changed
82  * channel when a notification is sent.
83  *
84  * @see zbus_obs_set_enable function to properly change the observer's enabled field.
85  *
86  */
87 struct zbus_observer {
88 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
89 	/** Observer name. */
90 	const char *const name;
91 #endif
92 	/** Enabled flag. Indicates if observer is receiving notification. */
93 	bool enabled;
94 	/** Observer message queue. It turns the observer into a subscriber. */
95 	struct k_msgq *const queue;
96 
97 	/** Observer callback function. It turns the observer into a listener. */
98 	void (*const callback)(const struct zbus_channel *chan);
99 };
100 
101 /** @cond INTERNAL_HIDDEN */
102 
103 #if defined(CONFIG_ZBUS_ASSERT_MOCK)
104 #define _ZBUS_ASSERT(_cond, _fmt, ...)                                                             \
105 	do {                                                                                       \
106 		if (!(_cond)) {                                                                    \
107 			printk("ZBUS ASSERT: ");                                                   \
108 			printk(_fmt, ##__VA_ARGS__);                                               \
109 			printk("\n");                                                              \
110 			return -EFAULT;                                                            \
111 		}                                                                                  \
112 	} while (0)
113 #else
114 #define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
115 #endif
116 
117 #if defined(CONFIG_ZBUS_CHANNEL_NAME)
118 #define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
119 #else
120 #define ZBUS_CHANNEL_NAME_INIT(_name)
121 #endif
122 
123 #if defined(CONFIG_ZBUS_OBSERVER_NAME)
124 #define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
125 #define _ZBUS_OBS_NAME(_obs)	       (_obs)->name
126 #else
127 #define ZBUS_OBSERVER_NAME_INIT(_name)
128 #define _ZBUS_OBS_NAME(_obs) ""
129 #endif
130 
131 #if CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0
132 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
133 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
134 #else
135 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
136 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
137 #endif
138 
139 #if defined(CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS)
140 #define _ZBUS_STRUCT_DECLARE(_type, _name) STRUCT_SECTION_ITERABLE(_type, _name)
141 #else
142 #define _ZBUS_STRUCT_DECLARE(_type, _name) struct _type _name
143 #endif /* CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS */
144 
145 #define _ZBUS_OBS_EXTERN(_name) extern struct zbus_observer _name
146 
147 #define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
148 
149 #define ZBUS_REF(_value) &(_value)
150 
151 k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks);
152 /** @endcond */
153 
154 /**
155  * @def ZBUS_OBS_DECLARE
156  * This macro list the observers to be used in a file. Internally, it declares the observers with
157  * the extern statement. Note it is only necessary when the observers are declared outside the file.
158  */
159 #define ZBUS_OBS_DECLARE(...) FOR_EACH(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
160 
161 /**
162  * @def ZBUS_CHAN_DECLARE
163  * This macro list the channels to be used in a file. Internally, it declares the channels with the
164  * extern statement. Note it is only necessary when the channels are declared outside the file.
165  */
166 #define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
167 
168 /**
169  * @def ZBUS_OBSERVERS_EMPTY
170  * This macro indicates the channel has no observers.
171  */
172 #define ZBUS_OBSERVERS_EMPTY
173 
174 /**
175  * @def ZBUS_OBSERVERS
176  * This macro indicates the channel has listed observers. Note the sequence of observer notification
177  * will follow the same as listed.
178  */
179 #define ZBUS_OBSERVERS(...) __VA_ARGS__
180 
181 /**
182  * @brief Zbus channel definition.
183  *
184  * This macro defines a channel.
185  *
186  * @param _name The channel's name.
187  * @param _type The Message type. It must be a struct or union.
188  * @param _validator The validator function.
189  * @param _user_data A pointer to the user data.
190  *
191  * @see struct zbus_channel
192  * @param _observers The observers list. The sequence indicates the priority of the observer. The
193  * first the highest priority.
194  * @param _init_val The message initialization.
195  */
196 #define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val)        \
197 	static _type _CONCAT(_zbus_message_, _name) = _init_val;                             \
198 	static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name));                                 \
199 	ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_CONCAT(_runtime_observers_, _name));               \
200 	FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), _observers)                            \
201 	static const struct zbus_observer *const _CONCAT(_zbus_observers_, _name)[] = {      \
202 	FOR_EACH_NONEMPTY_TERM(ZBUS_REF, (,), _observers) NULL};                             \
203 	const _ZBUS_STRUCT_DECLARE(zbus_channel, _name) = {                                  \
204 		ZBUS_CHANNEL_NAME_INIT(_name)		       /* Name */                    \
205 		.message_size = sizeof(_type),	               /* Message size */            \
206 		.user_data = _user_data,		       /* User data */               \
207 		.message = &_CONCAT(_zbus_message_, _name),    /* Reference to the message */\
208 		.validator = (_validator),		       /* Validator function */      \
209 		.mutex = &_CONCAT(_zbus_mutex_, _name),	       /* Channel's Mutex */         \
210 		ZBUS_RUNTIME_OBSERVERS_LIST_INIT(                                            \
211 			_CONCAT(_runtime_observers_, _name))   /* Runtime observer list */   \
212 		.observers = _CONCAT(_zbus_observers_, _name)} /* Static observer list */
213 
214 /**
215  * @brief Initialize a message.
216  *
217  * This macro initializes a message by passing the values to initialize the message struct
218  * or union.
219  *
220  * @param[in] _val Variadic with the initial values. ``ZBUS_INIT(0)`` means ``{0}``, as
221  * ZBUS_INIT(.a=10, .b=30) means ``{.a=10, .b=30}``.
222  */
223 #define ZBUS_MSG_INIT(_val, ...)                                                                   \
224 	{                                                                                          \
225 		_val, ##__VA_ARGS__                                                                \
226 	}
227 
228 /**
229  * @brief Define and initialize a subscriber.
230  *
231  * This macro defines an observer of subscriber type. It defines a message queue where the
232  * subscriber will receive the notification asynchronously, and initialize the ``struct
233  * zbus_observer`` defining the subscriber.
234  *
235  * @param[in] _name The subscriber's name.
236  * @param[in] _queue_size The notification queue's size.
237  */
238 #define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size)                                                 \
239 	K_MSGQ_DEFINE(_zbus_observer_queue_##_name, sizeof(const struct zbus_channel *),           \
240 		      _queue_size, sizeof(const struct zbus_channel *));                           \
241 	_ZBUS_STRUCT_DECLARE(zbus_observer,                                                        \
242 			     _name) = {ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */             \
243 					       .enabled = true,                                    \
244 				       .queue = &_zbus_observer_queue_##_name, .callback = NULL}
245 
246 /**
247  * @brief Define and initialize a listener.
248  *
249  * This macro defines an observer of listener type. This macro establishes the callback where the
250  * listener will be notified synchronously, and initialize the ``struct zbus_observer`` defining the
251  * listener.
252  *
253  * @param[in] _name The listener's name.
254  * @param[in] _cb The callback function.
255  */
256 #define ZBUS_LISTENER_DEFINE(_name, _cb)                                                           \
257 	_ZBUS_STRUCT_DECLARE(zbus_observer,                                                        \
258 			     _name) = {ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */             \
259 					       .enabled = true,                                    \
260 				       .queue = NULL, .callback = (_cb)}
261 
262 /**
263  *
264  * @brief Publish to a channel
265  *
266  * This routine publishes a message to a channel.
267  *
268  * @param chan The channel's reference.
269  * @param msg Reference to the message where the publish function copies the channel's
270  * message data from.
271  * @param timeout Waiting period to publish the channel,
272  *                or one of the special values K_NO_WAIT and K_FOREVER.
273  *
274  * @retval 0 Channel published.
275  * @retval -ENOMSG The message is invalid based on the validator function or some of the
276  * observers could not receive the notification.
277  * @retval -EBUSY The channel is busy.
278  * @retval -EAGAIN Waiting period timed out.
279  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
280  * observer, or the function context is invalid (inside an ISR). The function only returns this
281  * value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
282  */
283 int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
284 
285 /**
286  * @brief Read a channel
287  *
288  * This routine reads a message from a channel.
289  *
290  * @param[in] chan The channel's reference.
291  * @param[out] msg Reference to the message where the read function copies the channel's
292  * message data to.
293  * @param[in] timeout Waiting period to read the channel,
294  *                or one of the special values K_NO_WAIT and K_FOREVER.
295  *
296  * @retval 0 Channel read.
297  * @retval -EBUSY The channel is busy.
298  * @retval -EAGAIN Waiting period timed out.
299  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
300  * function only returns this value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
301  */
302 int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
303 
304 /**
305  * @brief Claim a channel
306  *
307  * This routine claims a channel. During the claiming period the channel is blocked for publishing,
308  * reading, notifying or claiming again. Finishing is the only available action.
309  *
310  * @warning After calling this routine, the channel cannot be used by other
311  * thread until the zbus_chan_finish routine is performed.
312  *
313  * @warning This routine should only be called once before a zbus_chan_finish.
314  *
315  * @param[in] chan The channel's reference.
316  * @param[in] timeout Waiting period to claim the channel,
317  *                or one of the special values K_NO_WAIT and K_FOREVER.
318  *
319  * @retval 0 Channel claimed.
320  * @retval -EBUSY The channel is busy.
321  * @retval -EAGAIN Waiting period timed out.
322  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
323  * function only returns this value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
324  */
325 int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
326 
327 /**
328  * @brief Finish a channel claim.
329  *
330  * This routine finishes a channel claim. After calling this routine with success, the channel will
331  * be able to be used by other thread.
332  *
333  * @warning This routine must only be used after a zbus_chan_claim.
334  *
335  * @param chan The channel's reference.
336  *
337  * @retval 0 Channel finished.
338  * @retval -EPERM The channel was claimed by other thread.
339  * @retval -EINVAL The channel's mutex is not locked.
340  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
341  * function only returns this value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
342  */
343 int zbus_chan_finish(const struct zbus_channel *chan);
344 
345 /**
346  * @brief Force a channel notification.
347  *
348  * This routine forces the event dispatcher to notify the channel's observers even if the message
349  * has no changes. Note this function could be useful after claiming/finishing actions.
350  *
351  * @param chan The channel's reference.
352  * @param timeout Waiting period to notify the channel,
353  *                or one of the special values K_NO_WAIT and K_FOREVER.
354  *
355  * @retval 0 Channel notified.
356  * @retval -EPERM The current thread does not own the channel.
357  * @retval -EBUSY The channel's mutex returned without waiting.
358  * @retval -EAGAIN Timeout to acquiring the channel's mutex.
359  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
360  * observer, or the function context is invalid (inside an ISR). The function only returns this
361  * value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
362  */
363 int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
364 
365 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
366 
367 /**
368  * @brief Get the channel's name.
369  *
370  * This routine returns the channel's name reference.
371  *
372  * @param chan The channel's reference.
373  *
374  * @return Channel's name reference.
375  */
zbus_chan_name(const struct zbus_channel * chan)376 static inline const char *zbus_chan_name(const struct zbus_channel *chan)
377 {
378 	__ASSERT(chan != NULL, "chan is required");
379 
380 	return chan->name;
381 }
382 
383 #endif
384 
385 /**
386  * @brief Get the reference for a channel message directly.
387  *
388  * This routine returns the reference of a channel message.
389  *
390  * @warning This function must only be used directly for acquired (locked by mutex) channels. This
391  * can be done inside a listener for the receiving channel or after claim a channel.
392  *
393  * @param chan The channel's reference.
394  *
395  * @return Channel's message reference.
396  */
zbus_chan_msg(const struct zbus_channel * chan)397 static inline void *zbus_chan_msg(const struct zbus_channel *chan)
398 {
399 	__ASSERT(chan != NULL, "chan is required");
400 
401 	return chan->message;
402 }
403 
404 /**
405  * @brief Get a constant reference for a channel message directly.
406  *
407  * This routine returns a constant reference of a channel message. This should be used
408  * inside listeners to access the message directly. In this way zbus prevents the listener of
409  * changing the notifying channel's message during the notification process.
410  *
411  * @warning This function must only be used directly for acquired (locked by mutex) channels. This
412  * can be done inside a listener for the receiving channel or after claim a channel.
413  *
414  * @param chan The channel's constant reference.
415  *
416  * @return A constant channel's message reference.
417  */
zbus_chan_const_msg(const struct zbus_channel * chan)418 static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
419 {
420 	__ASSERT(chan != NULL, "chan is required");
421 
422 	return chan->message;
423 }
424 
425 /**
426  * @brief Get the channel's message size.
427  *
428  * This routine returns the channel's message size.
429  *
430  * @param chan The channel's reference.
431  *
432  * @return Channel's message size.
433  */
zbus_chan_msg_size(const struct zbus_channel * chan)434 static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
435 {
436 	__ASSERT(chan != NULL, "chan is required");
437 
438 	return chan->message_size;
439 }
440 
441 /**
442  * @brief Get the channel's user data.
443  *
444  * This routine returns the channel's user data.
445  *
446  * @param chan The channel's reference.
447  *
448  * @return Channel's user data.
449  */
zbus_chan_user_data(const struct zbus_channel * chan)450 static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
451 {
452 	__ASSERT(chan != NULL, "chan is required");
453 
454 	return chan->user_data;
455 }
456 
457 #if (CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0) || defined(__DOXYGEN__)
458 
459 /**
460  * @brief Add an observer to a channel.
461  *
462  * This routine adds an observer to the channel.
463  *
464  * @param chan The channel's reference.
465  * @param obs The observer's reference to be added.
466  * @param timeout Waiting period to add an observer,
467  *                or one of the special values K_NO_WAIT and K_FOREVER.
468  *
469  * @retval 0 Observer added to the channel.
470  * @retval -EALREADY The observer is already present in the channel's runtime observers list.
471  * @retval -ENOMEM Returned without waiting.
472  * @retval -EAGAIN Waiting period timed out.
473  * @retval -EINVAL Some parameter is invalid.
474  */
475 int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
476 		      k_timeout_t timeout);
477 
478 /**
479  * @brief Remove an observer from a channel.
480  *
481  * This routine removes an observer to the channel.
482  *
483  * @param chan The channel's reference.
484  * @param obs The observer's reference to be removed.
485  * @param timeout Waiting period to remove an observer,
486  *                or one of the special values K_NO_WAIT and K_FOREVER.
487  *
488  * @retval 0 Observer removed to the channel.
489  * @retval -EINVAL Invalid data supplied.
490  * @retval -EBUSY Returned without waiting.
491  * @retval -EAGAIN Waiting period timed out.
492  * @retval -ENODATA no observer found in channel's runtime observer list.
493  * @retval -ENOMEM Returned without waiting.
494  */
495 int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
496 		     k_timeout_t timeout);
497 
498 /**
499  * @brief Get zbus runtime observers pool.
500  *
501  * This routine returns a reference of the runtime observers pool.
502  *
503  * @return Reference of runtime observers pool.
504  */
505 struct k_mem_slab *zbus_runtime_obs_pool(void);
506 
507 /** @cond INTERNAL_HIDDEN */
508 
509 struct zbus_observer_node {
510 	sys_snode_t node;
511 	const struct zbus_observer *obs;
512 };
513 
514 /** @endcond */
515 
516 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE */
517 
518 /**
519  * @brief Change the observer state.
520  *
521  * This routine changes the observer state. A channel when disabled will not receive
522  * notifications from the event dispatcher.
523  *
524  * @param[in] obs The observer's reference.
525  * @param[in] enabled State to be. When false the observer stops to receive notifications.
526  *
527  * @retval 0 Observer set enable.
528  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
529  * function only returns this value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
530  */
zbus_obs_set_enable(struct zbus_observer * obs,bool enabled)531 static inline int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled)
532 {
533 	_ZBUS_ASSERT(obs != NULL, "obs is required");
534 
535 	obs->enabled = enabled;
536 
537 	return 0;
538 }
539 
540 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
541 
542 /**
543  * @brief Get the observer's name.
544  *
545  * This routine returns the observer's name reference.
546  *
547  * @param obs The observer's reference.
548  *
549  * @return The observer's name reference.
550  */
zbus_obs_name(const struct zbus_observer * obs)551 static inline const char *zbus_obs_name(const struct zbus_observer *obs)
552 {
553 	__ASSERT(obs != NULL, "obs is required");
554 
555 	return obs->name;
556 }
557 
558 #endif
559 
560 /**
561  * @brief Wait for a channel notification.
562  *
563  * This routine makes the subscriber to wait a notification. The notification comes as a channel
564  * reference.
565  *
566  * @param[in] sub The subscriber's reference.
567  * @param[out] chan The notification channel's reference.
568  * @param[in] timeout Waiting period for a notification arrival,
569  *                or one of the special values K_NO_WAIT and K_FOREVER.
570  *
571  * @retval 0 Notification received.
572  * @retval -ENOMSG Returned without waiting.
573  * @retval -EAGAIN Waiting period timed out.
574  * @retval -EINVAL The observer is not a subscriber.
575  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
576  * function only returns this value when the CONFIG_ZBUS_ASSERT_MOCK is enabled.
577  */
578 int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
579 		  k_timeout_t timeout);
580 
581 #if defined(CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS) || defined(__DOXYGEN__)
582 /**
583  *
584  * @brief Iterate over channels.
585  *
586  * Enables the developer to iterate over the channels giving to this function an
587  * iterator_func which is called for each channel. If the iterator_func returns false all
588  * the iteration stops.
589  *
590  * @retval true Iterator executed for all channels.
591  * @retval false Iterator could not be executed. Some iterate returned false.
592  */
593 bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
594 
595 /**
596  *
597  * @brief Iterate over observers.
598  *
599  * Enables the developer to iterate over the observers giving to this function an
600  * iterator_func which is called for each observer. If the iterator_func returns false all
601  * the iteration stops.
602  *
603  * @retval true Iterator executed for all channels.
604  * @retval false Iterator could not be executed. Some iterate returned false.
605  */
606 bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
607 
608 #endif /* CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS */
609 /**
610  * @}
611  */
612 
613 #ifdef __cplusplus
614 }
615 #endif
616 
617 #endif /* ZEPHYR_INCLUDE_ZBUS_H_ */
618