Files

313 lines
7.4 KiB
C++
Raw Permalink Normal View History

2026-09-22 09:38:26 +08:00
/*
* SPDX-License-Identifier: LicenseRef-Unisoc-General-1.0
* Copyright 2016-2023 Unisoc (Shanghai) Technologies Co., Ltd
* Licensed under the Unisoc General Software License, version 1.0 (the License);
* you may not use this file except in compliance with the License. You may obtain a copy of the License at
* https://www.unisoc.com/en_us/license/UNISOC_GENERAL_LICENSE_V1.0-EN_US
* Software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, either express or implied.
* See the Unisoc General Software License, version 1.0 for more details.
*/
#include <cassert>
#include <errno.h>
#include <Debug.h>
#include <dbus/dbus.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include "EventLoop.h"
#include "CommonTimeout.h"
using namespace UDBus;
EventLoop::EventLoop()
: mRunning(false)
{
}
EventLoop::~EventLoop()
{
for (list<BusWatch *>::iterator iter = mBusWatchList.begin(); iter != mBusWatchList.end(); iter++)
{
delete (*iter);
}
for (list<CommonWatch *>::iterator iter = mCommonWatchList.begin(); iter != mCommonWatchList.end(); iter++)
{
delete (*iter);
}
for (list<BusTimeout *>::iterator ti = mBusTimeouts.begin(); ti != mBusTimeouts.end(); ti++)
{
delete (*ti);
}
for (list<CommonTimeout *>::iterator ti = mCommonTimeouts.begin(); ti != mCommonTimeouts.end(); ti++)
{
delete (*ti);
}
}
void EventLoop::AddDispatcher(Dispatcher *dispatcher)
{
mDispatches.push_back(dispatcher);
}
void EventLoop::RemoveDispatcher(Dispatcher *dispatcher)
{
mDispatches.remove(dispatcher);
}
void EventLoop::Stop()
{
mRunning = false;
}
void EventLoop::DispatcherScheme()
{
DispatcherList::iterator dispatcerIter = mDispatches.begin();
for (; dispatcerIter != mDispatches.end(); ++dispatcerIter)
{
Dispatcher *dispatcher = *dispatcerIter;
dispatcher->Dispatch();
}
}
void EventLoop::PollFdsAdd(int fd, short flag)
{
mPollFds.push_back({fd, flag, 0});
}
void EventLoop::PreparePollFds()
{
mPollFds.clear();
for (auto &watch : mBusWatchList)
{
if (watch->GetEnabled())
PollFdsAdd(watch->GetDescriptor(), watch->GetFlags());
}
map<int, vector<CommonWatch *>> watchMap;
for (auto &watch : mCommonWatchList)
{
watchMap[watch->GetDescriptor()].push_back(watch);
}
for (auto &elem : watchMap)
{
int flag = 0;
for (auto &watch : elem.second)
{
flag |= watch->GetFlags();
}
PollFdsAdd(elem.first, flag);
}
}
int EventLoop::GetPollTimeout()
{
int waitMs = -1;
for (list<BusTimeout *>::iterator ti = mBusTimeouts.begin(); ti != mBusTimeouts.end(); ++ti)
{
if (((*ti)->GetInterval() < waitMs) || (waitMs < 0))
waitMs = (*ti)->GetInterval();
}
for (list<CommonTimeout *>::iterator ti = mCommonTimeouts.begin(); ti != mCommonTimeouts.end(); ++ti)
{
if (((*ti)->GetInterval() < waitMs) || (waitMs < 0))
waitMs = (*ti)->GetInterval();
}
DEBUG("wait millsecond:%d", waitMs);
return waitMs;
}
// @return value: ms
double EventLoop::GetMonotonicTime()
{
struct timespec ts;
int result = clock_gettime(CLOCK_MONOTONIC, &ts);
if (result != 0)
{
DEBUG("get CLOCK_MONOTONIC fail");
}
return (((long)ts.tv_sec) * 1000.0) + (ts.tv_nsec / 1000000.0);
}
void EventLoop::TimeoutScheme()
{
DEBUG("");
double nowMillis = GetMonotonicTime();
for (list<BusTimeout *>::iterator ti = mBusTimeouts.begin(); ti != mBusTimeouts.end();)
{
BusTimeout *timeout = *ti;
if (!timeout)
{
ti++;
continue;
}
bool enable = timeout->GetEnabled();
if (!enable)
{
if (timeout)
{
delete timeout;
DEBUG(" delete BusTimeout ");
}
ti = mBusTimeouts.erase(ti);
}
else
{
if (nowMillis >= timeout->mExpiration)
{
if (timeout->mRepeat)
{
timeout->mExpiration = nowMillis + timeout->mInterval;
}
timeout->mBusExpired(*timeout);
}
ti++;
}
}
for (list<CommonTimeout *>::iterator ti = mCommonTimeouts.begin(); ti != mCommonTimeouts.end();)
{
CommonTimeout *timeout = *ti;
if (!timeout)
{
ti++;
continue;
}
bool enable = timeout->GetEnabled();
if (!enable)
{
if (timeout)
{
delete timeout;
DEBUG(" delete CommonTimeout ");
}
ti = mCommonTimeouts.erase(ti);
}
else
{
if (nowMillis >= timeout->mExpiration)
{
if (timeout->mRepeat)
{
timeout->mExpiration = nowMillis + timeout->mInterval;
}
timeout->mCommmonExpired(*timeout);
}
ti++;
}
}
}
void EventLoop::BusWatchScheme(pollfd &pollFd)
{
for (auto it = mBusWatchList.begin(); it != mBusWatchList.end();)
{
BusWatch *watch = *it;
if (nullptr == watch || false == watch->GetEnabled())
{
it = mBusWatchList.erase(it);
delete watch;
continue;
}
if (watch->mFd != pollFd.fd)
{
++it;
continue;
}
DEBUG("watch %p flag %d revent %d", watch, watch->GetFlags(), pollFd.revents);
watch->mState = pollFd.revents;
watch->mReady(*watch);
pollFd.revents = 0;
++it;
}
}
void EventLoop::CommonWatchScheme()
{
// mCommonWatchList allready sorted by priority while added
for (auto it = mCommonWatchList.begin(); it != mCommonWatchList.end();)
{
CommonWatch *watch = *it;
if (nullptr == watch || false == watch->GetEnabled())
{
delete watch;
it = mCommonWatchList.erase(it);
continue;
}
for (auto &pollFd : mPollFds)
{
if (watch->mFd != pollFd.fd)
continue;
int flag = pollFd.revents & watch->GetFlags();
if (0 == flag)
break;
watch->mState = flag;
watch->mReady(*watch);
break;
}
++it;
}
}
void EventLoop::WatchScheme()
{
for (auto &pollFd : mPollFds)
{
if (0 == pollFd.revents)
continue;
BusWatchScheme(pollFd);
}
CommonWatchScheme();
}
void EventLoop::Run()
{
mRunning = true;
while (mRunning)
{
try
{
DispatcherScheme();
PreparePollFds();
int timeWait = GetPollTimeout();
int fdReady = poll(mPollFds.data(), mPollFds.size(), timeWait);
TimeoutScheme();
if (fdReady > 0)
WatchScheme();
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
DEBUG("error %s", e.what());
}
}
}
bool EventLoop::CommonWatchFdEmpty(int fd) const
{
for (const auto &watch : mCommonWatchList)
{
if (watch && fd == watch->GetDescriptor() && watch->GetEnabled())
return false;
}
return true;
}