【FileZilla】事件调用机制代码解析

void event_loop::send_event(event_handler* handler, event_base* evt, bool deletable)
{
	event_assert(handler);
	event_assert(evt);

	{
		scoped_lock lock(sync_);
		if (!handler->removing_) {
			if (pending_events_.empty() && !active_handler_) {
				cond_.signal(lock);
			}
			pending_events_.emplace_back(handler, evt, deletable);
			return;
		}
	}

	if (deletable) {
		delete evt;
	}
}

首先关注事件发送代码的函数 send_event() 及函数模版:

class FZ_PUBLIC_SYMBOL event_handler
{
......
	template<typename T, typename... Args>
	void send_event(Args&&... args) {
		event_loop_.send_event(this, new T(std::forward<Args>(args)...), true);
	}

	template<typename T>
	void send_event(T* evt) {
		event_loop_.send_event(this, evt, true);
	}
......
}
typedef simple_event<process_event_type, process*, process_event_flag> process_event;

......
void thread_entry()
{
......
if (h == ol_read_.hEvent) {
	waiting_read_ = false;
	handler_->send_event<process_event>(&process_, process_event_flag::read);
}
......
if (waiting_write_) {
	waiting_write_ = false;
	handler_->send_event<process_event>(&process_, process_event_flag::write);
}
......
}

......

这个类模版的作用是在调用时做如下展开:

handler_->send_event<process_event>(&process_, process_event_flag::read);

//展开调用为:
event_loop_.send_event(this, new process_event(&process_, process_event_flag::read), true);

那我们的核心问题是 handler_->send_event<process_event>(&process_, process_event_flag::read) 发出的事件,到底在哪里被执行?事件处理函数什么时候调用?

其次关注事件处理代码的函数 process_event() 及调用线程函数 entry()

void event_loop::entry()
{
	thread_id_ = thread::own_id();

	monotonic_clock now;

	scoped_lock l(sync_);
	while (!quit_) {
		if (do_timers_ && process_timers(l, now)) {
			continue;
		}
		if (process_event(l)) {
			continue;
		}

		// Nothing to do, now we wait
		cond_.wait(l);
	}
}

在 process_event()中,从 send_event() 放进 event_loop::pending_events_ 中取出队列最前面的元祖 ev = pending_events_.front() 并执行元祖中重载的分发函数(这部分作者再用另一个博文讲解) (*std::get<0>(ev))(*std::get<1>(ev)) ,相当于 (*handler)(evt); // 实际调用事件处理函数 ,实际是调用 handler->operator()(evt) 。

// In event_loop.hpp
typedef std::deque<std::tuple<event_handler*, event_base*, bool>> Events;

// In event_loop.cpp
bool event_loop::process_event(scoped_lock & l)
{
	Events::value_type ev{};

	if (pending_events_.empty()) {
		return false;
	}
	ev = pending_events_.front();
	pending_events_.pop_front();

	event_assert(std::get<0>(ev));
	event_assert(std::get<1>(ev));
	event_assert(!std::get<0>(ev)->removing_);

	active_handler_ = std::get<0>(ev);

	l.unlock();

	event_assert(!resend_);

	(*std::get<0>(ev))(*std::get<1>(ev));
	if (resend_) {
		resend_ = false;
		l.lock();
		if (!std::get<0>(ev)->removing_) {
			pending_events_.emplace_back(ev);
		}
		else { // Unlikely, but possible to get into this branch branch
			if (std::get<2>(ev)) {
				delete std::get<1>(ev);
			}
		}
	}
	else {
		if (std::get<2>(ev)) {
			delete std::get<1>(ev);
		}
		l.lock();
	}

	active_handler_ = nullptr;

	return true;
}

总结答案

事件处理(如 process_event)的执行时机和位置如下:

  • event_loop::entry() 中的主循环触发

  • process_event() 从队列中取出并执行

  • 实际调用的是 event_handler::operator()(event_base*) 虚函数

  • 最终会触发 process_event::operator()(event_handler*) 的具体实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Emilin Amy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值