鸿蒙源码阅读-- 用户程序框架中的libevent 原创 精华
拓维信息流沙客
发布于 2023-2-11 23:14
浏览
0收藏
概念简述
用户程序框架存在一种异步操作相关的框架,对于应用程序,需要保证ui线程不被阻塞,这个框架便保证了这样的一个机制。
eventhandler:
是一种用户在当前线程上投递InnerEvent事件或者Runnable任务到异步线程上处理的机制;
eventRunner
是存在一个线程上的事件循环器
eventQuene
存在于eventRunner中管理innerEvent的数据结构
innerEvent
用于投递的事件(也包括任务,线程间通信以及异步任务处理)
源码相关分析
innerEvent
class InnerEvent final {
public:
using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;
using Callback = std::function<void()>;
using Pointer = std::unique_ptr<InnerEvent, void (*)(InnerEvent *)>;
class Waiter {
public:
Waiter() = default;
virtual ~Waiter() = default;
DISALLOW_COPY_AND_MOVE(Waiter);
virtual void Wait() = 0;
virtual void Notify() = 0;
};
DISALLOW_COPY_AND_MOVE(InnerEvent);
/**
* Get InnerEvent instance from pool.
*
* @param innerEventId The id of the event.
* @param param Basic parameter of the event, default is 0.
* @return Returns the pointer of InnerEvent instance.
*/
static Pointer Get(uint32_t innerEventId, int64_t param = 0);
/**
* Get InnerEvent instance from pool.
*
* @param innerEventId The id of the event.
* @param object Shared pointer of the object.
* @param param Basic parameter of the event, default is 0.
* @return Returns the pointer of InnerEvent instance.
*/
template <typename T>
static inline Pointer Get(uint32_t innerEventId, const std::shared_ptr<T> &object, int64_t param = 0)
{
auto event = Get(innerEventId, param);
event->SaveSharedPtr(object);
return event;
}
......
所有的innerEvent 存在一个eventPool管理,Get方法是获取事件的结构,重载了很多的不同参数。
返回为innerEvent一个unique_ptr,这种独占式指针,但注意模板参数的析构方法不是默认的,其实重载的deleter就是eventPool去回收这些已经被消耗掉的事件了。
// Allocate new memory, while pool is empty.
return InnerEvent::Pointer(new InnerEvent, Drop);
}
private:
static void Drop(InnerEvent *event)
{
if (event == nullptr) {
return;
}
auto destructor = [](InnerEvent *event) {
if (event != nullptr) {
delete event;
}
};
// Clear content of the event
event->ClearEvent();
// Put event into event buffer pool
GetInstance().Put(InnerEvent::Pointer(event, destructor));
}
可以看到事件被消耗后又放回了event buffer pool
innerevent针对用户开发可以分为两种一个发送线程消息,另一个是投递任务。一般来说发送消息,需要用户去处理事件,这个用在eventHandler中的ProcessEvent处理,所以不同的handler需要自己实现ProcessEvent方法。
void EventHandler::DistributeEvent(const InnerEvent::Pointer &event)
{
if (!event) {
HILOGE("DistributeEvent: Could not distribute an invalid event");
return;
}
// Save old event handler.
std::weak_ptr<EventHandler> oldHandler = currentEventHandler;
// Save current event handler into thread local data.
currentEventHandler = shared_from_this();
if (event->HasTask()) {
// Call task callback directly if contains a task.
(event->GetTaskCallback())();
} else {
// Otherwise let developers to handle it.
ProcessEvent(event);
}
可以看到EventHandler::DistributeEvent会做相关处理。
void Run() final
{
// Prepare to start event loop.
queue_->Prepare();
// Make sure instance of 'EventRunner' exists.
if (owner_.expired()) {
return;
}
threadId_ = std::this_thread::get_id();
// Save old event runner.
std::weak_ptr<EventRunner> oldRunner = currentEventRunner;
// Set current event runner into thread local data.
currentEventRunner = owner_;
// Start event looper.
for (auto event = queue_->GetEvent(); event; event = queue_->GetEvent()) {
std::shared_ptr<EventHandler> handler = event->GetOwner();
// Make sure owner of the event exists.
if (handler) {
std::shared_ptr<Logger> logging = logger_;
std::stringstream address;
address << handler.get();
if (logging != nullptr) {
if (!event->HasTask()) {
logging->Log("Dispatching to handler event id = " + std::to_string(event->GetInnerEventId()));
} else {
logging->Log("Dispatching to handler event task name = " + event->GetTaskName());
}
}
handler->DistributeEvent(event);
if (logging != nullptr) {
logging->Log("Finished to handler(0x" + address.str() + ")");
}
}
DistributeEvent 方法会在 eventRuner中的loop中被调用。
再看看eventQuene的相关实现
std::mutex queueLock_;
// Sub event queues for different priority.
std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> subEventQueues_;
// Event queue for IDLE events.
std::list<InnerEvent::Pointer> idleEvents_;
// Next wake up time when block in 'GetEvent'.
InnerEvent::TimePoint wakeUpTime_{InnerEvent::TimePoint::max()};
// Mark if in idle mode, and record the start time of idle.
InnerEvent::TimePoint idleTimeStamp_{InnerEvent::Clock::now()};
bool isIdle_{true};
// Mark if the event queue is finished.
bool finished_{true};
// IO waiter used to block if no events while calling 'GetEvent'.
std::shared_ptr<IoWaiter> ioWaiter_;
// File descriptor listeners to handle IO events.
std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_;
它的成员变量,包括了互斥锁,状态机管理,不同的队列
感觉说明几个类的关系,画一个类图会更加直观一点,后续有时间更新。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
赞
3
收藏
回复
相关推荐
分析部分学习了