aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-10-01 19:41:53 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2019-10-04 17:58:31 +0200
commit7428025801f36d8e08e404e90f4adfc7b54ef139 (patch)
tree930a0e879cbd17e90ead430cde26482f900bf49c
parent442a67e36946e035e0c2aa221d546939e91d9872 (diff)
add osmo_fsm_inst_dispatch_and_watch()neels/fsm
The most common use case for osmo_fsm_inst_watch() is to dispatch an event and determine whether that caused deallocation. Add this convenience wrapper to simplify implementing this use case. This: void event_action() { struct osmo_fsm_inst_watcher watch_bar; osmo_fsm_inst_watch(&watch_bar, bar); osmo_fsm_inst_dispatch(foo, FOO_EVENT, NULL); osmo_fsm_inst_unwatch(&watch_bar); if (watch_bar.exists) osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL); } becomes: void event_action() { if (osmo_fsm_inst_dispatch_and_watch(foo, FOO_EVENT, NULL, bar, NULL)) osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL); } Change-Id: Ie9a77783d2052d4677fc5d0a7eb15f9e3b0fda8f
-rw-r--r--include/osmocom/core/fsm.h14
-rw-r--r--src/fsm.c27
2 files changed, 41 insertions, 0 deletions
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index 24871243..8e9ed77e 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -301,6 +301,20 @@ int _osmo_fsm_inst_state_chg_keep_or_start_timer_ms(struct osmo_fsm_inst *fi, ui
int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data,
const char *file, int line);
+/*! dispatch an event to an FSM instance, while watching out for deallocation of this or another instance.
+ *
+ * This is a convenience wrapper for using osmo_fsm_inst_watch() and osmo_fsm_inst_dispatch().
+ *
+ * This is a macro that calls _osmo_fsm_inst_dispatch_and_watch() with the given
+ * parameters as well as the caller's source file and line number for logging
+ * purposes. See there for documentation.
+ */
+#define osmo_fsm_inst_dispatch_and_watch(fi, event, data, watch_fi, rc_p) \
+ _osmo_fsm_inst_dispatch_and_watch(fi, event, data, watch_fi, rc_p, __FILE__, __LINE__)
+bool _osmo_fsm_inst_dispatch_and_watch(struct osmo_fsm_inst *fi, uint32_t event, void *data,
+ struct osmo_fsm_inst *watch_fi, int *rc_p,
+ const char *file, int line);
+
/*! Terminate FSM instance with given cause
*
* This is a macro that calls _osmo_fsm_inst_term() with the given parameters
diff --git a/src/fsm.c b/src/fsm.c
index 4d6cdd65..8e35cbe9 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -836,6 +836,33 @@ int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data
return 0;
}
+/*! dispatch an event to an FSM instance, while watching out for deallocation of this or another instance.
+ *
+ * This is a convenience wrapper for using osmo_fsm_inst_watch() and osmo_fsm_inst_dispatch().
+ *
+ * \param[in] fi FSM instance to dispatch event to.
+ * \param[in] event Event to dispatch.
+ * \param[in] data Data to pass along with the event.
+ * \param[in] watch_fi FSM instance to watch deallocation of (possibly but not necessarily identical to fi).
+ * \param[out] rc_p If not NULL, return the _osmo_fsm_inst_dispatch() return value in this int.
+ * \param[in] file Calling source file (from osmo_fsm_inst_dispatch macro)
+ * \param[in] line Calling source line (from osmo_fsm_inst_dispatch macro)
+ * \returns true if watch_fi still exists after dispatching the event, false if it was deallocated or was NULL.
+ */
+bool _osmo_fsm_inst_dispatch_and_watch(struct osmo_fsm_inst *fi, uint32_t event, void *data,
+ struct osmo_fsm_inst *watch_fi, int *rc_p,
+ const char *file, int line)
+{
+ int rc;
+ struct osmo_fsm_inst_watcher watcher;
+ osmo_fsm_inst_watch(&watcher, watch_fi);
+ rc = _osmo_fsm_inst_dispatch(fi, event, data, file, line);
+ osmo_fsm_inst_unwatch(&watcher);
+ if (rc_p)
+ *rc_p = rc;
+ return watcher.exists;
+}
+
/*! Terminate FSM instance with given cause
*
* This safely terminates the given FSM instance by first iterating