Add mutex for thread safety of app_data access 57/260957/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Wed, 7 Jul 2021 10:37:46 +0000 (19:37 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Wed, 7 Jul 2021 11:13:30 +0000 (20:13 +0900)
app_data can be handled by main thread and sub thread for text playing.
Previous code guarantees the thread safety of sound data and speak data.
However, these are members of app data and thread safety of app data is not guaranteed.

This patch make mutex for app data access and unifies the mutex g_speak_data_mutex and
g_sound_data_mutex. These mutex are covered by new mutex for app data, because the data
covered by previous mutexs are member of app data.
So, if app wants to access those data, it should access app data first.

Change-Id: Ifb42b4e4751c32e3d8f786f79ffc3871b3c273e7
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
server/ttsd_data.cpp

index 6ba4349..df7d877 100644 (file)
@@ -43,10 +43,7 @@ typedef struct
 
 static vector<app_data_s> g_app_list;
 
-static pthread_mutex_t g_speak_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t g_sound_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static mutex g_app_state_mutex;
+static mutex g_app_data_mutex;
 
 /* If engine is running */
 static ttsd_synthesis_control_e        g_synth_control;
@@ -63,7 +60,6 @@ static void __data_show_list()
                return;
        }
 
-       lock_guard<mutex> lock(g_app_state_mutex);
        for (int i = 0; i < vsize; i++) {
                SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, g_app_list[i].pid, g_app_list[i].uid, g_app_list[i].state);
        }
@@ -72,14 +68,14 @@ static void __data_show_list()
 }
 #endif
 
-int __data_show_sound_list(int index)
+int __data_show_sound_list(app_data_s& app_data)
 {
        SLOG(LOG_DEBUG, tts_tag(), "----- Sound list -----");
 
        unsigned int i = 0;
-       if (!g_app_list[index].m_wav_data.empty()) {
+       if (!app_data.m_wav_data.empty()) {
                std::list<sound_data_s*>::iterator iter;
-               for (iter = g_app_list[index].m_wav_data.begin(); (NULL != *iter && iter != g_app_list[index].m_wav_data.end()); ++iter) {
+               for (iter = app_data.m_wav_data.begin(); (NULL != *iter && iter != app_data.m_wav_data.end()); ++iter) {
                        SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%d), uttid(%d), type(%d)",
                                        i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
                        i++;
@@ -94,14 +90,14 @@ int __data_show_sound_list(int index)
        return TTSD_ERROR_NONE;
 }
 
-int __data_show_text_list(int index)
+int __data_show_text_list(app_data_s& app_data)
 {
        SLOG(LOG_DEBUG, tts_tag(), "----- Text list -----");
 
        unsigned int i = 0;
-       if (!g_app_list[index].m_speak_data.empty()) {
+       if (!app_data.m_speak_data.empty()) {
                std::list<speak_data_s*>::iterator iter;
-               for (iter = g_app_list[index].m_speak_data.begin(); (NULL != *iter && iter != g_app_list[index].m_speak_data.end()); ++iter) {
+               for (iter = app_data.m_speak_data.begin(); (NULL != *iter && iter != app_data.m_speak_data.end()); ++iter) {
                        SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)",
                                        i + 1, *iter, (*iter)->lang, (*iter)->vctype, (*iter)->speed, (*iter)->utt_id, (*iter)->text);
                        i++;
@@ -116,14 +112,14 @@ int __data_show_text_list(int index)
        return TTSD_ERROR_NONE;
 }
 
-int __data_show_used_voice_list(int index)
+int __data_show_used_voice_list(app_data_s& app_data)
 {
        SLOG(LOG_DEBUG, tts_tag(), "----- Used voice list -----");
 
        unsigned int i = 0;
-       if (!g_app_list[index].m_used_voice.empty()) {
+       if (!app_data.m_used_voice.empty()) {
                std::list<used_voice_s>::iterator iter;
-               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); ++iter) {
+               for (iter = app_data.m_used_voice.begin(); iter != app_data.m_used_voice.end(); ++iter) {
                        SLOG(LOG_DEBUG, tts_tag(), "[%dth] lang(%s), vctype(%d)", i + 1, iter->lang, iter->vctype);
                        i++;
                }
@@ -152,10 +148,22 @@ ttsd_synthesis_control_e ttsd_get_synth_control()
        return g_synth_control;
 }
 
+static app_data_s* __get_client_app_data(int uid)
+{
+       for (auto& app_data : g_app_list) {
+               if (app_data.uid == uid) {
+                       return &app_data;
+               }
+       }
+
+       return nullptr;
+}
+
 int ttsd_data_new_client(int pid, int uid)
 {
-       if( -1 != ttsd_data_is_client(uid) ) {
-               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
+       lock_guard<mutex> lock(g_app_data_mutex);
+       if(nullptr != __get_client_app_data(uid) ) {
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is already registered (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
@@ -177,23 +185,77 @@ int ttsd_data_new_client(int pid, int uid)
        return TTSD_ERROR_NONE;
 }
 
+static void __clean_data(app_data_s& app_data)
+{
+       int removed_last_uttid = -1;
+       for (auto& speak_data : app_data.m_speak_data) {
+               if (nullptr == speak_data) {
+                       continue;
+               }
+
+               SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)",
+                               speak_data->utt_id, speak_data->text, speak_data->lang, speak_data->vctype, speak_data->speed);
+
+               if (nullptr != speak_data->text) {
+                       free(speak_data->text);
+                       speak_data->text = nullptr;
+               }
+               if (nullptr != speak_data->lang) {
+                       free(speak_data->lang);
+                       speak_data->lang = nullptr;
+               }
+               removed_last_uttid = speak_data->utt_id;
+
+               free(speak_data);
+               speak_data = nullptr;
+       }
+
+       if (-1 != removed_last_uttid) {
+               app_data.utt_id_stopped = removed_last_uttid;
+       }
+
+       int uid = app_data.uid;
+       for (auto& sound_data : app_data.m_wav_data) {
+               if (nullptr == sound_data) {
+                       continue;
+               }
+
+               SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] uid(%d), event(%d) data(%p) size(%d) rate(%d) utt(%d)",
+                       sound_data, uid, sound_data->event, sound_data->data, sound_data->data_size, sound_data->rate, sound_data->utt_id);
+
+               if (nullptr != sound_data->data) {
+                       free(sound_data->data);
+                       sound_data->data = nullptr;
+               }
+
+               free(sound_data);
+               sound_data = nullptr;
+       }
+
+       app_data.m_speak_data.clear();
+       app_data.m_wav_data.clear();
+}
+
 int ttsd_data_delete_client(int uid)
 {
+       lock_guard<mutex> lock(g_app_data_mutex);
        int index = 0;
+       for (auto& app_data : g_app_list) {
+               if (app_data.uid == uid) {
+                       break;
+               }
 
-       index = ttsd_data_is_client(uid);
+               index++;
+       }
 
-       if (index < 0) {
+       if (index >= (int)g_app_list.size()) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return -1;
        }
 
-       if (0 != ttsd_data_clear_data(uid)) {
-               SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] Fail to clear data");
-               return -1;
-       }
+       __clean_data(g_app_list[index]);
 
-       g_app_list.erase(g_app_list.begin()+index);
+       g_app_list.erase(g_app_list.begin() + index);
 
 #ifdef DATA_DEBUG
        __data_show_list();
@@ -206,6 +268,7 @@ int ttsd_data_delete_client(int uid)
 
 int ttsd_data_is_client(int uid)
 {
+       lock_guard<mutex> lock(g_app_data_mutex);
        int vsize = g_app_list.size();
 
        for (int i = 0; i < vsize; i++) {
@@ -229,78 +292,70 @@ int ttsd_data_get_client_count()
 
 int ttsd_data_get_pid(int uid)
 {
-       int index;
-
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0)  {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return -1;
        }
 
-       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d), pid(%d), index(%d)", uid, g_app_list[index].pid, index);
+       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d), pid(%d)", uid, app_data->pid);
 
-       return g_app_list[index].pid;
+       return app_data->pid;
 }
 
 int ttsd_data_set_ipc_method(int uid, tts_ipc_method_e method)
 {
-       int index = ttsd_data_is_client(uid);
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       g_app_list[index].ipc_method = method;
+       app_data->ipc_method = method;
 
        return TTSD_ERROR_NONE;
 }
 
 tts_ipc_method_e ttsd_data_get_ipc_method(int uid)
 {
-       int index = ttsd_data_is_client(uid);
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTS_IPC_METHOD_UNDEFINED;
        }
 
-       return g_app_list[index].ipc_method;
+       return app_data->ipc_method;
 }
 
 int ttsd_data_get_speak_data_size(int uid)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       /* mutex is locked */
-       pthread_mutex_lock(&g_speak_data_mutex);
-       int size = g_app_list[index].m_speak_data.size();
-
-       /* mutex is unlocked */
-       pthread_mutex_unlock(&g_speak_data_mutex);
-
-       return size;
+       return app_data->m_speak_data.size();
 }
 
 int ttsd_data_set_used_voice(int uid, const char* lang, int type)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
        /* Find voice */
+       list<used_voice_s>& usedVoices = app_data->m_used_voice;
        std::list<used_voice_s>::iterator iter;
-       if (!g_app_list[index].m_used_voice.empty()) {
-               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end();++iter) {
+       if (!usedVoices.empty()) {
+               for (iter = usedVoices.begin(); iter != usedVoices.end();++iter) {
                        if (0 == strcmp(lang, iter->lang) && type == iter->vctype) {
                                SLOG(LOG_DEBUG, tts_tag(), "[DATA] The voice is already registered (%s)(%d)", lang, type);
                                return 0;
@@ -314,7 +369,7 @@ int ttsd_data_set_used_voice(int uid, const char* lang, int type)
        used_voice.vctype = type;
 
        try {
-               iter = g_app_list[index].m_used_voice.insert(g_app_list[index].m_used_voice.end(), used_voice);
+               iter = usedVoices.insert(usedVoices.end(), used_voice);
        } catch (const std::bad_alloc&) {
                SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_used_voice (bad_alloc)");
                return -1;
@@ -322,7 +377,7 @@ int ttsd_data_set_used_voice(int uid, const char* lang, int type)
        SLOG(LOG_ERROR, tts_tag(), "[DATA] lang(%s), vctype(%d)", iter->lang, iter->vctype);
 
 #ifdef DATA_DEBUG
-       __data_show_used_voice_list(index);
+       __data_show_used_voice_list(*app_data);
 #endif
 
        return -1;      /* Need to load voice*/
@@ -330,10 +385,9 @@ int ttsd_data_set_used_voice(int uid, const char* lang, int type)
 
 int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0) {
+       unique_lock<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
@@ -343,12 +397,15 @@ int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
        }
 
        /* Find voice */
-       if (!g_app_list[index].m_used_voice.empty()) {
+       list<used_voice_s>& usedVoices = app_data->m_used_voice;
+       if (!usedVoices.empty()) {
                std::list<used_voice_s>::iterator iter;
 
-               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); ++iter) {
+               for (iter = usedVoices.begin(); iter != usedVoices.end(); ++iter) {
                        if (NULL != callback) {
+                               lock.unlock();
                                callback(iter->lang, iter->vctype);
+                               lock.lock();
                        }
 
                        if (NULL != iter->lang) {
@@ -357,11 +414,11 @@ int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
                        }
                }
 
-               g_app_list[index].m_used_voice.clear();
+               usedVoices.clear();
        }
 
 #ifdef DATA_DEBUG
-       __data_show_used_voice_list(index);
+       __data_show_used_voice_list(*app_data);
 #endif
 
        return TTSD_ERROR_NONE;
@@ -369,104 +426,82 @@ int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
 
 int ttsd_data_add_speak_data(int uid, speak_data_s* data)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       /* mutex is locked */
-       pthread_mutex_lock(&g_speak_data_mutex);
-
        std::list<speak_data_s*>::iterator iter;
 
-       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d), index(%d)", uid, index);
+       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d)", uid);
 
        try {
-               int vsize = g_app_list.size();
-               if (index < vsize) {
-                       int spk_data_size = g_app_list[index].m_speak_data.size();
-                       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] m_speak_data size(%d)", spk_data_size);
-                       iter = g_app_list[index].m_speak_data.insert(g_app_list[index].m_speak_data.end(), data);
-               } else {
-                       SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] Fail to insert data into m_speak_data. index(%d), app list size(%d)", index, vsize);
-                       pthread_mutex_unlock(&g_speak_data_mutex);
-
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
+               list<speak_data_s*>& speakData = app_data->m_speak_data;
+               int spk_data_size = speakData.size();
+               SLOG(LOG_INFO, tts_tag(), "[DATA INFO] m_speak_data size(%d)", spk_data_size);
+               iter = speakData.insert(speakData.end(), data);
        } catch (const std::bad_alloc&) {
                SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_speak_data (bad_alloc)");
-               pthread_mutex_unlock(&g_speak_data_mutex);
-
                return TTSD_ERROR_OUT_OF_MEMORY;
        }
        SLOG(LOG_ERROR, tts_tag(), "[DATA][%p] utt_id(%d), text(%s), lang(%s), vctype(%d), speed(%d)",
                        *iter, (*iter)->utt_id, (*iter)->text, (*iter)->lang, (*iter)->vctype, (*iter)->speed);
 
        if (1 == data->utt_id)
-               g_app_list[index].utt_id_stopped = 0;
+               app_data->utt_id_stopped = 0;
 
 #ifdef DATA_DEBUG
-       __data_show_text_list(index);
+       __data_show_text_list(*app_data);
 #endif
-       pthread_mutex_unlock(&g_speak_data_mutex);
 
        return TTSD_ERROR_NONE;
 }
 
-int __get_speak_data(int index, speak_data_s** data)
+int __get_speak_data(app_data_s* app_data, speak_data_s** data)
 {
-       if (0 == g_app_list[index].m_speak_data.size()) {
+       if (0 == app_data->m_speak_data.size()) {
 #ifdef DATA_DEBUG
                SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] There is no speak data");
 #endif
                return -1;
        }
 
-       if (!g_app_list[index].m_speak_data.empty()) {
-               std::list<speak_data_s*>::iterator iter = g_app_list[index].m_speak_data.begin();
+       if (!app_data->m_speak_data.empty()) {
+               std::list<speak_data_s*>::iterator iter = app_data->m_speak_data.begin();
                *data = *iter;
-               g_app_list[index].m_speak_data.pop_front();
+               app_data->m_speak_data.pop_front();
        }
 
 #ifdef DATA_DEBUG
-       __data_show_text_list(index);
+       __data_show_text_list(*app_data);
 #endif
        return 0;
 }
 
 int ttsd_data_get_speak_data(int uid, speak_data_s** data)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid(%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       /* mutex is locked */
-       pthread_mutex_lock(&g_speak_data_mutex);
-
-       if (0 != __get_speak_data(index, data)) {
+       if (0 != __get_speak_data(app_data, data)) {
                SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] There is no speak data");
-               pthread_mutex_unlock(&g_speak_data_mutex);
                return -1;
        }
 
-       pthread_mutex_unlock(&g_speak_data_mutex);
-
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_add_sound_data(int uid, sound_data_s* data)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
-       if(index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
@@ -475,146 +510,111 @@ int ttsd_data_add_sound_data(int uid, sound_data_s* data)
                SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] sound data is NULL");
                return TTSD_ERROR_INVALID_PARAMETER;
        }
-       /* mutex is locked */
-       pthread_mutex_lock(&g_sound_data_mutex);
-
        std::list<sound_data_s*>::iterator iter;
 
-       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d), index(%d)", uid, index);
+       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] uid(%d)", uid);
 
        try {
-               int vsize = g_app_list.size();
-               if (index < vsize) {
-                       int wav_data_size = g_app_list[index].m_wav_data.size();
-                       SLOG(LOG_INFO, tts_tag(), "[DATA INFO] m_wav_data size(%d)", wav_data_size);
-                       iter = g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data);
-               } else {
-                       SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] Fail to insert data into m_wav_data. index(%d), app list size(%d)", index, vsize);
-                       pthread_mutex_unlock(&g_sound_data_mutex);
-
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
+               list<sound_data_s*>& wavData = app_data->m_wav_data;
+               int wav_data_size = wavData.size();
+               SLOG(LOG_INFO, tts_tag(), "[DATA INFO] m_wav_data size(%d)", wav_data_size);
+               iter = wavData.insert(wavData.end(), data);
        } catch (const std::bad_alloc&) {
                SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_sound_data (bad_alloc)");
-               pthread_mutex_unlock(&g_sound_data_mutex);
-
                return TTSD_ERROR_OUT_OF_MEMORY;
        }
        SLOG(LOG_ERROR, tts_tag(), "[DATA][%p] utt_id(%d), data(%p) data size(%d), type(%d)", *iter, (*iter)->utt_id, (*iter)->data, (*iter)->data_size, (*iter)->audio_type);
 
 #ifdef DATA_DEBUG
-       __data_show_sound_list(index);
+       __data_show_sound_list(*app_data);
 #endif
 
-       /* mutex is unlocked */
-       pthread_mutex_unlock(&g_sound_data_mutex);
-
        return TTSD_ERROR_NONE;
 }
 
-int __get_sound_data(int index, sound_data_s** data)
+int __get_sound_data(app_data_s* app_data, sound_data_s** data)
 {
-       if (0 == g_app_list[index].m_wav_data.size()) {
+       if (0 == app_data->m_wav_data.size()) {
 #ifdef DATA_DEBUG
                SLOG(LOG_DEBUG, tts_tag(), "[DATA] There is no wav data");
 #endif
                return -1;
        }
 
-       if (!g_app_list[index].m_wav_data.empty()) {
-               std::list<sound_data_s*>::iterator iter = g_app_list[index].m_wav_data.begin();
+       if (!app_data->m_wav_data.empty()) {
+               std::list<sound_data_s*>::iterator iter = app_data->m_wav_data.begin();
                *data = *iter;
-               g_app_list[index].m_wav_data.pop_front();
+               app_data->m_wav_data.pop_front();
        }
 
 #ifdef DATA_DEBUG
-       __data_show_sound_list(index);
+       __data_show_sound_list(*app_data);
 #endif
        return 0;
 }
 
 int ttsd_data_get_sound_data(int uid, sound_data_s** data)
 {
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-
        SLOG(LOG_DEBUG, tts_tag(), "[DATA] sound_data_s: %p", *data);
 
-       if (index < 0)  {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       /* mutex is locked */
-       pthread_mutex_lock(&g_sound_data_mutex);
-
-       if (0 != __get_sound_data(index, data)) {
+       if (0 != __get_sound_data(app_data, data)) {
                SLOG(LOG_DEBUG, tts_tag(), "[DATA] There is no wav data");
-               /* mutex is unlocked */
-               pthread_mutex_unlock(&g_sound_data_mutex);
                return -1;
        }
-       /* mutex is unlocked */
-       pthread_mutex_unlock(&g_sound_data_mutex);
 
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_get_sound_data_size(int uid)
 {
-       int index = 0;
-       int data_size = 0;
-       index = ttsd_data_is_client(uid);
-
-       if (index < 0)  {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
-               return TTSD_ERROR_INVALID_PARAMETER;
+               return -1;
        }
 
-       /* mutex is locked */
-       pthread_mutex_lock(&g_sound_data_mutex);
-       data_size = g_app_list[index].m_wav_data.size();
-
-       /* mutex is unlocked */
-       pthread_mutex_unlock(&g_sound_data_mutex);
-
-       return data_size;
+       return app_data->m_wav_data.size();
 }
 
 int ttsd_data_clear_speak_data(int uid, speak_data_s** speak_data)
 {
-       pthread_mutex_lock(&g_speak_data_mutex);
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
 
-       int index = 0;
-       index = ttsd_data_is_client(uid);
-       if (index >= 0) {
-               if (NULL != *speak_data) {
-                       SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)",
-                                       (*speak_data)->utt_id, (*speak_data)->text, (*speak_data)->lang, (*speak_data)->vctype, (*speak_data)->speed);
-
-                       if (NULL != (*speak_data)->text) {
-                               free((*speak_data)->text);
-                               (*speak_data)->text = NULL;
-                       }
-                       if (NULL != (*speak_data)->lang) {
-                               free((*speak_data)->lang);
-                               (*speak_data)->lang = NULL;
-                       }
+       if (NULL != *speak_data) {
+               SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)",
+                               (*speak_data)->utt_id, (*speak_data)->text, (*speak_data)->lang, (*speak_data)->vctype, (*speak_data)->speed);
 
-                       free(*speak_data);
-                       *speak_data = NULL;
+               if (NULL != (*speak_data)->text) {
+                       free((*speak_data)->text);
+                       (*speak_data)->text = NULL;
+               }
+               if (NULL != (*speak_data)->lang) {
+                       free((*speak_data)->lang);
+                       (*speak_data)->lang = NULL;
                }
-       }
 
-       pthread_mutex_unlock(&g_speak_data_mutex);
+               free(*speak_data);
+               *speak_data = NULL;
+       }
 
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_clear_sound_data(sound_data_s** sound_data)
 {
-       pthread_mutex_lock(&g_sound_data_mutex);
-
        if (NULL != *sound_data) {
                SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] event(%d) data(%p) size(%d) rate(%d) utt(%d)",
                                (*sound_data), (*sound_data)->event, (*sound_data)->data, (*sound_data)->data_size, (*sound_data)->rate, (*sound_data)->utt_id);
@@ -628,103 +628,40 @@ int ttsd_data_clear_sound_data(sound_data_s** sound_data)
                *sound_data = NULL;
        }
 
-       pthread_mutex_unlock(&g_sound_data_mutex);
-
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_clear_data(int uid)
 {
-       int index = 0;
-
-       index = ttsd_data_is_client(uid);
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       int removed_last_uttid = -1;
-       speak_data_s* temp_speak = NULL;
-       sound_data_s* temp_sound = NULL;
-
-       /* free allocated data */
-       pthread_mutex_lock(&g_speak_data_mutex);
-       while(1) {
-               if (0 != __get_speak_data(index, &temp_speak)) {
-                       break;
-               }
-
-               if (NULL != temp_speak) {
-                       SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)",
-                                       temp_speak->utt_id, temp_speak->text, temp_speak->lang, temp_speak->vctype, temp_speak->speed);
-
-                       if (NULL != temp_speak->text) {
-                               free(temp_speak->text);
-                               temp_speak->text = NULL;
-                       }
-                       if (NULL != temp_speak->lang) {
-                               free(temp_speak->lang);
-                               temp_speak->lang = NULL;
-                       }
-                       removed_last_uttid = temp_speak->utt_id;
-
-                       free(temp_speak);
-                       temp_speak = NULL;
-               }
-       }
-
-       if (-1 != removed_last_uttid) {
-               g_app_list[index].utt_id_stopped = removed_last_uttid;
-       }
-
-       g_app_list[index].m_speak_data.clear();
-       pthread_mutex_unlock(&g_speak_data_mutex);
-
-       pthread_mutex_lock(&g_sound_data_mutex);
-       while(1) {
-               if (0 != __get_sound_data(index, &temp_sound)) {
-                       break;
-               }
-
-               if (NULL != temp_sound) {
-                       SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] uid(%d), event(%d) data(%p) size(%d) rate(%d) utt(%d)",
-                               temp_sound, uid, temp_sound->event, temp_sound->data, temp_sound->data_size, temp_sound->rate, temp_sound->utt_id);
-
-                       if (NULL != temp_sound->data) {
-                               free(temp_sound->data);
-                               temp_sound->data = NULL;
-                       }
-
-                       free(temp_sound);
-                       temp_sound = NULL;
-               }
-       }
-
-       g_app_list[index].m_wav_data.clear();
-       pthread_mutex_unlock(&g_sound_data_mutex);
+       __clean_data(*app_data);
 
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_get_client_state(int uid, app_tts_state_e* state)
 {
-       int index = 0;
-
-       index = ttsd_data_is_client(uid);
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       lock_guard<mutex> lock(g_app_state_mutex);
-       *state = g_app_list[index].state;
+       *state = app_data->state;
 
        return TTSD_ERROR_NONE;
 }
 
 static int __get_playing_app_uid()
 {
-       for (auto app : g_app_list) {
+       for (auto& app : g_app_list) {
                if (APP_STATE_PLAYING == app.state) {
                        return app.uid;
                }
@@ -735,16 +672,14 @@ static int __get_playing_app_uid()
 
 int ttsd_data_set_client_state(int uid, app_tts_state_e state)
 {
-       int index = 0;
-
-       index = ttsd_data_is_client(uid);
-       if (index < 0) {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       lock_guard<mutex> lock(g_app_state_mutex);
-       if (g_app_list[index].state == state) {
+       if (app_data->state == state) {
                SLOG(LOG_ERROR, tts_tag(), "[DATA] Already current state. (%d)", state);
                return TTSD_ERROR_NONE;
        }
@@ -756,14 +691,14 @@ int ttsd_data_set_client_state(int uid, app_tts_state_e state)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       g_app_list[index].state = state;
+       app_data->state = state;
 
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_get_current_playing()
 {
-       lock_guard<mutex> lock(g_app_state_mutex);
+       lock_guard<mutex> lock(g_app_data_mutex);
        int uid = __get_playing_app_uid();
 
        return uid;
@@ -782,9 +717,9 @@ int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data)
 
        /* Copy app info */
        vector<app_data_s> temp_app_list;
-       int vsize = g_app_list.size();
 
-       g_app_state_mutex.lock();
+       unique_lock<mutex> lock(g_app_data_mutex);
+       int vsize = g_app_list.size();
        for (int i = 0; i < vsize; i++) {
                app_data_s app = {0, };
                app.pid = g_app_list[i].pid;
@@ -794,7 +729,7 @@ int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data)
 
                temp_app_list.insert(temp_app_list.end(), app);
        }
-       g_app_state_mutex.unlock();
+       lock.unlock();
 
        for (int i = 0; i < vsize; i++) {
                SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, temp_app_list[i].pid, temp_app_list[i].uid, temp_app_list[i].state);
@@ -808,15 +743,14 @@ int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data)
 
 bool ttsd_data_is_uttid_valid(int uid, int uttid)
 {
-       int index = 0;
-
-       index = ttsd_data_is_client(uid);
-       if (index < 0)  {
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
                SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return false;
        }
 
-       if (uttid < g_app_list[index].utt_id_stopped)
+       if (uttid < app_data->utt_id_stopped)
                return false;
 
        return true;
@@ -824,6 +758,7 @@ bool ttsd_data_is_uttid_valid(int uid, int uttid)
 
 int ttsd_data_get_same_pid_client_count(int pid)
 {
+       lock_guard<mutex> lock(g_app_data_mutex);
        int vsize = g_app_list.size();
        int number = 0;
 
@@ -838,55 +773,41 @@ int ttsd_data_get_same_pid_client_count(int pid)
 
 int ttsd_data_save_error_log(int uid, FILE* fp)
 {
-       int ret;
-       int pid = ttsd_data_get_pid(uid);
+       lock_guard<mutex> lock(g_app_data_mutex);
+       app_data_s* app_data = __get_client_app_data(uid);
+       if (nullptr == app_data) {
+               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid client");
+               return -1;
+       }
 
        /* pid */
-       if (pid <= 0) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get pid");
-       } else {
-               fprintf(fp, "pid - %d", pid);
-       }
+       fprintf(fp, "pid - %d", app_data->pid);
+
        /* app state */
-       app_tts_state_e state;
-       ret = ttsd_data_get_client_state(uid, &state);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get app state");
-       } else {
-               fprintf(fp, "app state - %d", state);
-       }
+       fprintf(fp, "app state - %d", app_data->state);
 
-       int index = 0;
-       unsigned int i;
 
-       index = ttsd_data_is_client(uid);
-       if (0 > index) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid client");
-               return -1;
-       }
 
        /* get sound data */
        fprintf(fp, "----- Sound list -----");
-
-       i = 0;
-       if (!g_app_list[index].m_wav_data.empty()) {
+       if (!app_data->m_wav_data.empty()) {
+               unsigned int i = 0;
                std::list<sound_data_s*>::iterator iter;
-               for (iter = g_app_list[index].m_wav_data.begin(); (NULL != *iter && iter != g_app_list[index].m_wav_data.end()); ++iter) {
+               for (iter = app_data->m_wav_data.begin(); (NULL != *iter && iter != app_data->m_wav_data.end()); ++iter) {
                        SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%d), uttid(%d), type(%d)",
                                        i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
                        i++;
                }
        }
-
        fprintf(fp, "----------------------");
 
        /* get speck data */
        fprintf(fp, "----- Text list -----");
 
-       i = 0;
-       if (!g_app_list[index].m_speak_data.empty()) {
+       if (!app_data->m_speak_data.empty()) {
+               unsigned int i = 0;
                std::list<speak_data_s*>::iterator iter_speak;
-               for (iter_speak = g_app_list[index].m_speak_data.begin(); (NULL != *iter_speak && iter_speak != g_app_list[index].m_speak_data.end()); ++iter_speak) {
+               for (iter_speak = app_data->m_speak_data.begin(); (NULL != *iter_speak && iter_speak != app_data->m_speak_data.end()); ++iter_speak) {
                        SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)",
                                        i, *iter_speak, (*iter_speak)->lang, (*iter_speak)->vctype, (*iter_speak)->speed, (*iter_speak)->utt_id, (*iter_speak)->text);
                        i++;