1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "ExpiryTimerImpl.h"
27 ExpiryTimerImpl* ExpiryTimerImpl::s_instance = nullptr;
28 std::once_flag* ExpiryTimerImpl::s_flag = new std::once_flag;
30 ExpiryTimerImpl::ExpiryTimerImpl()
32 m_engine = std::default_random_engine(m_device());
33 m_checkerThread = std::thread(&ExpiryTimerImpl::runChecker, this);
36 ExpiryTimerImpl::~ExpiryTimerImpl()
38 m_checkerThread.join();
41 ExpiryTimerImpl* ExpiryTimerImpl::getInstance()
43 std::call_once(*s_flag, [](){ s_instance = new ExpiryTimerImpl(); });
47 ExpiryTimerImpl::Id ExpiryTimerImpl::post(DelayInMilliSec millisec, CB cb)
49 Id retID = generateId();
51 MilliSeconds delay(millisec);
52 insertTimerCBInfo(countExpireTime(delay), cb, retID);
57 bool ExpiryTimerImpl::cancel(Id id)
60 std::lock_guard<std::mutex> lockf(m_mutex);
61 for(auto it: m_timerCBList)
63 if(it.second.m_id == id)
65 if(m_timerCBList.erase(it.first)!=0)
74 void ExpiryTimerImpl::insertTimerCBInfo(ExpiredTime msec, CB cb, Id id)
76 TimerCBInfo newInfo{id, cb};
77 std::lock_guard<std::mutex> lockf(m_mutex);
78 m_timerCBList.insert({msec, newInfo});
82 ExpiryTimerImpl::ExpiredTime ExpiryTimerImpl::countExpireTime(MilliSeconds msec)
84 auto now = std::chrono::system_clock::now();
85 return std::chrono::duration_cast<MilliSeconds>(now.time_since_epoch()) + msec;
88 ExpiryTimerImpl::Id ExpiryTimerImpl::generateId()
90 Id retID = m_dist(m_device);
92 for(auto it = m_timerCBList.begin(); it != m_timerCBList.end(); )
94 if(it->second.m_id == retID || retID == 0)
96 retID = m_dist(m_device);
97 it = m_timerCBList.begin();
108 void ExpiryTimerImpl::runChecker()
112 std::unique_lock<std::mutex> ul(m_mutex);
114 if(m_timerCBList.empty())
120 ExpiredTime expireTime;
121 expireTime = m_timerCBList.begin()->first;
123 auto now = std::chrono::system_clock::now();
124 MilliSeconds waitTime = expireTime - std::chrono::duration_cast<MilliSeconds>(now.time_since_epoch());
125 m_cond.wait_for(ul, waitTime);
127 auto callTime = std::chrono::system_clock::now();
128 runExecutor(std::chrono::duration_cast<MilliSeconds>(callTime.time_since_epoch()));
133 void ExpiryTimerImpl::runExecutor(ExpiredTime expireTime)
135 for(auto it = m_timerCBList.begin(); it != m_timerCBList.end(); ++it)
137 if(it->first <= expireTime)
139 ExecutorThread executor(it->second);
140 m_timerCBList.erase(it);
149 // ExecutorThread Class
150 ExpiryTimerImpl::ExecutorThread::ExecutorThread(TimerCBInfo cbInfo)
152 m_executorThread = std::thread(&ExpiryTimerImpl::ExecutorThread::executorFunc, this, cbInfo);
155 ExpiryTimerImpl::ExecutorThread::~ExecutorThread()
157 m_executorThread.detach();
160 void ExpiryTimerImpl::ExecutorThread::executorFunc(TimerCBInfo cbInfo)
162 cbInfo.m_cB(cbInfo.m_id);