151 lines
4.0 KiB
C++
151 lines
4.0 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 <string.h>
|
||
|
|
#include <sys/poll.h>
|
||
|
|
#include <dbus/dbus.h>
|
||
|
|
#include <errno.h>
|
||
|
|
#include <Debug.h>
|
||
|
|
#include "CommonDispatcher.h"
|
||
|
|
#include "CommonWatch.h"
|
||
|
|
#include "CommonTimeout.h"
|
||
|
|
#include "EventLoop.h"
|
||
|
|
#include <algorithm>
|
||
|
|
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<CommonDispatcher, void, CommonTimeout &>(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<CommonTimeout *>(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<Timeout *>(&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<CommonDispatcher, void, Watch &>(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<CommonWatch *>(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<CommonWatch *>(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<Watch *>(ew.GetData()));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CommonDispatcher::Dispatch()
|
||
|
|
{
|
||
|
|
}
|