+/**
+ * Call every device in the current session's callback.
+ *
+ * For sessions not driven by select loops such as sr_session_run(),
+ * but driven by another scheduler, this can be used to poll the devices
+ * from within that scheduler.
+ *
+ * @param block If TRUE, this call will wait for any of the session's
+ * sources to fire an event on the file descriptors, or
+ * any of their timeouts to activate. In other words, this
+ * can be used as a select loop.
+ * If FALSE, all sources have their callback run, regardless
+ * of file descriptor or timeout status.
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR Error occured.
+ */
+static int sr_session_iteration(gboolean block)
+{
+ struct sr_session *session = sr_current_session;
+ unsigned int i;
+ int ret;
+
+ ret = g_poll(session->pollfds, session->num_sources,
+ block ? session->source_timeout : 0);
+ for (i = 0; i < session->num_sources; i++) {
+ if (session->pollfds[i].revents > 0 || (ret == 0
+ && session->source_timeout == session->sources[i].timeout)) {
+ /*
+ * Invoke the source's callback on an event,
+ * or if the poll timed out and this source
+ * asked for that timeout.
+ */
+ if (!session->sources[i].cb(session->pollfds[i].fd,
+ session->pollfds[i].revents,
+ session->sources[i].cb_data))
+ sr_session_source_remove(session,
+ session->sources[i].poll_object);
+ }
+ /*
+ * We want to take as little time as possible to stop
+ * the session if we have been told to do so. Therefore,
+ * we check the flag after processing every source, not
+ * just once per main event loop.
+ */
+ g_mutex_lock(&session->stop_mutex);
+ if (session->abort_session) {
+ sr_session_stop_sync(session);
+ /* But once is enough. */
+ session->abort_session = FALSE;
+ }
+ g_mutex_unlock(&session->stop_mutex);
+ }
+
+ return SR_OK;