* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* ubs-hcom is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <sys/epoll.h>
#include <unistd.h>
#include "net_delay_release_timer.h"
namespace ock {
namespace hcom {
constexpr uint32_t EPOLL_WAIT_TIMEOUT = NN_NO1000 * NN_NO10;
NResult NetDelayReleaseTimer::Start()
{
std::lock_guard<std::mutex> guard(mMutex);
if (mStarted) {
return NN_OK;
}
std::thread delayReleaseThread(&NetDelayReleaseTimer::RunDelayReleaseThread, this);
mThread = std::move(delayReleaseThread);
std::string treadName = "DelayRelease" + std::to_string(mDriverIndex);
if (pthread_setname_np(mThread.native_handle(), treadName.c_str()) != 0) {
NN_LOG_WARN("Invalid to set name of NetDelayReleaseTimer working thread to " << treadName);
}
while (!mThreadStarted.load()) {
usleep(NN_NO10);
}
mStarted = true;
return NN_OK;
}
void NetDelayReleaseTimer::Stop()
{
std::lock_guard<std::mutex> guard(mMutex);
if (!mStarted) {
NN_LOG_WARN("NetDelayReleaseTimer " << mName << " has not been started");
return;
}
StopInner();
mStarted = false;
}
void NetDelayReleaseTimer::StopInner()
{
mNeedStop = true;
if (mThread.native_handle()) {
mThread.join();
}
}
void NetDelayReleaseTimer::RunDelayReleaseThread()
{
mThreadStarted.store(true);
NN_LOG_INFO("NetDelayReleaseTimer " << mName << " working thread started");
int eFd = epoll_create(1);
if (eFd < 0) {
char buf[NET_STR_ERROR_BUF_SIZE] = {0};
NN_LOG_ERROR("NetDelayReleaseTimer thread failed to create epoll by "
<< NetFunc::NN_GetStrError(errno, buf, NET_STR_ERROR_BUF_SIZE));
return;
}
while (!mNeedStop) {
auto startTime = NetMonotonic::TimeMs();
DequeueDelayRelease();
auto spendTime = NetMonotonic::TimeMs() - startTime;
struct epoll_event ev {
};
int waitTimeMs = 0;
if (spendTime >= EPOLL_WAIT_TIMEOUT) {
continue;
} else {
waitTimeMs = static_cast<int32_t>(EPOLL_WAIT_TIMEOUT - spendTime);
}
epoll_wait(eFd, &ev, NN_NO1, waitTimeMs);
}
NetFunc::NN_SafeCloseFd(eFd);
NN_LOG_INFO("NetDelayReleaseTimer " << mName << " working thread exiting");
}
void NetDelayReleaseTimer::DequeueDelayRelease()
{
std::lock_guard<std::mutex> gard(mDelayReleaseMutex);
while (!mDelayReleaseQueue.empty()) {
auto epRes = mDelayReleaseQueue.front();
if (epRes.IsTimeOut()) {
if (NN_UNLIKELY(epRes.mEp != nullptr)) {
NN_LOG_DEBUG("Destroy Ep " << epRes.mEp->Id() << ", delayed release time has come");
epRes.mEp.Set(nullptr);
}
mDelayReleaseQueue.pop();
continue;
}
break;
}
}
void NetDelayReleaseTimer::EnqueueDelayRelease(UBSHcomNetEndpointPtr &ep)
{
std::lock_guard<std::mutex> gard(mDelayReleaseMutex);
auto epRes = NetDelayReleaseResource(ep, NN_NO20);
mDelayReleaseQueue.push(epRes);
}
}
}