[Archive] Remove TODO about thread safety
authorPiotr Kosko <p.kosko@samsung.com>
Tue, 6 Oct 2015 11:51:09 +0000 (13:51 +0200)
committerPiotr Kosko <p.kosko@samsung.com>
Tue, 6 Oct 2015 11:51:13 +0000 (13:51 +0200)
[Feature] Execution moved to single background thread to ensure that all operations are done
  sequentially.

[Verification] Code compiles without errors.
  All operations are done in one background thread.
  TCT passrate is 100%.

Change-Id: Ie79e61413f258ae3ace3ae37c56ce942f24cd9fb
Signed-off-by: Piotr Kosko <p.kosko@samsung.com>
src/archive/archive_callback_data.cc
src/archive/archive_file.cc
src/archive/archive_file.h
src/archive/archive_manager.cc
src/archive/archive_manager.h

index 2efbaefb2a829e37ff5646164b7c1cadf17c5275..81bb82111aa34f27b57a4f0c053f07900ad8fb66 100755 (executable)
@@ -603,9 +603,6 @@ PlatformResult AddProgressCallback::executeOperation(ArchiveFilePtr archive_file
 
     LoggerD("Update decompressed size and entry list");
     // update informations about decompressed size and entry list
-    // TODO FIXME need to resolve problem with access to file by
-    // more than one thread
-
     return archive_file_ptr->updateListOfEntries();
 }
 
index e929740dd6755a255a8acf5a80eeec17557308f0..68e772d090f85f8e2715adfd1d9de3e9fa5927cb 100755 (executable)
@@ -175,20 +175,20 @@ gboolean ArchiveFile::callErrorCallback(void* data)
     return false;
 }
 
-void* ArchiveFile::taskManagerThread(void *data)
+void ArchiveFile::taskManagerThread(gpointer data, gpointer user_data)
 {
     LoggerD("Entered");
     ArchiveFileHolder* archive_file_holder = static_cast<ArchiveFileHolder*>(data);
     if (!archive_file_holder) {
         LoggerE("archive_file_holder is null");
-        return NULL;
+        return;
     }
 
     if (!archive_file_holder->ptr){
         LoggerE("archive_file is null");
         delete archive_file_holder;
         archive_file_holder = NULL;
-        return NULL;
+        return;
     }
 
     PlatformResult result(ErrorCode::NO_ERROR);
@@ -235,7 +235,7 @@ void* ArchiveFile::taskManagerThread(void *data)
     delete archive_file_holder;
     archive_file_holder = NULL;
 
-    return NULL;
+    return;
 }
 
 PlatformResult ArchiveFile::addOperation(OperationCallbackData* callback)
@@ -251,23 +251,21 @@ PlatformResult ArchiveFile::addOperation(OperationCallbackData* callback)
         size = m_task_queue.size();
     }
     if(1 == size) {
-        pthread_t thread;
         ArchiveFileHolder* holder = new(std::nothrow) ArchiveFileHolder();
         if(!holder) {
             LoggerE("Memory allocation error");
             return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation error");
         }
         holder->ptr = shared_from_this();
-        if (pthread_create(&thread, NULL, taskManagerThread,
-                static_cast<void*>(holder))) {
-            LoggerE("Thread creation failed");
-            delete holder;
-            holder = NULL;
-            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Thread creation failed");
-        }
 
-        if (pthread_detach(thread)) {
-            LoggerE("Thread detachment failed");
+        // operations would be executed asynchronously on one background thread
+        // (no risk of parallel operations on file)
+        if (!g_thread_pool_push(ArchiveManager::getInstance().getThreadPool(),
+                                static_cast<gpointer>(holder), NULL)) {
+          LoggerE("Thread creation failed");
+          delete holder;
+          holder = NULL;
+          return PlatformResult(ErrorCode::UNKNOWN_ERR, "Thread creation failed");
         }
     }
     return PlatformResult(ErrorCode::NO_ERROR);
index 61f6a6da8ba7bd3c096183c9ecb75ec0e593cb27..c81b86d7b14b5ce5ae2c3d973c4ea8b834b3e205 100755 (executable)
@@ -156,7 +156,7 @@ private:
     static gboolean getEntriesTaskCompleteCB(void *data);
     static gboolean getEntryByNameTaskCompleteCB(void *data);
 
-    static void* taskManagerThread(void *data);
+    static void taskManagerThread(gpointer data, gpointer user_data);
     common::PlatformResult addOperation(OperationCallbackData* callback);
     static gboolean callErrorCallback(void* data);
 
index 97a9998cc4c779d667f62eaa8c9314d965a6bb66..ebe596413f24f0eb9cf821b720ef0c44933ad12c 100755 (executable)
@@ -28,11 +28,16 @@ ArchiveManager::ArchiveManager():
         m_next_unique_id(0)
 {
     LoggerD("Initialize ArchiveManager");
+    // create thread pool with max threads = 1 to make API calls async but
+    // only one call at time
+    m_pool = g_thread_pool_new(ArchiveFile::taskManagerThread, NULL, 1, true, NULL);
 }
 
 ArchiveManager::~ArchiveManager()
 {
     LoggerD("Deinitialize ArchiveManager");
+    //finish only current task and wait for thread to stop
+    g_thread_pool_free(m_pool, true, true);
 }
 
 ArchiveManager& ArchiveManager::getInstance()
@@ -42,6 +47,11 @@ ArchiveManager& ArchiveManager::getInstance()
     return instance;
 }
 
+GThreadPool* ArchiveManager::getThreadPool()
+{
+  return m_pool;
+}
+
 void ArchiveManager::abort(long operation_id)
 {
     LoggerD("Entered");
index 354edb09e5b78f053669ab544c2e585d3f1f83c9..fb9f19aaf4eb7e607a5c9a448c497572b6917398 100755 (executable)
@@ -20,6 +20,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <glib.h>
 
 #include "archive_file.h"
 #include "archive_callback_data.h"
@@ -41,6 +42,7 @@ public:
     long addPrivData(ArchiveFilePtr archive_file_ptr);
     common::PlatformResult getPrivData(long handle, ArchiveFilePtr* archive_file);
     common::PlatformResult open(OpenCallbackData* callback);
+    GThreadPool* getThreadPool();
 
 private:
     ArchiveManager();
@@ -51,6 +53,9 @@ private:
     ArchiveFileMap m_priv_map;
 
     long m_next_unique_id;
+
+    //! Handler for thread pool
+    GThreadPool* m_pool;
 };
 
 } // archive