Files
BPI-M2C/source_sync_rls_25c/source/unisoc/perflink/libudbus/BusDispatcher.cpp
T
2026-09-22 09:38:26 +08:00

152 lines
4.1 KiB
C++

/*
* 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 <string.h>
#include <Debug.h>
#include <sys/poll.h>
#include <dbus/dbus.h>
#include <errno.h>
#include <BusTimeout.h>
#include <BusDispatcher.h>
#include <BusWatch.h>
#include "ConnectionInternal.h"
#include <algorithm>
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<BusDispatcher, void, BusTimeout &>(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<BusTimeout *>(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<BusDispatcher, void, Watch &>(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<BusWatch *>(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<BusWatch *>(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;
}