From c80d54da40610cf5d276bb62fc0e784e1bcfca1a Mon Sep 17 00:00:00 2001 From: ChaJiwon Date: Wed, 8 Jul 2015 15:25:28 +0900 Subject: [PATCH] Change thread model to std::thread 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 Reviewed-on: https://gerrit.iotivity.org/gerrit/1570 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi --- .../common/expiryTimer/include/ExpiryTimer.h | 25 +-- .../modules/common/expiryTimer/src/ExpiryTimer.cpp | 26 +-- .../common/expiryTimer/src/ExpiryTimer_Impl.cpp | 208 ++++++++------------- .../common/expiryTimer/src/ExpiryTimer_Impl.h | 103 +++++----- 4 files changed, 156 insertions(+), 206 deletions(-) diff --git a/service/resource-manipulation/modules/common/expiryTimer/include/ExpiryTimer.h b/service/resource-manipulation/modules/common/expiryTimer/include/ExpiryTimer.h index 8562a31..df6ecbe 100644 --- a/service/resource-manipulation/modules/common/expiryTimer/include/ExpiryTimer.h +++ b/service/resource-manipulation/modules/common/expiryTimer/include/ExpiryTimer.h @@ -22,31 +22,26 @@ #define _EXPIRY_TIMER_H_ #include -#include #include - -#include "ExpiryTimer_Impl.h" - -using namespace std; - -typedef unsigned int TimerID; -typedef function TimerCB; +#include class ExpiryTimer { public: + typedef unsigned int TimerID; + typedef std::function 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 mTimerIDList; - ExpiryTimer_Impl* timerPtr; + std::list mTimerIDList; }; #endif //_TIMER_H_ diff --git a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer.cpp b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer.cpp index e70cd73..e4279b9 100644 --- a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer.cpp +++ b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer.cpp @@ -19,8 +19,9 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "ExpiryTimer.h" +#include "ExpiryTimer_Impl.h" -#include +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; } diff --git a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.cpp b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.cpp index 84f489c..99d9a58 100644 --- a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.cpp +++ b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.cpp @@ -25,185 +25,139 @@ #include #include - -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 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::value_type(countSEC, newInfo)); + std::lock_guard lockf(m_mutex); + TimerCBInfo newInfo = {timerID, cb}; + mTimerCBList.insert(std::multimap::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(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::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 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(now.time_since_epoch()); + m_cond.wait_for(ul, waitTime); - return NULL; + auto callTime = std::chrono::system_clock::now(); + doExecutor(std::chrono::duration_cast(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); } diff --git a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.h b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.h index 5c5b526..a5b8a0c 100644 --- a/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.h +++ b/service/resource-manipulation/modules/common/expiryTimer/src/ExpiryTimer_Impl.h @@ -21,75 +21,82 @@ #ifndef _EXPIRY_TIMER_Impl_H_ #define _EXPIRY_TIMER_Impl_H_ -#include -#include +// CHECKER_WAIT_TIME : checker thread waits new request for 10000 seconds +#define CHECKER_WAIT_TIME 10000 + +#include #include -#include #include -#include -#include - -#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 TimerCB; +#include +#include +#include +#include class ExpiryTimer_Impl { +public: + typedef unsigned int Id; + typedef std::function TimerCb; + + typedef long long DelayMilliSec; + typedef std::chrono::milliseconds milliSeconds; + typedef std::chrono::duration milliDelayTime; + typedef std::chrono::duration 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 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 mTimerCBList; - multimap mTimerCBList; - bool checkThreadRun; - list 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_ -- 2.7.4