/* * 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 #include #include "ConnectionInternal.h" #include using namespace UDBus; Timeout *BusDispatcher::AddTimeout(Timeout::Internal *ti) { if (nullptr == mMainLoop) return nullptr; BusTimeout *bt = new (nothrow) BusTimeout(ti, mMainLoop); if (!bt) return nullptr; bt->mBusExpired = new (nothrow) Callback(this, &BusDispatcher::TimeoutExpired); bt->SetData(bt); mMainLoop->mBusTimeouts.push_back(bt); DEBUG("added timeout %p (%s) interval=%d", bt, bt->GetBusEnabled() ? "on" : "off", bt->GetBusInterval()); return bt; } void BusDispatcher::RemTimeout(Timeout *ti) { if (nullptr == mMainLoop || nullptr == ti) return; BusTimeout *timeout = reinterpret_cast(ti); if (NOTFOUND(mMainLoop->mBusTimeouts, timeout)) return; timeout->SetEnabled(false); DEBUG("%p", timeout); } Watch *BusDispatcher::AddWatch(Watch::Internal *internal, unsigned char pri) { if (nullptr == mMainLoop) return nullptr; BusWatch *busWatch = new (nothrow) BusWatch(internal); if (nullptr == busWatch) return nullptr; busWatch->mReady = new (nothrow) Callback(this, &BusDispatcher::WatchReady); busWatch->SetData(busWatch); busWatch->SetPriority(pri); mMainLoop->mBusWatchList.push_front(busWatch); mMainLoop->mBusWatchList.sort([](const BusWatch *w1, const BusWatch *w2) { return w1->GetPriority() > w2->GetPriority(); }); DEBUG("%p fd=%d flags=%d", busWatch, ((Watch *)busWatch)->GetDescriptor(), ((Watch *)busWatch)->GetFlags()); return busWatch; } void BusDispatcher::RemoveWatch(Watch *watch) { if (nullptr == mMainLoop || nullptr == watch) return; BusWatch *busWatch = reinterpret_cast(watch); DEBUG("%p", busWatch); if (NOTFOUND(mMainLoop->mBusWatchList, busWatch)) return; busWatch->SetEnabled(false); } void BusDispatcher::TimeoutExpired(BusTimeout &et) { DEBUG("timeout %p mExpired", &et); et.Handle(); et.UpdateExpiration(et.GetInterval()); } void BusDispatcher::WatchReady(Watch &ew) { BusWatch *watch = reinterpret_cast(ew.GetData()); DEBUG("watch %p ready, flags=%d state=%d", watch, ((Watch *)watch)->GetFlags(), watch->GetState()); int flags = 0; if (watch->GetState() & POLLIN) flags |= DBUS_WATCH_READABLE; if (watch->GetState() & POLLOUT) flags |= DBUS_WATCH_WRITABLE; if (watch->GetState() & POLLHUP) flags |= DBUS_WATCH_HANGUP; if (watch->GetState() & POLLERR) flags |= DBUS_WATCH_ERROR; watch->Handle(flags); } void BusDispatcher::Dispatch() { if (mDispatching) { DEBUG("It is dispatching"); return; } mDispatching = true; while (!mPendingQueue.empty()) //! allways be 0 or 1 { Connection::PrivateSuffix *p = mPendingQueue.front(); bool done = false; while (!done) // there are remain message in connection (iter) { try { done = p->DoDispatch(); } catch (UDBusError &e) { done = true; DEBUG("Error{%s}", e.what()); } } mPendingQueue.pop_front(); } mDispatching = false; }