/* * 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 "CommonDispatcher.h" #include "CommonWatch.h" #include "CommonTimeout.h" #include "EventLoop.h" #include CommonDispatcher::CommonDispatcher(EventLoop *eventLoop) : Dispatcher(eventLoop) { } CommonDispatcher::~CommonDispatcher() { } Timeout *CommonDispatcher::AddTimeout(Timeout::Internal *ti) { if (nullptr == mMainLoop) return nullptr; CommonTimeout *bt = new (nothrow) CommonTimeout(ti, mMainLoop); if (!bt) return nullptr; bt->mCommmonExpired = new (nothrow) Callback(this, &CommonDispatcher::TimeoutExpired); bt->SetData(bt); mMainLoop->mCommonTimeouts.push_back(bt); DEBUG("added timeout %p interval=%d", bt, ((DefaultTimeout *)bt)->GetInterval()); return bt; } void CommonDispatcher::RemTimeout(Timeout *ti) { if (nullptr == mMainLoop || nullptr == ti) return; CommonTimeout *timeout = reinterpret_cast(ti); if (NOTFOUND(mMainLoop->mCommonTimeouts, timeout)) return; DEBUG("%p", timeout); timeout->SetEnabled(false); } void CommonDispatcher::TimeoutExpired(CommonTimeout &et) { bool ret = false; try { ret = et.Handle(); } catch (const std::exception &e) { ERROR("%s", e.what()); // remove timeout if any exception cached to avoid the endless loogp } if (!ret) { this->RemTimeout(reinterpret_cast(&et)); } else { et.UpdateExpiration(et.GetInterval()); } } Watch *CommonDispatcher::AddWatch(Watch::Internal *internal, unsigned char pri) { if (nullptr == mMainLoop || nullptr == internal) return nullptr; CommonWatchCallback *watchCb = (CommonWatchCallback *)internal; CommonWatch *commonWatch = new (nothrow) CommonWatch(watchCb); if (nullptr == commonWatch) return nullptr; commonWatch->mReady = new (nothrow) Callback(this, &CommonDispatcher::WatchReady); commonWatch->SetData(commonWatch); commonWatch->SetPriority(pri); mMainLoop->mCommonWatchList.push_front(commonWatch); mMainLoop->mCommonWatchList.sort([](const CommonWatch *w1, const CommonWatch *w2) { return w1->GetPriority() > w2->GetPriority(); }); DEBUG("added watch %p fd=%d flags=%x", commonWatch, ((Watch *)commonWatch)->GetDescriptor(), ((Watch *)commonWatch)->GetFlags()); return commonWatch; } void CommonDispatcher::RemoveWatch(Watch *w) { if (nullptr == mMainLoop || nullptr == w) return; CommonWatch *watch = reinterpret_cast(w); if (NOTFOUND(mMainLoop->mCommonWatchList, watch)) return; DEBUG("%p", watch); watch->SetEnabled(false); int fd = watch->mWatchCb->getFd(); if (mMainLoop->CommonWatchFdEmpty(fd)) close(fd); } void CommonDispatcher::WatchReady(Watch &ew) { CommonWatch *watch = reinterpret_cast(ew.GetData()); DEBUG("watch %p ready, flags=%d state=%d", watch, ((Watch *)watch)->GetFlags(), watch->GetState()); bool status = watch->Handle(watch->GetState()); if (!status) { RemoveWatch(reinterpret_cast(ew.GetData())); } } void CommonDispatcher::Dispatch() { }