Make class for managing g_config_client_list 05/286205/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Wed, 7 Dec 2022 02:21:09 +0000 (11:21 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Fri, 30 Dec 2022 04:37:57 +0000 (13:37 +0900)
- Requirement:
g_config_client_list is shared memory, so thread safe access for
g_config_client_list is needed.

- Contents:
This patch makes new classes for accessing list of vc_config_client_s
instance. Through this patch, all other functions in this module can
access list of client information in a thread safe way using new class
instance introduced by this patch.
This new class will protect each client information element using mutex,
so the class will assure to prevent race condition.

Change-Id: I2426df83bd763ee3a96334cc64b4b93f6e06a760
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
client/CMakeLists.txt
common/VoiceControlClientInfo.cpp [new file with mode: 0644]
common/VoiceControlClientInfo.h [new file with mode: 0644]
common/VoiceControlClients.cpp [new file with mode: 0644]
common/VoiceControlClients.h [new file with mode: 0644]
common/vc_config_mgr.cpp
server/CMakeLists.txt

index 50149cf..6c62f69 100644 (file)
@@ -10,6 +10,8 @@ SET(SRCS
        ../common/vc_config_mgr.cpp
        ../common/VoiceControlEngines.cpp
        ../common/VoiceControlEngineInfo.cpp
+       ../common/VoiceControlClients.cpp
+       ../common/VoiceControlClientInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
@@ -23,6 +25,8 @@ SET(SETTING_SRCS
        ../common/vc_config_mgr.cpp
        ../common/VoiceControlEngines.cpp
        ../common/VoiceControlEngineInfo.cpp
+       ../common/VoiceControlClients.cpp
+       ../common/VoiceControlClientInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
 )
@@ -39,6 +43,8 @@ SET(WIDGET_SRCS
        ../common/vc_config_mgr.cpp
        ../common/VoiceControlEngines.cpp
        ../common/VoiceControlEngineInfo.cpp
+       ../common/VoiceControlClients.cpp
+       ../common/VoiceControlClientInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
@@ -61,6 +67,8 @@ SET(MANAGER_SRCS
        ../common/vc_config_mgr.cpp
        ../common/VoiceControlEngines.cpp
        ../common/VoiceControlEngineInfo.cpp
+       ../common/VoiceControlClients.cpp
+       ../common/VoiceControlClientInfo.cpp
        ../common/VoiceControlConfig.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
diff --git a/common/VoiceControlClientInfo.cpp b/common/VoiceControlClientInfo.cpp
new file mode 100644 (file)
index 0000000..8ce8f62
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#include <stdexcept>
+#include <dlog.h>
+
+#include "vc_main.h"
+
+#include "VoiceControlClientInfo.h"
+
+
+using namespace std;
+
+VoiceControlClientInfo::VoiceControlClientInfo(unsigned int uid)
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Constructor] VoiceControlClientInfo");
+       __engineChangedCallback = nullptr;
+       __languageChangedCallback = nullptr;
+       __enabledChangedCallback = nullptr;
+       __uid = uid;
+}
+
+VoiceControlClientInfo::~VoiceControlClientInfo()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Destructor] VoiceControlClientInfo");
+
+       __engineChangedCallback = nullptr;
+       __languageChangedCallback = nullptr;
+       __enabledChangedCallback = nullptr;
+       __uid = 0;
+}
+
+unsigned int VoiceControlClientInfo::getUid()
+{
+       return __uid;
+}
+
+void VoiceControlClientInfo::setEngineChangedCallback(vc_config_engine_changed_cb callback)
+{
+       __engineChangedCallback = callback;
+}
+
+void VoiceControlClientInfo::invokeEngineChangedCallback(const char *engine_appid)
+{
+       if (__engineChangedCallback == nullptr) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "Engine changed callback is not set. uid(%u)", __uid);
+               return;
+       }
+
+       __engineChangedCallback(engine_appid);
+}
+
+void VoiceControlClientInfo::setLanguageChangedCallback(vc_config_lang_changed_cb callback)
+{
+       __languageChangedCallback = callback;
+}
+
+void VoiceControlClientInfo::invokeLanguageChangedCallback(const char* before_lang, const char* current_lang)
+{
+       if (__languageChangedCallback == nullptr) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "language changed callback is not set. uid(%u)", __uid);
+               return;
+       }
+
+       __languageChangedCallback(before_lang, current_lang);
+}
+
+void VoiceControlClientInfo::setEnabledChangedCallback(vc_config_enabled_cb callback)
+{
+       __enabledChangedCallback = callback;
+}
+
+void VoiceControlClientInfo::invokeEnabledChangedCallback(bool enable)
+{
+       if (__enabledChangedCallback == nullptr) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "Enabled changed callback is not set. uid(%u)", __uid);
+               return;
+       }
+
+       __enabledChangedCallback(enable);
+}
diff --git a/common/VoiceControlClientInfo.h b/common/VoiceControlClientInfo.h
new file mode 100644 (file)
index 0000000..d6df960
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#ifndef __VC_COMMON_VOICE_CONTROL_CLIENT_INFO_H_
+#define __VC_COMMON_VOICE_CONTROL_CLIENT_INFO_H_
+
+#include <vector>
+#include <string>
+#include <mutex>
+
+#include "vc_config_mgr.h"
+
+class VoiceControlClientInfo {
+public:
+       VoiceControlClientInfo(unsigned int uid);
+       virtual ~VoiceControlClientInfo();
+
+       unsigned int getUid();
+
+       void setEngineChangedCallback(vc_config_engine_changed_cb callback);
+       void invokeEngineChangedCallback(const char *engine_appid);
+
+       void setLanguageChangedCallback(vc_config_lang_changed_cb callback);
+       void invokeLanguageChangedCallback(const char* before_lang, const char* current_lang);
+
+       void setEnabledChangedCallback(vc_config_enabled_cb callback);
+       void invokeEnabledChangedCallback(bool enable);
+
+private:
+       unsigned int __uid;
+       vc_config_engine_changed_cb __engineChangedCallback;
+       vc_config_lang_changed_cb __languageChangedCallback;
+       vc_config_enabled_cb __enabledChangedCallback;
+};
+
+#endif /* __VC_COMMON_VOICE_CONTROL_CLIENT_INFO_H_ */
diff --git a/common/VoiceControlClients.cpp b/common/VoiceControlClients.cpp
new file mode 100644 (file)
index 0000000..cb72caf
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#include "vc_main.h"
+
+#include "VoiceControlClients.h"
+
+using namespace std;
+
+VoiceControlClients::VoiceControlClients()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Constructor] VoiceControlClients");
+}
+
+VoiceControlClients::~VoiceControlClients()
+{
+       SLOG(LOG_INFO, TAG_VCCONFIG, "[Destructor] VoiceControlClients");
+}
+
+void VoiceControlClients::printOutClients()
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "@ Client list @");
+
+       if (0 == __clients.size()) {
+               SLOG(LOG_DEBUG, TAG_VCCONFIG, "  No Client");
+       } else {
+               unsigned int index = 0;
+               for (auto &clientInfo : __clients) {
+                       SLOG(LOG_DEBUG, TAG_VCCONFIG, "[%dth] uid(%u)", index, clientInfo.getUid());
+               }
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "@@@@");
+}
+
+void VoiceControlClients::appendClient(VoiceControlClientInfo &clientInfo)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       __clients.push_back(clientInfo);
+}
+
+std::size_t VoiceControlClients::removeClient(unsigned int uid)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "Remove client ID (%u)", uid);
+       for (auto iter = __clients.begin(); iter != __clients.end(); iter++) {
+               if (iter->getUid() == uid) {
+                       SLOG(LOG_INFO, TAG_VCCONFIG, "Success to remove client (%u)", uid);
+                       __clients.erase(iter);
+                       return __clients.size();
+               }
+       }
+
+       SLOG(LOG_ERROR, TAG_VCCONFIG, "There is no client (%u)", uid);
+       return __clients.size();
+}
+
+void VoiceControlClients::setEngineChangedCallback(unsigned int uid, vc_config_engine_changed_cb callback)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       auto clientInfo = findClient(uid);
+       if (clientInfo == nullptr) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to found client info");
+               return;
+       }
+
+       clientInfo->setEngineChangedCallback(callback);
+
+}
+
+void VoiceControlClients::setLanguageChangedCallback(unsigned int uid, vc_config_lang_changed_cb callback)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       auto clientInfo = findClient(uid);
+       if (clientInfo == nullptr) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to found client info");
+               return;
+       }
+
+       clientInfo->setLanguageChangedCallback(callback);
+
+}
+
+void VoiceControlClients::setEnabledChangedCallback(unsigned int uid, vc_config_enabled_cb callback)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       auto clientInfo = findClient(uid);
+       if (clientInfo == nullptr) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to found client info");
+               return;
+       }
+
+       clientInfo->setEnabledChangedCallback(callback);
+}
+
+
+bool VoiceControlClients::isUidValid(unsigned int uid)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       bool isValid = (nullptr != findClient(uid));
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Client Id(%u) is %svalid", uid, (isValid ? "" : "not "));
+       return isValid;
+}
+
+std::shared_ptr<VoiceControlClientInfo> VoiceControlClients::getClientInfo(unsigned int uid)
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Get client info with ID(%u)", uid);
+       auto clientInfo = findClient(uid);
+       if (clientInfo == nullptr) {
+               SLOG(LOG_ERROR, TAG_VCCONFIG, "[ERROR] Fail to found client info");
+               return nullptr;
+       }
+
+       return make_shared<VoiceControlClientInfo>(*clientInfo);
+}
+
+VoiceControlClientInfo *VoiceControlClients::findClient(unsigned int uid)
+{
+       SLOG(LOG_DEBUG, TAG_VCCONFIG, "Find client ID (%u)", uid);
+       for (auto &clientInfo : __clients) {
+               if (clientInfo.getUid() == uid) {
+                       SLOG(LOG_INFO, TAG_VCCONFIG, "Success to find client (%u)", uid);
+                       return &clientInfo;
+               }
+       }
+
+       SLOG(LOG_ERROR, TAG_VCCONFIG, "There is no client (%u)", uid);
+       return nullptr;
+}
+
+std::vector<VoiceControlClientInfo> VoiceControlClients::getClients()
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Get clients. size(%zu)", __clients.size());
+       return __clients;
+}
+
+bool VoiceControlClients::isClientEmpty()
+{
+       unique_lock<mutex> lock(__clientsMutex);
+       SLOG(LOG_INFO, TAG_VCCONFIG, "Length of clients (%zu)", __clients.size());
+       return __clients.empty();
+}
+
diff --git a/common/VoiceControlClients.h b/common/VoiceControlClients.h
new file mode 100644 (file)
index 0000000..01303f5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+*  Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*  Licensed under the Apache License, Version 2.0 (the "License");
+*  you may not use this file except in compliance with the License.
+*  You may obtain a copy of the License at
+*  http://www.apache.org/licenses/LICENSE-2.0
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+
+#ifndef __VC_COMMON_VOICE_CONTROL_CLIENTS_H_
+#define __VC_COMMON_VOICE_CONTROL_CLIENTS_H_
+
+#include <vector>
+#include <string>
+#include <mutex>
+#include <memory>
+
+#include "VoiceControlClientInfo.h"
+
+class VoiceControlClients {
+public:
+       VoiceControlClients();
+       virtual ~VoiceControlClients();
+
+       void printOutClients();
+
+       void appendClient(VoiceControlClientInfo &clientInfo);
+       std::size_t removeClient(unsigned int uid);
+
+       void setEngineChangedCallback(unsigned int uid, vc_config_engine_changed_cb callback);
+       void setLanguageChangedCallback(unsigned int uid, vc_config_lang_changed_cb callback);
+       void setEnabledChangedCallback(unsigned int uid, vc_config_enabled_cb callback);
+
+       bool isUidValid(unsigned int uid);
+       std::shared_ptr<VoiceControlClientInfo> getClientInfo(unsigned int uid);
+       std::vector<VoiceControlClientInfo> getClients();
+       bool isClientEmpty();
+
+private:
+       VoiceControlClientInfo *findClient(unsigned int uid);
+
+       std::vector<VoiceControlClientInfo> __clients;
+       std::mutex __clientsMutex;
+};
+
+
+#endif /* __VC_COMMON_VOICE_CONTROL_CLIENTS_H_ */
index 60aed36..0544548 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "VoiceControlConfig.h"
 #include "VoiceControlEngines.h"
+#include "VoiceControlClients.h"
 
 #include "vc_config_mgr.h"
 #include "vc_config_parser.h"
@@ -45,13 +46,6 @@ using namespace std;
 #define EVENT_SIZE  (sizeof(struct inotify_event))
 #define BUF_LEN     (EVENT_SIZE + 16)
 
-typedef struct {
-       unsigned int uid;
-       vc_config_engine_changed_cb     engine_cb;
-       vc_config_lang_changed_cb       lang_cb;
-       vc_config_enabled_cb            enabled_cb;
-} vc_config_client_s;
-
 /* for engine directory monitoring */
 typedef struct {
        Ecore_Fd_Handler* dir_fd_handler;
@@ -59,19 +53,6 @@ typedef struct {
        int dir_wd;
 } vc_engine_inotify_s;
 
-typedef struct {
-       const char* before_lang;
-       const char* current_lang;
-} lang_cb_parameter_s;
-
-typedef struct {
-       const char *engine_appid;
-} engine_cb_parameter_s;
-
-typedef struct {
-       bool enable;
-} enabled_cb_parameter_s;
-
 static const char* vc_config_tag()
 {
        return TAG_VCCONFIG;
@@ -81,7 +62,7 @@ static atomic<bool> g_config_mgr_initialized(false);
 
 static VoiceControlEngines *g_VoiceControlEngines = nullptr;
 
-static GSList* g_config_client_list = NULL;
+static VoiceControlClients *g_VoiceControlClients = nullptr;
 
 static VoiceControlConfig *g_VoiceControlConfig = nullptr;
 
@@ -99,114 +80,56 @@ static int __vc_config_mgr_register_engine_config_updated_event(const char* path
 static int __vc_config_mgr_unregister_engine_config_updated_event();
 static int __vc_config_mgr_set_default_language(const char* language);
 
-int __vc_config_mgr_print_client_info();
-
-static gint __compare_uid_in_client_list(gconstpointer a, gconstpointer b)
-{
-       const vc_config_client_s *client_info = static_cast<const vc_config_client_s *>(a);
-       uintptr_t ptr_uid = (uintptr_t)b;
-       unsigned int uid = ptr_uid;
-
-       if (NULL == client_info) {
-               return 1;
-       }
-
-       if (uid == client_info->uid) {
-               SLOG(LOG_DEBUG, vc_config_tag(), "Find client information of %d", uid);
-               return 0;
-       }
-
-       return 1;
-}
-
-static vc_config_client_s *__find_client_info(unsigned int uid)
-{
-       uintptr_t ptr_uid = uid;
-       GSList *target = g_slist_find_custom(g_config_client_list, (gconstpointer)ptr_uid, __compare_uid_in_client_list);
-
-       vc_config_client_s *result = NULL;
-       if (NULL != target) {
-               result = static_cast<vc_config_client_s *>(target->data);
-       }
-
-       return result;
-}
-
-static void __invoke_lang_cb_in_client_list(gpointer data, gpointer user_data)
-{
-       vc_config_client_s* client_info = (vc_config_client_s*)data;
-       lang_cb_parameter_s* parameter = (lang_cb_parameter_s*)user_data;
-
-       if (NULL == client_info || NULL == parameter) {
-               return;
-       }
-
-       if (NULL != client_info->lang_cb) {
-               client_info->lang_cb(parameter->before_lang, parameter->current_lang);
-       }
-}
-
-static void __invoke_engine_cb_in_client_list(gpointer data, gpointer user_data)
+static void __vc_config_mgr_notify_engine_changed(const char *engine_appid)
 {
-       vc_config_client_s* client_info = (vc_config_client_s*)data;
-       engine_cb_parameter_s* parameter = (engine_cb_parameter_s*)user_data;
-
-       if (NULL == client_info || NULL == parameter) {
+       SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback");
+       if (nullptr == engine_appid) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
                return;
        }
 
-       if (NULL != client_info->engine_cb) {
-               client_info->engine_cb(parameter->engine_appid);
-       }
-}
-
-static void __invoke_enabled_cb_in_client_list(gpointer data, gpointer user_data)
-{
-       vc_config_client_s* client_info = (vc_config_client_s*)data;
-       enabled_cb_parameter_s* parameter = (enabled_cb_parameter_s*)user_data;
-
-       if (NULL == client_info || NULL == 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;
+               }
 
-       if (NULL != client_info->enabled_cb) {
-               client_info->enabled_cb(parameter->enable);
+               clientInfo.invokeEngineChangedCallback(engine_appid);
        }
 }
 
 static void __vc_config_mgr_notify_language_changed(const char* before_lang, const char* current_lang)
 {
-       if (NULL == before_lang || NULL == current_lang) {
+       SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback");
+       if (nullptr == before_lang || nullptr == current_lang) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
                return;
        }
 
-       lang_cb_parameter_s lang_cb_parameter;
-       lang_cb_parameter.before_lang = before_lang;
-       lang_cb_parameter.current_lang = current_lang;
-
-       g_slist_foreach(g_config_client_list, __invoke_lang_cb_in_client_list, &lang_cb_parameter);
-}
+       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;
+               }
 
-static void __vc_config_mgr_notify_engine_changed(const char *engine_appid)
-{
-       if (NULL == engine_appid) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
-               return;
+               clientInfo.invokeLanguageChangedCallback(before_lang, current_lang);
        }
-
-       engine_cb_parameter_s engine_cb_parameter;
-       engine_cb_parameter.engine_appid = engine_appid;
-
-       g_slist_foreach(g_config_client_list, __invoke_engine_cb_in_client_list, &engine_cb_parameter);
 }
 
 static void __vc_config_mgr_notify_enabled_changed(bool enable)
 {
-       enabled_cb_parameter_s enabled_cb_parameter;
-       enabled_cb_parameter.enable = 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;
+               }
 
-       g_slist_foreach(g_config_client_list, __invoke_enabled_cb_in_client_list, &enabled_cb_parameter);
+               clientInfo.invokeEnabledChangedCallback(enable);
+       }
 }
 
 static int __initialize_config_info()
@@ -321,20 +244,6 @@ int __vc_config_mgr_select_lang(const char* engine_id, char** language)
        return VC_CONFIG_ERROR_NONE;
 }
 
-int __vc_config_release_client(unsigned int uid)
-{
-       vc_config_client_s* temp_client = __find_client_info(uid);
-
-       if (NULL != temp_client) {
-               g_config_client_list = g_slist_remove(g_config_client_list, temp_client);
-               free(temp_client);
-       }
-
-       SLOG(LOG_DEBUG, vc_config_tag(), "Client count (%d)", g_slist_length(g_config_client_list));
-
-       return g_slist_length(g_config_client_list);
-}
-
 void __vc_config_release_engine()
 {
        delete g_VoiceControlEngines;
@@ -856,8 +765,6 @@ static int __initialize_vc_config_mgr()
 
 int vc_config_mgr_initialize(unsigned int uid)
 {
-       vc_config_client_s* temp_client = NULL;
-
        SLOG(LOG_INFO, vc_config_tag(), "[WARNING] Enter critical section");
        ecore_thread_main_loop_begin();
        pthread_mutex_lock(&vc_config_mgr_mutex);
@@ -871,8 +778,12 @@ int vc_config_mgr_initialize(unsigned int uid)
                return ret;
        }
 
+       if (g_VoiceControlClients == nullptr) {
+               g_VoiceControlClients = new VoiceControlClients();
+       }
+
        /* Check uid */
-       if (NULL != __find_client_info(uid)) {
+       if (g_VoiceControlClients->isUidValid(uid)) {
                SLOG(LOG_WARN, vc_config_tag(), "[CONFIG] uid(%u) has already registered", uid);
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                ecore_thread_main_loop_end();
@@ -880,25 +791,12 @@ int vc_config_mgr_initialize(unsigned int uid)
                return VC_CONFIG_ERROR_NONE;
        }
 
-       temp_client = (vc_config_client_s*)calloc(1, sizeof(vc_config_client_s));
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
-               ecore_thread_main_loop_end();
-               return VC_ERROR_OUT_OF_MEMORY;
-       }
-
-       temp_client->uid = uid;
-       temp_client->engine_cb = NULL;
-       temp_client->lang_cb = NULL;
-       temp_client->enabled_cb = NULL;
-
-       /* Add uid */
-       g_config_client_list = g_slist_append(g_config_client_list, temp_client);
+       VoiceControlClientInfo clientInfo(uid);
+       g_VoiceControlClients->appendClient(clientInfo);
 
        SLOG(LOG_INFO, vc_config_tag(), "[CONFIG] Add new client. uid(%u)", uid);
 
-       __vc_config_mgr_print_client_info();
+       g_VoiceControlClients->printOutClients();
 
        pthread_mutex_unlock(&vc_config_mgr_mutex);
        ecore_thread_main_loop_end();
@@ -912,13 +810,16 @@ int vc_config_mgr_finalize(unsigned int uid)
 
        pthread_mutex_lock(&vc_config_mgr_mutex);
 
-       if (0 < __vc_config_release_client(uid)) {
+       if (0 < g_VoiceControlClients->removeClient(uid)) {
                pthread_mutex_unlock(&vc_config_mgr_mutex);
                SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
 
                return VC_ERROR_NONE;
        }
 
+       delete g_VoiceControlClients;
+       g_VoiceControlClients = nullptr;
+
        __vc_config_release_engine();
 
        __vc_config_mgr_unregister_engine_config_updated_event();
@@ -996,101 +897,78 @@ int __vc_config_mgr_unregister_config_event()
 
 int vc_config_mgr_set_engine_cb(unsigned int uid, vc_config_engine_changed_cb engine_cb)
 {
-       ecore_thread_main_loop_begin();
-       pthread_mutex_lock(&vc_config_mgr_mutex);
+       if (nullptr == engine_cb) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enagine cb is NULL : uid(%u) ", uid);
+               return VC_CONFIG_ERROR_INVALID_PARAMETER;
+       }
 
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       ecore_thread_main_loop_begin();
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                ecore_thread_main_loop_end();
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->engine_cb = engine_cb;
+       g_VoiceControlClients->setEngineChangedCallback(uid, engine_cb);
+
        if (VC_CONFIG_ERROR_NONE != __vc_config_mgr_register_lang_event()) {
                SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register config event");
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
                ecore_thread_main_loop_end();
                return VC_CONFIG_ERROR_OPERATION_FAILED;
        }
 
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
        ecore_thread_main_loop_end();
-       return VC_ERROR_NONE;
+       return VC_CONFIG_ERROR_NONE;
 }
 
 int vc_config_mgr_unset_engine_cb(unsigned int uid)
 {
        ecore_thread_main_loop_begin();
-       pthread_mutex_lock(&vc_config_mgr_mutex);
-
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                ecore_thread_main_loop_end();
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->engine_cb = NULL;
+       g_VoiceControlClients->setEngineChangedCallback(uid, nullptr);
+
        __vc_config_mgr_unregister_config_event();
 
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
        ecore_thread_main_loop_end();
-       return VC_ERROR_NONE;
+       return VC_CONFIG_ERROR_NONE;
 }
 
-
 int vc_config_mgr_set_lang_cb(unsigned int uid, vc_config_lang_changed_cb lang_cb)
 {
-       ecore_thread_main_loop_begin();
-       pthread_mutex_lock(&vc_config_mgr_mutex);
-
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
-               ecore_thread_main_loop_end();
+       if (nullptr == lang_cb) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enagine cb is NULL : uid(%u) ", uid);
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->lang_cb = lang_cb;
-       if (0 != __vc_config_mgr_register_lang_event()) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register config event");
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       ecore_thread_main_loop_begin();
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                ecore_thread_main_loop_end();
-               return VC_CONFIG_ERROR_OPERATION_FAILED;
+               return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
+       g_VoiceControlClients->setLanguageChangedCallback(uid, lang_cb);
        ecore_thread_main_loop_end();
-       return VC_ERROR_NONE;
+       return VC_CONFIG_ERROR_NONE;
 }
 
 int vc_config_mgr_unset_lang_cb(unsigned int uid)
 {
        ecore_thread_main_loop_begin();
-       pthread_mutex_lock(&vc_config_mgr_mutex);
-
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                ecore_thread_main_loop_end();
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->lang_cb = NULL;
-       __vc_config_mgr_unregister_config_event();
-
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
+       g_VoiceControlClients->setLanguageChangedCallback(uid, nullptr);
        ecore_thread_main_loop_end();
-       return VC_ERROR_NONE;
+       return VC_CONFIG_ERROR_NONE;
 }
 
 int vc_config_mgr_set_enabled_cb(unsigned int uid, vc_config_enabled_cb enabled_cb)
@@ -1100,38 +978,24 @@ int vc_config_mgr_set_enabled_cb(unsigned int uid, vc_config_enabled_cb enabled_
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       pthread_mutex_lock(&vc_config_mgr_mutex);
-
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->enabled_cb = enabled_cb;
-
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
+       g_VoiceControlClients->setEnabledChangedCallback(uid, enabled_cb);
        return VC_CONFIG_ERROR_NONE;
 }
 
 int vc_config_mgr_unset_enabled_cb(unsigned int uid)
 {
-       pthread_mutex_lock(&vc_config_mgr_mutex);
-
-       /* Call all callbacks of client*/
-       vc_config_client_s* temp_client = __find_client_info(uid);
-       if (NULL == temp_client) {
-               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Uid is not valid (%u)", uid);
-               pthread_mutex_unlock(&vc_config_mgr_mutex);
+       if (false == g_VoiceControlClients->isUidValid(uid)) {
+               SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
                return VC_CONFIG_ERROR_INVALID_PARAMETER;
        }
 
-       temp_client->enabled_cb = NULL;
-
-       pthread_mutex_unlock(&vc_config_mgr_mutex);
-       return VC_ERROR_NONE;
+       g_VoiceControlClients->setEnabledChangedCallback(uid, nullptr);
+       return VC_CONFIG_ERROR_NONE;
 }
 
 int vc_config_mgr_get_auto_language(bool* value)
@@ -1622,34 +1486,3 @@ int vc_config_mgr_get_foreground(int* pid)
        pthread_mutex_unlock(&vc_config_mgr_mutex);
        return vc_parser_get_foreground(pid);
 }
-
-int __vc_config_mgr_print_client_info()
-{
-       GSList *iter = NULL;
-       vc_config_client_s* temp_client = NULL;
-
-       if (0 >= g_slist_length(g_config_client_list)) {
-               SLOG(LOG_DEBUG, vc_config_tag(), "@ Client list @");
-               SLOG(LOG_DEBUG, vc_config_tag(), "  No Client");
-               SLOG(LOG_DEBUG, vc_config_tag(), "@@@@");
-               return VC_ERROR_NONE;
-       }
-
-       /* Get a first item */
-       iter = g_slist_nth(g_config_client_list, 0);
-
-       SLOG(LOG_DEBUG, vc_config_tag(), "@ Client list @");
-
-       int i = 1;
-       while (NULL != iter) {
-               temp_client = static_cast<vc_config_client_s*>(iter->data);
-
-               SLOG(LOG_DEBUG, vc_config_tag(), "[%dth] uid(%u)", i, temp_client->uid);
-
-               iter = g_slist_next(iter);
-               i++;
-       }
-       SLOG(LOG_DEBUG, vc_config_tag(), "@@@@");
-
-       return VC_ERROR_NONE;
-}
index 11b6213..4b1b80e 100644 (file)
@@ -6,6 +6,8 @@ SET(SRCS
        ../common/VoiceControlConfig.cpp
        ../common/VoiceControlEngines.cpp
        ../common/VoiceControlEngineInfo.cpp
+       ../common/VoiceControlClients.cpp
+       ../common/VoiceControlClientInfo.cpp
        ../common/vc_config_parser.c
        ../common/vc_info_parser.c
        ../common/vc_json_parser.c