Invoke changed callbacks using ecore idler 79/291079/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Fri, 7 Apr 2023 08:31:36 +0000 (17:31 +0900)
committerTizen AI <ai.tzn.sec@samsung.com>
Fri, 7 Apr 2023 11:03:42 +0000 (20:03 +0900)
- Requirements:
Each callbacks should not prevent main loop for a long time.

- Contents:
This patch fixes the logic of changed callback invocation. Through this
patch, each callbacks will be invoked by ecore idler. This makes the
code blocks the main loop for reasonable time. And this makes each
callbacks behavior become asynchronous.

Change-Id: I482e5168f3f9ff44398b5b7d067a68f37e511fd0
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
common/vc_config_mgr.cpp

index e502e7e..3986088 100644 (file)
@@ -53,6 +53,11 @@ typedef struct {
        int dir_wd;
 } vc_engine_inotify_s;
 
+typedef struct {
+       char* before_lang;
+       char* current_lang;
+} language_changed_cb_parameters_s;
+
 static const char* vc_config_tag()
 {
        return TAG_VCCONFIG;
@@ -66,6 +71,10 @@ static VoiceControlClients *g_VoiceControlClients = nullptr;
 
 static VoiceControlConfig *g_VoiceControlConfig = nullptr;
 
+static Ecore_Idler *g_engine_changed_event_idler = NULL;
+static Ecore_Idler *g_language_changed_event_idler = NULL;
+static Ecore_Idler *g_enabled_changed_event_idler = NULL;
+
 static int g_lang_ref_count;
 static Ecore_Fd_Handler* g_fd_handler_lang = NULL;
 static int g_fd_lang = -1;
@@ -78,6 +87,45 @@ static int register_engine_config_updated_event(const char* path);
 static int unregister_engine_config_updated_event();
 static int set_current_language(const char* language);
 
+static Eina_Bool notify_engine_changed_event_by_idler(void *data)
+{
+       char *engine_appid = static_cast<char *>(data);
+       [&engine_appid]() {
+               if (nullptr == engine_appid) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified.");
+                       return;
+               }
+
+               if (nullptr == g_VoiceControlClients) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
+                       return;
+               }
+
+               auto clients = g_VoiceControlClients->getClients();
+               for (auto &clientInfo : clients) {
+                       if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
+                               SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
+                               continue;
+                       }
+
+                       clientInfo.invokeEngineChangedCallback(engine_appid);
+               }
+       }();
+
+       free(engine_appid);
+       g_engine_changed_event_idler = nullptr;
+       return EINA_FALSE;
+}
+
+static inline void delete_engine_changed_event_invoker()
+{
+       if (nullptr != g_engine_changed_event_idler) {
+               void *param = ecore_idler_del(g_engine_changed_event_idler);
+               g_engine_changed_event_idler = nullptr;
+               free(static_cast<char *>(param));
+       }
+}
+
 static void notify_engine_changed(const char *engine_appid)
 {
        SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback");
@@ -86,14 +134,63 @@ static void notify_engine_changed(const char *engine_appid)
                return;
        }
 
-       auto clients = g_VoiceControlClients->getClients();
-       for (auto &clientInfo : clients) {
-               if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
-                       SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
-                       continue;
+       char *param = strdup(engine_appid);
+       if (nullptr == param) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
+               return;
+       }
+
+       delete_engine_changed_event_invoker();
+       g_engine_changed_event_idler = ecore_idler_add(notify_engine_changed_event_by_idler, static_cast<void *>(param));
+}
+
+static inline void release_language_changed_cb_params(language_changed_cb_parameters_s *params)
+{
+       if (nullptr == params) {
+               return;
+       }
+
+       free(params->before_lang);
+       free(params->current_lang);
+       delete params;
+}
+
+static Eina_Bool notify_language_changed_event_by_idler(void *data)
+{
+       language_changed_cb_parameters_s *params = static_cast<language_changed_cb_parameters_s *>(data);
+       [&params]() {
+               if (nullptr == params) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Parameters are not specified.");
+                       return;
+               }
+
+               if (nullptr == g_VoiceControlClients) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
+                       return;
+               }
+
+               auto clients = g_VoiceControlClients->getClients();
+               for (auto &clientInfo : clients) {
+                       if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
+                               SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
+                               continue;
+                       }
+
+                       clientInfo.invokeLanguageChangedCallback(params->before_lang, params->current_lang);
                }
+       }();
 
-               clientInfo.invokeEngineChangedCallback(engine_appid);
+       release_language_changed_cb_params(params);
+       g_language_changed_event_idler = nullptr;
+       return EINA_FALSE;
+}
+
+static inline void delete_language_changed_event_invoker()
+{
+       if (nullptr != g_language_changed_event_idler) {
+               void *params = ecore_idler_del(g_language_changed_event_idler);
+               g_language_changed_event_idler = nullptr;
+               release_language_changed_cb_params(static_cast<language_changed_cb_parameters_s *>(params));
        }
 }
 
@@ -105,34 +202,70 @@ static void notify_language_changed(const char* before_lang, const char* current
                return;
        }
 
-       if (nullptr == g_VoiceControlClients) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
+       auto *params = new language_changed_cb_parameters_s();
+       if (nullptr == params) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
                return;
        }
 
-       auto clients = g_VoiceControlClients->getClients();
-       for (auto &clientInfo : clients) {
-               if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
-                       SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
-                       continue;
+       params->before_lang = strdup(before_lang);
+       params->current_lang = strdup(current_lang);
+
+       delete_language_changed_event_invoker();
+       g_engine_changed_event_idler = ecore_idler_add(notify_language_changed_event_by_idler, static_cast<void *>(params));
+}
+
+static Eina_Bool notify_enabled_changed_event_by_idler(void *data)
+{
+       bool *enable = static_cast<bool *>(data);
+       [&enable]() {
+               if (nullptr == enable) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified.");
+                       return;
+               }
+
+               if (nullptr == g_VoiceControlClients) {
+                       SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
+                       return;
+               }
+
+               auto clients = g_VoiceControlClients->getClients();
+               for (auto &clientInfo : clients) {
+                       if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
+                               SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
+                               continue;
+                       }
+
+                       clientInfo.invokeEnabledChangedCallback(*enable);
                }
+       }();
 
-               clientInfo.invokeLanguageChangedCallback(before_lang, current_lang);
+       free(enable);
+       g_enabled_changed_event_idler = nullptr;
+       return EINA_FALSE;
+}
+
+static inline void delete_enabled_changed_event_invoker()
+{
+       if (nullptr != g_enabled_changed_event_idler) {
+               void *param = ecore_idler_del(g_enabled_changed_event_idler);
+               g_enabled_changed_event_idler = nullptr;
+               free(static_cast<bool *>(param));
        }
 }
 
 static void notify_enabled_changed(bool enable)
 {
        SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled callback");
-       auto clients = g_VoiceControlClients->getClients();
-       for (auto &clientInfo : clients) {
-               if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
-                       SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
-                       continue;
-               }
 
-               clientInfo.invokeEnabledChangedCallback(enable);
+       bool *param = new bool(enable);
+       if (nullptr == param) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
+               return;
        }
+
+       delete_enabled_changed_event_invoker();
+       g_engine_changed_event_idler = ecore_idler_add(notify_enabled_changed_event_by_idler, static_cast<void *>(param));
 }
 
 static int initialize_config_info()