1518678f8Sopenharmony_ci/* 2518678f8Sopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd. 3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License. 5518678f8Sopenharmony_ci * You may obtain a copy of the License at 6518678f8Sopenharmony_ci * 7518678f8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8518678f8Sopenharmony_ci * 9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and 13518678f8Sopenharmony_ci * limitations under the License. 14518678f8Sopenharmony_ci */ 15518678f8Sopenharmony_ci#include <map> 16518678f8Sopenharmony_ci#include "dhcp_thread.h" 17518678f8Sopenharmony_ci#include "dhcp_logger.h" 18518678f8Sopenharmony_ci#if DHCP_FFRT_ENABLE 19518678f8Sopenharmony_ci#include "ffrt_inner.h" 20518678f8Sopenharmony_ci#else 21518678f8Sopenharmony_ci#include <atomic> 22518678f8Sopenharmony_ci#include <chrono> 23518678f8Sopenharmony_ci#include <condition_variable> 24518678f8Sopenharmony_ci#include <deque> 25518678f8Sopenharmony_ci#include <memory> 26518678f8Sopenharmony_ci#include <mutex> 27518678f8Sopenharmony_ci#include <thread> 28518678f8Sopenharmony_ci#ifndef OHOS_ARCH_LITE 29518678f8Sopenharmony_ci#include "common_timer_errors.h" 30518678f8Sopenharmony_ci#include "timer.h" 31518678f8Sopenharmony_ci#endif 32518678f8Sopenharmony_ci#endif 33518678f8Sopenharmony_cinamespace OHOS { 34518678f8Sopenharmony_cinamespace DHCP { 35518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpThread"); 36518678f8Sopenharmony_ci#if DHCP_FFRT_ENABLE 37518678f8Sopenharmony_ciclass DhcpThread::DhcpThreadImpl { 38518678f8Sopenharmony_cipublic: 39518678f8Sopenharmony_ci DhcpThreadImpl(const std::string &threadName) 40518678f8Sopenharmony_ci { 41518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 42518678f8Sopenharmony_ci if (eventQueue != nullptr) { 43518678f8Sopenharmony_ci DHCP_LOGI("DhcpThreadImpl already init."); 44518678f8Sopenharmony_ci return; 45518678f8Sopenharmony_ci } 46518678f8Sopenharmony_ci eventQueue = std::make_shared<ffrt::queue>(threadName.c_str()); 47518678f8Sopenharmony_ci DHCP_LOGI("DhcpThreadImpl: Create a new eventQueue, threadName:%{public}s", threadName.c_str()); 48518678f8Sopenharmony_ci } 49518678f8Sopenharmony_ci ~DhcpThreadImpl() 50518678f8Sopenharmony_ci { 51518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 52518678f8Sopenharmony_ci DHCP_LOGI("DhcpThread: ~DhcpThread"); 53518678f8Sopenharmony_ci if (eventQueue) { 54518678f8Sopenharmony_ci eventQueue = nullptr; 55518678f8Sopenharmony_ci } 56518678f8Sopenharmony_ci for (auto iter = taskMap_.begin(); iter != taskMap_.end();) { 57518678f8Sopenharmony_ci iter->second = nullptr; 58518678f8Sopenharmony_ci iter = taskMap_.erase(iter); 59518678f8Sopenharmony_ci } 60518678f8Sopenharmony_ci } 61518678f8Sopenharmony_ci bool PostSyncTask(Callback &callback) 62518678f8Sopenharmony_ci { 63518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 64518678f8Sopenharmony_ci if (eventQueue == nullptr) { 65518678f8Sopenharmony_ci DHCP_LOGE("PostSyncTask: eventQueue is nullptr!"); 66518678f8Sopenharmony_ci return false; 67518678f8Sopenharmony_ci } 68518678f8Sopenharmony_ci DHCP_LOGD("PostSyncTask Enter"); 69518678f8Sopenharmony_ci ffrt::task_handle handle = eventQueue->submit_h(callback); 70518678f8Sopenharmony_ci if (handle == nullptr) { 71518678f8Sopenharmony_ci return false; 72518678f8Sopenharmony_ci } 73518678f8Sopenharmony_ci eventQueue->wait(handle); 74518678f8Sopenharmony_ci return true; 75518678f8Sopenharmony_ci } 76518678f8Sopenharmony_ci bool PostAsyncTask(Callback &callback, int64_t delayTime = 0) 77518678f8Sopenharmony_ci { 78518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 79518678f8Sopenharmony_ci if (eventQueue == nullptr) { 80518678f8Sopenharmony_ci DHCP_LOGE("PostAsyncTask: eventQueue is nullptr!"); 81518678f8Sopenharmony_ci return false; 82518678f8Sopenharmony_ci } 83518678f8Sopenharmony_ci int64_t delayTimeUs = delayTime * 1000; 84518678f8Sopenharmony_ci DHCP_LOGD("PostAsyncTask Enter"); 85518678f8Sopenharmony_ci ffrt::task_handle handle = eventQueue->submit_h(callback, ffrt::task_attr().delay(delayTimeUs)); 86518678f8Sopenharmony_ci return handle != nullptr; 87518678f8Sopenharmony_ci } 88518678f8Sopenharmony_ci bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0) 89518678f8Sopenharmony_ci { 90518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 91518678f8Sopenharmony_ci if (eventQueue == nullptr) { 92518678f8Sopenharmony_ci DHCP_LOGE("PostAsyncTask: eventQueue is nullptr!"); 93518678f8Sopenharmony_ci return false; 94518678f8Sopenharmony_ci } 95518678f8Sopenharmony_ci int64_t delayTimeUs = delayTime * 1000; 96518678f8Sopenharmony_ci DHCP_LOGD("PostAsyncTask Enter %{public}s", name.c_str()); 97518678f8Sopenharmony_ci ffrt::task_handle handle = eventQueue->submit_h( 98518678f8Sopenharmony_ci callback, ffrt::task_attr().name(name.c_str()).delay(delayTimeUs)); 99518678f8Sopenharmony_ci if (handle == nullptr) { 100518678f8Sopenharmony_ci return false; 101518678f8Sopenharmony_ci } 102518678f8Sopenharmony_ci taskMap_[name] = std::move(handle); 103518678f8Sopenharmony_ci return true; 104518678f8Sopenharmony_ci } 105518678f8Sopenharmony_ci void RemoveAsyncTask(const std::string &name) 106518678f8Sopenharmony_ci { 107518678f8Sopenharmony_ci std::lock_guard<ffrt::mutex> lock(eventQurueMutex); 108518678f8Sopenharmony_ci DHCP_LOGD("RemoveAsyncTask Enter %{public}s", name.c_str()); 109518678f8Sopenharmony_ci auto item = taskMap_.find(name); 110518678f8Sopenharmony_ci if (item == taskMap_.end()) { 111518678f8Sopenharmony_ci DHCP_LOGD("task not found"); 112518678f8Sopenharmony_ci return; 113518678f8Sopenharmony_ci } 114518678f8Sopenharmony_ci if (item->second != nullptr && eventQueue != nullptr) { 115518678f8Sopenharmony_ci int32_t ret = eventQueue->cancel(item->second); 116518678f8Sopenharmony_ci if (ret != 0) { 117518678f8Sopenharmony_ci DHCP_LOGE("RemoveAsyncTask failed, error code : %{public}d", ret); 118518678f8Sopenharmony_ci } 119518678f8Sopenharmony_ci } 120518678f8Sopenharmony_ci taskMap_.erase(name); 121518678f8Sopenharmony_ci } 122518678f8Sopenharmony_ciprivate: 123518678f8Sopenharmony_ci std::shared_ptr<ffrt::queue> eventQueue = nullptr; 124518678f8Sopenharmony_ci mutable ffrt::mutex eventQurueMutex; 125518678f8Sopenharmony_ci std::map<std::string, ffrt::task_handle> taskMap_; 126518678f8Sopenharmony_ci}; 127518678f8Sopenharmony_ci#else 128518678f8Sopenharmony_ciclass DhcpThread::DhcpThreadImpl { 129518678f8Sopenharmony_cipublic: 130518678f8Sopenharmony_ci DhcpThreadImpl(const std::string &threadName) 131518678f8Sopenharmony_ci { 132518678f8Sopenharmony_ci mRunFlag = true; 133518678f8Sopenharmony_ci mWorkerThread = std::thread(DhcpThreadImpl::Run, std::ref(*this)); 134518678f8Sopenharmony_ci pthread_setname_np(mWorkerThread.native_handle(), threadName.c_str()); 135518678f8Sopenharmony_ci } 136518678f8Sopenharmony_ci ~DhcpThreadImpl() 137518678f8Sopenharmony_ci { 138518678f8Sopenharmony_ci mRunFlag = false; 139518678f8Sopenharmony_ci mCondition.notify_one(); 140518678f8Sopenharmony_ci if (mWorkerThread.joinable()) { 141518678f8Sopenharmony_ci mWorkerThread.join(); 142518678f8Sopenharmony_ci } 143518678f8Sopenharmony_ci } 144518678f8Sopenharmony_ci bool PostSyncTask(Callback &callback) 145518678f8Sopenharmony_ci { 146518678f8Sopenharmony_ci DHCP_LOGE("DhcpThreadImpl PostSyncTask Unsupported in lite."); 147518678f8Sopenharmony_ci return false; 148518678f8Sopenharmony_ci } 149518678f8Sopenharmony_ci bool PostAsyncTask(Callback &callback, int64_t delayTime = 0) 150518678f8Sopenharmony_ci { 151518678f8Sopenharmony_ci if (delayTime > 0) { 152518678f8Sopenharmony_ci DHCP_LOGE("DhcpThreadImpl PostAsyncTask with delayTime Unsupported in lite."); 153518678f8Sopenharmony_ci return false; 154518678f8Sopenharmony_ci } 155518678f8Sopenharmony_ci DHCP_LOGD("PostAsyncTask Enter"); 156518678f8Sopenharmony_ci { 157518678f8Sopenharmony_ci std::unique_lock<std::mutex> lock(mMutex); 158518678f8Sopenharmony_ci mEventQue.push_back(callback); 159518678f8Sopenharmony_ci } 160518678f8Sopenharmony_ci mCondition.notify_one(); 161518678f8Sopenharmony_ci return true; 162518678f8Sopenharmony_ci } 163518678f8Sopenharmony_ci bool PostAsyncTask(Callback &callback, const std::string &name, int64_t delayTime = 0) 164518678f8Sopenharmony_ci { 165518678f8Sopenharmony_ci DHCP_LOGE("DhcpThreadImpl PostAsyncTask with name Unsupported in lite."); 166518678f8Sopenharmony_ci return false; 167518678f8Sopenharmony_ci } 168518678f8Sopenharmony_ci void RemoveAsyncTask(const std::string &name) 169518678f8Sopenharmony_ci { 170518678f8Sopenharmony_ci DHCP_LOGE("DhcpThreadImpl RemoveAsyncTask Unsupported in lite."); 171518678f8Sopenharmony_ci } 172518678f8Sopenharmony_ciprivate: 173518678f8Sopenharmony_ci static void Run(DhcpThreadImpl &instance) 174518678f8Sopenharmony_ci { 175518678f8Sopenharmony_ci while (instance.mRunFlag) { 176518678f8Sopenharmony_ci std::unique_lock<std::mutex> lock(instance.mMutex); 177518678f8Sopenharmony_ci while (instance.mEventQue.empty() && instance.mRunFlag) { 178518678f8Sopenharmony_ci instance.mCondition.wait(lock); 179518678f8Sopenharmony_ci } 180518678f8Sopenharmony_ci if (!instance.mRunFlag) { 181518678f8Sopenharmony_ci break; 182518678f8Sopenharmony_ci } 183518678f8Sopenharmony_ci Callback msg = instance.mEventQue.front(); 184518678f8Sopenharmony_ci instance.mEventQue.pop_front(); 185518678f8Sopenharmony_ci lock.unlock(); 186518678f8Sopenharmony_ci msg(); 187518678f8Sopenharmony_ci } 188518678f8Sopenharmony_ci return; 189518678f8Sopenharmony_ci } 190518678f8Sopenharmony_ci std::thread mWorkerThread; 191518678f8Sopenharmony_ci std::atomic<bool> mRunFlag; 192518678f8Sopenharmony_ci std::mutex mMutex; 193518678f8Sopenharmony_ci std::condition_variable mCondition; 194518678f8Sopenharmony_ci std::deque<Callback> mEventQue; 195518678f8Sopenharmony_ci}; 196518678f8Sopenharmony_ci#endif 197518678f8Sopenharmony_ci 198518678f8Sopenharmony_ci 199518678f8Sopenharmony_ciDhcpThread::DhcpThread(const std::string &threadName) 200518678f8Sopenharmony_ci :ptr_(new DhcpThreadImpl(threadName)) 201518678f8Sopenharmony_ci{} 202518678f8Sopenharmony_ci 203518678f8Sopenharmony_ciDhcpThread::~DhcpThread() 204518678f8Sopenharmony_ci{ 205518678f8Sopenharmony_ci ptr_.reset(); 206518678f8Sopenharmony_ci} 207518678f8Sopenharmony_ci 208518678f8Sopenharmony_cibool DhcpThread::PostSyncTask(const Callback &callback) 209518678f8Sopenharmony_ci{ 210518678f8Sopenharmony_ci if (ptr_ == nullptr) { 211518678f8Sopenharmony_ci DHCP_LOGE("PostSyncTask: ptr_ is nullptr!"); 212518678f8Sopenharmony_ci return false; 213518678f8Sopenharmony_ci } 214518678f8Sopenharmony_ci return ptr_->PostSyncTask(const_cast<Callback &>(callback)); 215518678f8Sopenharmony_ci} 216518678f8Sopenharmony_ci 217518678f8Sopenharmony_cibool DhcpThread::PostAsyncTask(const Callback &callback, int64_t delayTime) 218518678f8Sopenharmony_ci{ 219518678f8Sopenharmony_ci if (ptr_ == nullptr) { 220518678f8Sopenharmony_ci DHCP_LOGE("PostAsyncTask: ptr_ is nullptr!"); 221518678f8Sopenharmony_ci return false; 222518678f8Sopenharmony_ci } 223518678f8Sopenharmony_ci return ptr_->PostAsyncTask(const_cast<Callback &>(callback), delayTime); 224518678f8Sopenharmony_ci} 225518678f8Sopenharmony_ci 226518678f8Sopenharmony_cibool DhcpThread::PostAsyncTask(const Callback &callback, const std::string &name, int64_t delayTime) 227518678f8Sopenharmony_ci{ 228518678f8Sopenharmony_ci if (ptr_ == nullptr) { 229518678f8Sopenharmony_ci DHCP_LOGE("PostAsyncTask: ptr_ is nullptr!"); 230518678f8Sopenharmony_ci return false; 231518678f8Sopenharmony_ci } 232518678f8Sopenharmony_ci return ptr_->PostAsyncTask(const_cast<Callback &>(callback), name, delayTime); 233518678f8Sopenharmony_ci} 234518678f8Sopenharmony_civoid DhcpThread::RemoveAsyncTask(const std::string &name) 235518678f8Sopenharmony_ci{ 236518678f8Sopenharmony_ci if (ptr_ == nullptr) { 237518678f8Sopenharmony_ci DHCP_LOGE("RemoveAsyncTask: ptr_ is nullptr!"); 238518678f8Sopenharmony_ci return; 239518678f8Sopenharmony_ci } 240518678f8Sopenharmony_ci ptr_->RemoveAsyncTask(name); 241518678f8Sopenharmony_ci} 242518678f8Sopenharmony_ci 243518678f8Sopenharmony_ci#ifndef OHOS_ARCH_LITE 244518678f8Sopenharmony_ciDhcpTimer *DhcpTimer::GetInstance() 245518678f8Sopenharmony_ci{ 246518678f8Sopenharmony_ci static DhcpTimer instance; 247518678f8Sopenharmony_ci return &instance; 248518678f8Sopenharmony_ci} 249518678f8Sopenharmony_ci#ifdef DHCP_FFRT_ENABLE 250518678f8Sopenharmony_ciDhcpTimer::DhcpTimer() : timer_(std::make_unique<DhcpThread>("DhcpTimer")) 251518678f8Sopenharmony_ci{ 252518678f8Sopenharmony_ci timerIdInit = 0; 253518678f8Sopenharmony_ci} 254518678f8Sopenharmony_ci 255518678f8Sopenharmony_ciDhcpTimer::~DhcpTimer() 256518678f8Sopenharmony_ci{ 257518678f8Sopenharmony_ci if (timer_) { 258518678f8Sopenharmony_ci timer_.reset(); 259518678f8Sopenharmony_ci } 260518678f8Sopenharmony_ci} 261518678f8Sopenharmony_ci 262518678f8Sopenharmony_ciEnumErrCode DhcpTimer::Register(const TimerCallback &callback, uint32_t &outTimerId, uint32_t interval, bool once) 263518678f8Sopenharmony_ci{ 264518678f8Sopenharmony_ci if (timer_ == nullptr) { 265518678f8Sopenharmony_ci DHCP_LOGE("timer_ is nullptr"); 266518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 267518678f8Sopenharmony_ci } 268518678f8Sopenharmony_ci timerIdInit++; 269518678f8Sopenharmony_ci bool ret = timer_->PostAsyncTask(callback, std::to_string(timerIdInit), interval); 270518678f8Sopenharmony_ci if (!ret) { 271518678f8Sopenharmony_ci DHCP_LOGE("Register timer failed"); 272518678f8Sopenharmony_ci timerIdInit--; 273518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 274518678f8Sopenharmony_ci } 275518678f8Sopenharmony_ci 276518678f8Sopenharmony_ci outTimerId = timerIdInit; 277518678f8Sopenharmony_ci return DHCP_OPT_SUCCESS; 278518678f8Sopenharmony_ci} 279518678f8Sopenharmony_ci 280518678f8Sopenharmony_civoid DhcpTimer::UnRegister(uint32_t timerId) 281518678f8Sopenharmony_ci{ 282518678f8Sopenharmony_ci if (timerId == 0) { 283518678f8Sopenharmony_ci DHCP_LOGE("timerId is 0, no register timer"); 284518678f8Sopenharmony_ci return; 285518678f8Sopenharmony_ci } 286518678f8Sopenharmony_ci 287518678f8Sopenharmony_ci if (timer_ == nullptr) { 288518678f8Sopenharmony_ci DHCP_LOGE("timer_ is nullptr"); 289518678f8Sopenharmony_ci return; 290518678f8Sopenharmony_ci } 291518678f8Sopenharmony_ci 292518678f8Sopenharmony_ci timer_->RemoveAsyncTask(std::to_string(timerId)); 293518678f8Sopenharmony_ci return; 294518678f8Sopenharmony_ci} 295518678f8Sopenharmony_ci#else 296518678f8Sopenharmony_ciDhcpTimer::DhcpTimer() : timer_(std::make_unique<Utils::Timer>("DhcpTimer")) 297518678f8Sopenharmony_ci{ 298518678f8Sopenharmony_ci timer_->Setup(); 299518678f8Sopenharmony_ci} 300518678f8Sopenharmony_ci 301518678f8Sopenharmony_ciDhcpTimer::~DhcpTimer() 302518678f8Sopenharmony_ci{ 303518678f8Sopenharmony_ci if (timer_) { 304518678f8Sopenharmony_ci timer_->Shutdown(true); 305518678f8Sopenharmony_ci } 306518678f8Sopenharmony_ci} 307518678f8Sopenharmony_ci 308518678f8Sopenharmony_ciEnumErrCode DhcpTimer::Register(const TimerCallback &callback, uint32_t &outTimerId, uint32_t interval, bool once) 309518678f8Sopenharmony_ci{ 310518678f8Sopenharmony_ci if (timer_ == nullptr) { 311518678f8Sopenharmony_ci DHCP_LOGE("timer_ is nullptr"); 312518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 313518678f8Sopenharmony_ci } 314518678f8Sopenharmony_ci 315518678f8Sopenharmony_ci uint32_t ret = timer_->Register(callback, interval, once); 316518678f8Sopenharmony_ci if (ret == Utils::TIMER_ERR_DEAL_FAILED) { 317518678f8Sopenharmony_ci DHCP_LOGE("Register timer failed"); 318518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 319518678f8Sopenharmony_ci } 320518678f8Sopenharmony_ci 321518678f8Sopenharmony_ci outTimerId = ret; 322518678f8Sopenharmony_ci return DHCP_OPT_SUCCESS; 323518678f8Sopenharmony_ci} 324518678f8Sopenharmony_ci 325518678f8Sopenharmony_civoid DhcpTimer::UnRegister(uint32_t timerId) 326518678f8Sopenharmony_ci{ 327518678f8Sopenharmony_ci if (timerId == 0) { 328518678f8Sopenharmony_ci DHCP_LOGE("timerId is 0, no register timer"); 329518678f8Sopenharmony_ci return; 330518678f8Sopenharmony_ci } 331518678f8Sopenharmony_ci 332518678f8Sopenharmony_ci if (timer_ == nullptr) { 333518678f8Sopenharmony_ci DHCP_LOGE("timer_ is nullptr"); 334518678f8Sopenharmony_ci return; 335518678f8Sopenharmony_ci } 336518678f8Sopenharmony_ci 337518678f8Sopenharmony_ci timer_->Unregister(timerId); 338518678f8Sopenharmony_ci return; 339518678f8Sopenharmony_ci} 340518678f8Sopenharmony_ci#endif 341518678f8Sopenharmony_ci#endif 342518678f8Sopenharmony_ci} 343518678f8Sopenharmony_ci}