/* * 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 #include #include #include #include #include #include #include "EventLoop.h" #include "CommonTimeout.h" using namespace UDBus; EventLoop::EventLoop() : mRunning(false) { } EventLoop::~EventLoop() { for (list::iterator iter = mBusWatchList.begin(); iter != mBusWatchList.end(); iter++) { delete (*iter); } for (list::iterator iter = mCommonWatchList.begin(); iter != mCommonWatchList.end(); iter++) { delete (*iter); } for (list::iterator ti = mBusTimeouts.begin(); ti != mBusTimeouts.end(); ti++) { delete (*ti); } for (list::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> 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::iterator ti = mBusTimeouts.begin(); ti != mBusTimeouts.end(); ++ti) { if (((*ti)->GetInterval() < waitMs) || (waitMs < 0)) waitMs = (*ti)->GetInterval(); } for (list::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::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::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; }