Change thread model to std::thread
authorChaJiwon <jw_wonny.cha@samsung.com>
Wed, 8 Jul 2015 06:25:28 +0000 (15:25 +0900)
committerUze Choi <uzchoi@samsung.com>
Wed, 8 Jul 2015 08:15:18 +0000 (08:15 +0000)
Use condition variable to check expired time.
Add lock_guard to insert & cancel timerCBList.
Change Singleton instance pointer from shared pointer to pointer.

Change-Id: I0fc13809777691396140910eac6648b0ea5cfe57
Signed-off-by: ChaJiwon <jw_wonny.cha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1570
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/resource-manipulation/modules/common/expiryTimer/include/ExpiryTimer.h
service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer.cpp
service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.cpp
service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.h

index 8562a31..df6ecbe 100644 (file)
 #define _EXPIRY_TIMER_H_
 
 #include <functional>
-#include <list>
 #include <iostream>
-
-#include "ExpiryTimer_Impl.h"
-
-using namespace std;
-
-typedef unsigned int TimerID;
-typedef function<void*(TimerID)> TimerCB;
+#include <list>
 
 class ExpiryTimer
 {
 public:
+    typedef unsigned int TimerID;
+    typedef std::function<void*(TimerID)> TimerCB;
+    typedef long long DelayMilliSec;
+
+public:
     ExpiryTimer();
     ~ExpiryTimer();
 
-    TimerID requestTimer(long long sec, TimerCB);
-    void cancelTimer(TimerID timerID);
+public:
+    TimerID postTimer(DelayMilliSec sec, TimerCB);
+    bool cancelTimer(TimerID timerID);
 
 private:
-
-    long long countExpiredTime(long long sec);
-
-    list<TimerID> mTimerIDList;
-    ExpiryTimer_Impl* timerPtr;
+    std::list<TimerID> mTimerIDList;
 };
 
 #endif //_TIMER_H_
index e70cd73..e4279b9 100644 (file)
@@ -19,8 +19,9 @@
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 #include "ExpiryTimer.h"
+#include "ExpiryTimer_Impl.h"
 
-#include <ctime>
+ExpiryTimer_Impl* timerPtr;
 
 ExpiryTimer::ExpiryTimer()
 {
@@ -29,7 +30,6 @@ ExpiryTimer::ExpiryTimer()
 
 ExpiryTimer::~ExpiryTimer()
 {
-    // clear ExpiryTimer id
     for(auto it : mTimerIDList)
     {
         timerPtr->cancelTimer(it);
@@ -37,28 +37,22 @@ ExpiryTimer::~ExpiryTimer()
     mTimerIDList.clear();
 }
 
-TimerID ExpiryTimer::requestTimer(long long sec, TimerCB cb)
+ExpiryTimer::TimerID ExpiryTimer::postTimer(long long sec, TimerCB cb)
 {
-    TimerID retID;
-    long long expiredTime;
-
-    expiredTime = countExpiredTime(sec);
-    retID = timerPtr->requestTimer(expiredTime, cb);
+    TimerID retID = 0;
 
+    retID = timerPtr->postTimer(sec, cb);
     mTimerIDList.push_back(retID);
 
     return retID;
 }
 
-void ExpiryTimer::cancelTimer(TimerID timerID)
+bool ExpiryTimer::cancelTimer(TimerID timerID)
 {
-    timerPtr->cancelTimer(timerID);
+    bool ret = false;
+
+    ret = timerPtr->cancelTimer(timerID);
     mTimerIDList.remove(timerID);
-}
 
-long long ExpiryTimer::countExpiredTime(long long sec)
-{
-    time_t curSEC;
-    time(&curSEC);
-    return curSEC + sec;
+    return ret;
 }
index 84f489c..99d9a58 100644 (file)
 #include <cstdlib>
 #include <utility>
 
-
-ExpiryTimer_Impl* ExpiryTimer_Impl::s_instance = nullptr;
-std::mutex ExpiryTimer_Impl::s_mutexForCreation;
-bool ExpiryTimer_Impl::isDestroyed = false;
+ExpiryTimer_Impl* ExpiryTimer_Impl::s_instance;
+std::once_flag ExpiryTimer_Impl::mflag;
 
 ExpiryTimer_Impl::ExpiryTimer_Impl()
 {
-    threadNum = 0;
-    checkThreadRun = false;
+    createChecker();
 }
 
 ExpiryTimer_Impl::~ExpiryTimer_Impl()
 {
-    isDestroyed = true;
-    int status;
-
-    pthread_join(checker_th, (void **)&status);
-    pthread_detach(checker_th);
-}
-
-void ExpiryTimer_Impl::killTimer()
-{
-    s_instance->~ExpiryTimer_Impl();
 }
 
 ExpiryTimer_Impl* ExpiryTimer_Impl::getInstance()
 {
-    if(isDestroyed)
-    {
-        new(s_instance) ExpiryTimer_Impl;
-        atexit(killTimer);
-        isDestroyed = false;
-    }
-    else if(s_instance == nullptr)
-    {
-        static ExpiryTimer_Impl tmp_instance;
-        s_instance = &tmp_instance;
-    }
+    std::call_once(mflag, [](){ s_instance = new ExpiryTimer_Impl; });
     return s_instance;
 }
 
-TimerID ExpiryTimer_Impl::requestTimer(long long sec, TimerCB cb)
+ExpiryTimer_Impl::Id ExpiryTimer_Impl::postTimer(DelayMilliSec msec, TimerCb cb)
 {
-    if(threadNum < EXPIRY_THREAD_LIST)
-    {
-        unsigned int timerID = generateTimerID();
-        ExpiryTimer_Impl::getInstance()->registerCBTimer(sec, cb, timerID);
-        return timerID;
-    }
-    else
-        return OVERFLOW_THREAD_NUM;
+    Id retID;
+    retID = generateID();
+    milliSeconds delay(msec);
+    insertTimerCBInfo(countExpireTime(delay), cb, retID);
+
+    return retID;
 }
 
-void ExpiryTimer_Impl::cancelTimer(TimerID timerID)
+bool ExpiryTimer_Impl::cancelTimer(Id timerID)
 {
-    for( auto it : mTimerCBList)
+    std::lock_guard<std::mutex> lockf(m_mutex);
+    bool ret = false;
+    for(auto it: mTimerCBList)
     {
         if(it.second.m_id == timerID)
         {
-            mTimerCBList.erase(it.first);
-            timerIDList.remove(it.second.m_id);
+            if(mTimerCBList.erase(it.first)!=0)
+                ret = true;
+            else
+                ret = false;
         }
     }
+    return ret;
 }
 
-void ExpiryTimer_Impl::registerCBTimer(long long countSEC, TimerCB _cb, TimerID id)
+void ExpiryTimer_Impl::insertTimerCBInfo(ExpiredTime msec, TimerCb cb, Id timerID)
 {
-    timerCBInfo newInfo = {id, _cb};
-    mTimerCBList.insert(multimap<long long, ExpiryTimer_Impl::timerCBInfo>::value_type(countSEC, newInfo));
+    std::lock_guard<std::mutex> lockf(m_mutex);
+    TimerCBInfo newInfo = {timerID, cb};
+    mTimerCBList.insert(std::multimap<ExpiredTime, TimerCBInfo>::value_type(msec, newInfo));
+    m_cond.notify_all();
+}
 
-    if (checkThreadRun == false)
-    {
-        initThCheck();
-    }
+ExpiryTimer_Impl::ExpiredTime ExpiryTimer_Impl::countExpireTime(milliDelayTime msec)
+{
+    auto now = std::chrono::system_clock::now();
+    milliSeconds ret = std::chrono::duration_cast<milliSeconds>(now.time_since_epoch()) + msec;
+
+    return ret;
 }
 
-void ExpiryTimer_Impl::checkTimeOut()
+ExpiryTimer_Impl::Id ExpiryTimer_Impl::generateID()
 {
-    while (1)
-    {
-        if(mTimerCBList.empty())
-        {
-            checkThreadRun = false;
-            break;
-        }
-       else
+    srand(time(NULL));
+    Id retID = rand();
+
+    for(std::multimap<ExpiredTime, TimerCBInfo>::iterator it=mTimerCBList.begin(); it!=mTimerCBList.end(); ++it)
+     {
+       if((*it).second.m_id == retID || retID == 0)
         {
-           long long curSEC = getSeconds(0);
-           long long expireTime;
-           expireTime = mTimerCBList.begin()->first;
-
-           if(curSEC >= expireTime)
-           {
-               initThExecutor(mTimerCBList.begin()->second);
-               mTimerCBList.erase(mTimerCBList.begin());
-           }
+            retID = rand();
+            it = mTimerCBList.begin();
         }
-       usleep(SLEEP_TIME);
-    }
+     }
+    return retID;
 }
 
-void* ExpiryTimer_Impl::threadChecker(void * msg)
+void ExpiryTimer_Impl::createChecker()
 {
-    if(s_instance != nullptr)
-        s_instance->checkTimeOut();
-    return NULL;
+    check = std::thread(&ExpiryTimer_Impl::doChecker, this);
 }
 
-void ExpiryTimer_Impl::initThCheck()
+void ExpiryTimer_Impl::doChecker()
 {
-    int retThreadCreation;
-
-    retThreadCreation = pthread_create(&checker_th, NULL, s_instance->threadChecker, NULL);
-    if (retThreadCreation != 0)
-    {
-        return;
-    }
-    else
+    while(true)
     {
-        checkThreadRun = true;
-    }
-}
+        std::unique_lock<std::mutex> ul(cond_mutex);
 
-void *ExpiryTimer_Impl::threadExecutor(void * msg)
-{
-    TimerCB cb;
-    timerCBInfo *curCBInfo;
-    curCBInfo= (timerCBInfo *) msg;
+        if(mTimerCBList.empty())
+        {
+            m_cond.wait_for(ul, std::chrono::seconds(CHECKER_WAIT_TIME));
+        }
+        else
+        {
+            ExpiredTime expireTime;
+            expireTime = mTimerCBList.begin()->first;
 
-    cb = curCBInfo->m_pCB;
-    cb(curCBInfo->m_id);
+            auto now = std::chrono::system_clock::now();
+            milliSeconds waitTime = expireTime - std::chrono::duration_cast<milliSeconds>(now.time_since_epoch());
+            m_cond.wait_for(ul, waitTime);
 
-    return NULL;
+            auto callTime = std::chrono::system_clock::now();
+            doExecutor(std::chrono::duration_cast<milliSeconds>(callTime.time_since_epoch()));
+        }
+    }
 }
 
-void ExpiryTimer_Impl::initThExecutor(timerCBInfo cbInfo)
+void ExpiryTimer_Impl::doExecutor(ExpiredTime expireTime)
 {
-
-    int retThreadCreation;
-    int status;
-    pthread_t executor_th;
-
-    retThreadCreation = pthread_create(&executor_th, NULL, ExpiryTimer_Impl::threadExecutor, (void *)&cbInfo);
-    threadNum++;
-
-    if (retThreadCreation != 0)
+    for(auto it: mTimerCBList)
     {
-        return;
-    }
-    else
-    {
-        pthread_join(executor_th, (void **)&status);
-        pthread_detach(executor_th);
-        threadNum--;
+        if(it.first <= expireTime)
+        {
+            new ExecutorThread(it.second);
+            mTimerCBList.erase(mTimerCBList.begin());
+        }
+        else
+            break;
     }
 }
 
-TimerID ExpiryTimer_Impl::generateTimerID()
+// ExecuterThread Class
+ExpiryTimer_Impl::ExecutorThread::ExecutorThread(TimerCBInfo cbInfo)
 {
-    srand(time(NULL));
-    unsigned int retID = rand();
-
-    for(auto it : timerIDList)
-     {
-       if(it == retID || retID == 0)
-        {
-            retID = rand();
-            it = s_instance->timerIDList.front();
-        }
-     }
-    timerIDList.push_back(retID);
+    execute = std::thread(&ExpiryTimer_Impl::ExecutorThread::executorFunc, this, cbInfo);
+}
 
-    return retID;
+ExpiryTimer_Impl::ExecutorThread::~ExecutorThread()
+{
+    execute.detach();
 }
 
-long long ExpiryTimer_Impl::getSeconds(long long sec)
+void ExpiryTimer_Impl::ExecutorThread::executorFunc(TimerCBInfo cbInfo)
 {
-    time_t curSEC;
-    time(&curSEC);
-    long long retSEC = curSEC + sec;
-    return retSEC;
+    cbInfo.m_cb(cbInfo.m_id);
 }
index 5c5b526..a5b8a0c 100644 (file)
 #ifndef _EXPIRY_TIMER_Impl_H_
 #define _EXPIRY_TIMER_Impl_H_
 
-#include <mutex>
-#include <pthread.h>
+// CHECKER_WAIT_TIME : checker thread waits new request for 10000 seconds
+#define CHECKER_WAIT_TIME 10000
+
+#include <iostream>
 #include <functional>
-#include <list>
 #include <map>
-#include <iostream>
-#include <new>
-
-#define EXPIRY_THREAD_LIST 50
-#define OVERFLOW_THREAD_NUM -1
-// Current checker thread design have to get checking interval.
-// SLEEP_TIME value will be removed later.
-#define SLEEP_TIME 50000
-
-using namespace std;
-
-typedef unsigned int TimerID;
-typedef function<void*(TimerID)> TimerCB;
+#include <mutex>
+#include <thread>
+#include <chrono>
+#include <condition_variable>
 
 class ExpiryTimer_Impl
 {
+public:
+    typedef unsigned int Id;
+    typedef std::function<void*(Id)> TimerCb;
+
+    typedef long long DelayMilliSec;
+    typedef std::chrono::milliseconds milliSeconds;
+    typedef std::chrono::duration<int64_t, std::milli> milliDelayTime;
+    typedef std::chrono::duration<int64_t, std::milli> ExpiredTime;
+
 private:
-   struct timerCBInfo
+    struct TimerCBInfo
     {
-       TimerID m_id;
-       TimerCB m_pCB;
+        Id m_id;
+        TimerCb m_cb;
     };
 
-    ExpiryTimer_Impl();
-    ExpiryTimer_Impl(const ExpiryTimer_Impl & other);
-    ~ExpiryTimer_Impl();
-
 public:
-
-     static ExpiryTimer_Impl * getInstance();
-
-    TimerID requestTimer(long long sec, TimerCB);
-    void cancelTimer(TimerID timerID);
+   ~ExpiryTimer_Impl();
 
 private:
+   ExpiryTimer_Impl();
+
+public:
+    static ExpiryTimer_Impl* getInstance();
 
-   static void killTimer();
-   static void *threadExecutor(void * msg);
-   static void *threadChecker(void * msg);
+    Id postTimer(DelayMilliSec, TimerCb);
+    bool cancelTimer(Id);
 
-   void registerCBTimer(long long countSEC, TimerCB _cb, TimerID id);
-   void initThCheck();
-   void initThExecutor(timerCBInfo cbInfo);
-   void checkTimeOut();
+private:
+   Id generateID();
 
-   TimerID generateTimerID();
-   long long getSeconds(long long sec);
+   void insertTimerCBInfo(ExpiredTime, TimerCb ,Id);
+   ExpiredTime countExpireTime(milliSeconds);
 
-public:
+   void createChecker();
+   void doChecker();
 
-    list<TimerID> timerIDList;
+   void doExecutor(ExpiredTime);
 
 private:
+   static ExpiryTimer_Impl* s_instance;
+   static std::once_flag mflag;
 
-    static ExpiryTimer_Impl * s_instance;
-    static mutex s_mutexForCreation;
-    static bool isDestroyed;
+   std::multimap<ExpiredTime, TimerCBInfo> mTimerCBList;
 
-    multimap<long long, timerCBInfo> mTimerCBList;
-    bool checkThreadRun;
-    list<int> mExecutorIndexList;
-    int threadNum;
+   std::thread check;
+   std::mutex m_mutex;
+   std::mutex cond_mutex;
+   std::condition_variable m_cond;
 
-    pthread_t checker_th;
-    pthread_mutex_t checker_mutex;
+public:
+   class ExecutorThread
+   {
+   public:
+       ExecutorThread(TimerCBInfo);
+       ~ExecutorThread();
+
+   public:
+       void executorFunc(TimerCBInfo);
+
+   private:
+       std::thread execute;
+   };
 };
+
 #endif //_EXPIRY_TIMER_Impl_H_