152 lines
4.1 KiB
C++
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;
|
|
}
|