• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <map>
16 #include "dhcp_thread.h"
17 #include "dhcp_logger.h"
18 #if DHCP_FFRT_ENABLE
19 #include "ffrt_inner.h"
20 #else
21 #include <atomic>
22 #include <chrono>
23 #include <condition_variable>
24 #include <deque>
25 #include <memory>
26 #include <mutex>
27 #include <thread>
28 #ifndef OHOS_ARCH_LITE
29 #include "common_timer_errors.h"
30 #include "timer.h"
31 #endif
32 #endif
33 namespace OHOS {
34 namespace DHCP {
35 DEFINE_DHCPLOG_DHCP_LABEL("DhcpThread");
36 #if DHCP_FFRT_ENABLE
37 class DhcpThread::DhcpThreadImpl {
38 public:
DhcpThreadImpl(const std::string & threadName)39     DhcpThreadImpl(const std::string &threadName)
40     {
41         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
42         if (eventQueue != nullptr) {
43             DHCP_LOGI("DhcpThreadImpl already init.");
44             return;
45         }
46         eventQueue = std::make_shared<ffrt::queue>(threadName.c_str());
47         DHCP_LOGI("DhcpThreadImpl: Create a new eventQueue, threadName:%{public}s", threadName.c_str());
48     }
~DhcpThreadImpl()49     ~DhcpThreadImpl()
50     {
51         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
52         DHCP_LOGI("DhcpThread: ~DhcpThread");
53         if (eventQueue) {
54             eventQueue = nullptr;
55         }
56         for (auto iter = taskMap_.begin(); iter != taskMap_.end();) {
57             iter->second = nullptr;
58             iter = taskMap_.erase(iter);
59         }
60     }
PostSyncTask(Callback & callback)61     bool PostSyncTask(Callback &callback)
62     {
63         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
64         if (eventQueue == nullptr) {
65             DHCP_LOGE("PostSyncTask: eventQueue is nullptr!");
66             return false;
67         }
68         DHCP_LOGD("PostSyncTask Enter");
69         ffrt::task_handle handle = eventQueue->submit_h(callback);
70         if (handle == nullptr) {
71             return false;
72         }
73         eventQueue->wait(handle);
74         return true;
75     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)76     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
77     {
78         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
79         if (eventQueue == nullptr) {
80             DHCP_LOGE("PostAsyncTask: eventQueue is nullptr!");
81             return false;
82         }
83         int64_t delayTimeUs = delayTime * 1000;
84         DHCP_LOGD("PostAsyncTask Enter");
85         ffrt::task_handle handle = eventQueue->submit_h(callback, ffrt::task_attr().delay(delayTimeUs));
86         return handle != nullptr;
87     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0)88     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0)
89     {
90         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
91         if (eventQueue == nullptr) {
92             DHCP_LOGE("PostAsyncTask: eventQueue is nullptr!");
93             return false;
94         }
95         int64_t delayTimeUs = delayTime * 1000;
96         DHCP_LOGD("PostAsyncTask Enter %{public}s", name.c_str());
97         ffrt::task_handle handle = eventQueue->submit_h(
98             callback, ffrt::task_attr().name(name.c_str()).delay(delayTimeUs));
99         if (handle == nullptr) {
100             return false;
101         }
102         taskMap_[name] = std::move(handle);
103         return true;
104     }
RemoveAsyncTask(const std::string & name)105     void RemoveAsyncTask(const std::string &name)
106     {
107         std::lock_guard<ffrt::mutex> lock(eventQurueMutex);
108         DHCP_LOGD("RemoveAsyncTask Enter %{public}s", name.c_str());
109         auto item = taskMap_.find(name);
110         if (item == taskMap_.end()) {
111             DHCP_LOGD("task not found");
112             return;
113         }
114         if (item->second != nullptr && eventQueue != nullptr) {
115             int32_t ret = eventQueue->cancel(item->second);
116             if (ret != 0) {
117                 DHCP_LOGE("RemoveAsyncTask failed, error code : %{public}d", ret);
118             }
119         }
120         taskMap_.erase(name);
121     }
122 private:
123     std::shared_ptr<ffrt::queue> eventQueue = nullptr;
124     mutable ffrt::mutex eventQurueMutex;
125     std::map<std::string, ffrt::task_handle> taskMap_;
126 };
127 #else
128 class DhcpThread::DhcpThreadImpl {
129 public:
DhcpThreadImpl(const std::string & threadName)130     DhcpThreadImpl(const std::string &threadName)
131     {
132         mRunFlag = true;
133         mWorkerThread = std::thread(DhcpThreadImpl::Run, std::ref(*this));
134         pthread_setname_np(mWorkerThread.native_handle(), threadName.c_str());
135     }
~DhcpThreadImpl()136     ~DhcpThreadImpl()
137     {
138         mRunFlag = false;
139         mCondition.notify_one();
140         if (mWorkerThread.joinable()) {
141             mWorkerThread.join();
142         }
143     }
PostSyncTask(Callback & callback)144     bool PostSyncTask(Callback &callback)
145     {
146         DHCP_LOGE("DhcpThreadImpl PostSyncTask Unsupported in lite.");
147         return false;
148     }
PostAsyncTask(Callback & callback,int64_t delayTime=0)149     bool PostAsyncTask(Callback &callback, int64_t delayTime = 0)
150     {
151         if (delayTime > 0) {
152             DHCP_LOGE("DhcpThreadImpl PostAsyncTask with delayTime Unsupported in lite.");
153             return false;
154         }
155         DHCP_LOGD("PostAsyncTask Enter");
156         {
157             std::unique_lock<std::mutex> lock(mMutex);
158             mEventQue.push_back(callback);
159         }
160         mCondition.notify_one();
161         return true;
162     }
PostAsyncTask(Callback & callback,const std::string & name,int64_t delayTime=0)163     bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0)
164     {
165         DHCP_LOGE("DhcpThreadImpl PostAsyncTask with name Unsupported in lite.");
166         return false;
167     }
RemoveAsyncTask(const std::string & name)168     void RemoveAsyncTask(const std::string &name)
169     {
170         DHCP_LOGE("DhcpThreadImpl RemoveAsyncTask Unsupported in lite.");
171     }
172 private:
Run(DhcpThreadImpl & instance)173     static  void Run(DhcpThreadImpl &instance)
174     {
175         while (instance.mRunFlag) {
176             std::unique_lock<std::mutex> lock(instance.mMutex);
177             while (instance.mEventQue.empty() && instance.mRunFlag) {
178                 instance.mCondition.wait(lock);
179             }
180             if (!instance.mRunFlag) {
181                 break;
182             }
183             Callback msg = instance.mEventQue.front();
184             instance.mEventQue.pop_front();
185             lock.unlock();
186             msg();
187         }
188         return;
189     }
190     std::thread mWorkerThread;
191     std::atomic<bool> mRunFlag;
192     std::mutex mMutex;
193     std::condition_variable mCondition;
194     std::deque<Callback> mEventQue;
195 };
196 #endif
197 
198 
DhcpThread(const std::string & threadName)199 DhcpThread::DhcpThread(const std::string &threadName)
200     :ptr(new DhcpThreadImpl(threadName))
201 {}
202 
~DhcpThread()203 DhcpThread::~DhcpThread()
204 {
205     ptr.reset();
206 }
207 
PostSyncTask(const Callback & callback)208 bool DhcpThread::PostSyncTask(const Callback &callback)
209 {
210     return ptr->PostSyncTask(const_cast<Callback &>(callback));
211 }
212 
PostAsyncTask(const Callback & callback,int64_t delayTime)213 bool DhcpThread::PostAsyncTask(const Callback &callback, int64_t delayTime)
214 {
215     return ptr->PostAsyncTask(const_cast<Callback &>(callback), delayTime);
216 }
217 
PostAsyncTask(const Callback & callback,const std::string & name,int64_t delayTime)218 bool DhcpThread::PostAsyncTask(const Callback &callback, const std::string &name, int64_t delayTime)
219 {
220     return ptr->PostAsyncTask(const_cast<Callback &>(callback), name, delayTime);
221 }
RemoveAsyncTask(const std::string & name)222 void DhcpThread::RemoveAsyncTask(const std::string &name)
223 {
224     ptr->RemoveAsyncTask(name);
225 }
226 
227 #ifndef OHOS_ARCH_LITE
GetInstance()228 DhcpTimer *DhcpTimer::GetInstance()
229 {
230     static DhcpTimer instance;
231     return &instance;
232 }
233 #ifdef DHCP_FFRT_ENABLE
DhcpTimer()234 DhcpTimer::DhcpTimer() : timer_(std::make_unique<DhcpThread>("DhcpTimer"))
235 {
236     timerIdInit = 0;
237 }
238 
~DhcpTimer()239 DhcpTimer::~DhcpTimer()
240 {
241     if (timer_) {
242         timer_.reset();
243     }
244 }
245 
Register(const TimerCallback & callback,uint32_t & outTimerId,uint32_t interval,bool once)246 EnumErrCode DhcpTimer::Register(const TimerCallback &callback, uint32_t &outTimerId, uint32_t interval, bool once)
247 {
248     if (timer_ == nullptr) {
249         DHCP_LOGE("timer_ is nullptr");
250         return DHCP_OPT_FAILED;
251     }
252     timerIdInit++;
253     bool ret = timer_->PostAsyncTask(callback, std::to_string(timerIdInit), interval);
254     if (!ret) {
255         DHCP_LOGE("Register timer failed");
256         timerIdInit--;
257         return DHCP_OPT_FAILED;
258     }
259 
260     outTimerId = timerIdInit;
261     return DHCP_OPT_SUCCESS;
262 }
263 
UnRegister(uint32_t timerId)264 void DhcpTimer::UnRegister(uint32_t timerId)
265 {
266     if (timerId == 0) {
267         DHCP_LOGE("timerId is 0, no register timer");
268         return;
269     }
270 
271     if (timer_ == nullptr) {
272         DHCP_LOGE("timer_ is nullptr");
273         return;
274     }
275 
276     timer_->RemoveAsyncTask(std::to_string(timerId));
277     return;
278 }
279 #else
DhcpTimer()280 DhcpTimer::DhcpTimer() : timer_(std::make_unique<Utils::Timer>("DhcpTimer"))
281 {
282     timer_->Setup();
283 }
284 
~DhcpTimer()285 DhcpTimer::~DhcpTimer()
286 {
287     if (timer_) {
288         timer_->Shutdown(true);
289     }
290 }
291 
Register(const TimerCallback & callback,uint32_t & outTimerId,uint32_t interval,bool once)292 EnumErrCode DhcpTimer::Register(const TimerCallback &callback, uint32_t &outTimerId, uint32_t interval, bool once)
293 {
294     if (timer_ == nullptr) {
295         DHCP_LOGE("timer_ is nullptr");
296         return DHCP_OPT_FAILED;
297     }
298 
299     uint32_t ret = timer_->Register(callback, interval, once);
300     if (ret == Utils::TIMER_ERR_DEAL_FAILED) {
301         DHCP_LOGE("Register timer failed");
302         return DHCP_OPT_FAILED;
303     }
304 
305     outTimerId = ret;
306     return DHCP_OPT_SUCCESS;
307 }
308 
UnRegister(uint32_t timerId)309 void DhcpTimer::UnRegister(uint32_t timerId)
310 {
311     if (timerId == 0) {
312         DHCP_LOGE("timerId is 0, no register timer");
313         return;
314     }
315 
316     if (timer_ == nullptr) {
317         DHCP_LOGE("timer_ is nullptr");
318         return;
319     }
320 
321     timer_->Unregister(timerId);
322     return;
323 }
324 #endif
325 #endif
326 }
327 }