wpf 监听退出事件_异步事件库async

b3de7e24fb973ab1c3e7a87b4a2b284a.png

异步事件库async

程序设计里,有一种称为事件驱动模型的方式。 比如说,一个网络服务器需要监听来自客户端的连接,以及处理客户端发送的请求, 没有客户端的时候,服务器是空闲的,它要等待事件发生然后进行处理。 事件驱动模式是非常常见,也是很基础的。

在linux上,事件驱动是通过epoll,poll等系统本身提供的机制,典型的项目包括nginx网络服务器,缓存服务redis等。

在Android系统上,很常见的looper/handler类库,就是基于epoll的封装,使得多线程的事件分发处理非常方便。

而fuchsia,对应的就是async库, 它是非常底层基础的类库,几乎所有应用都依赖于它,所以要作为第一优先级学习和分析。

async使用

使用async可以参考源码树里的示例,比如echo示例的源码。位于garnet/examples/fidl/echo_server_cpp/http://echo_server.cc

// 包含async库的头文件
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <string>

int main(int argc, const char** argv) {
  // 创建loop对象
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  bool quiet = (argc >= 2) && std::string("-q") == argv[1];
  echo::EchoServerApp app(quiet);
  loop.Run(); // loop对象的循环,程序会一直在loop里,执行不到下面的return语句, 除非调用loop.quit主动退出
  return 0;
}

在编译配置BUILD.gn文件里需要加上对async库的依赖

executable("bin") {
  output_name = "echo_server_cpp"

  sources = [ "echo_server.cc" ]

  deps = [
    ":lib",
    "//zircon/public/lib/async-default", //有3个和async相关的lib
    "//zircon/public/lib/async-loop-cpp",
    "//zircon/public/lib/async-loop-default",
  ]
}

回想下linux epoll的事件监听, 原理上要包含:

- 事件监听机制的初始化(比如linux epoll,就需要调epoll_create函数)

- 把需要监听的文件描述符加入到监听机制里(比如linux上读网络数据,那就要把socket fd加入到epoll,用epoll_ctl)

- 然后当前线程在一个死循环里调用事件等待函数(epoll_wait), 当前线程就一直阻塞,直到有事件发生时返回,程序继续往下走,这时候我们要检查是那个描述符的什么事件,相应的进行业务上的处理, 处理完继续循环调等待函数。

epoll代码的主体流程类似于:

//创建 epoll
int epfd = epoll_crete(1000);
//将 listen_fd 添加进 epoll 中
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &listen_event);
while (1) {
	//阻塞等待 epoll 中 的fd 触发
  	int active_cnt = epoll_wait(epfd, events, 1000, -1);
 	 for (i = 0; i < active_cnt; i++) {
  		 if (evnets[i].data.fd == listen_fd) {
				//accept. 并且将新accept 的fd 加进epoll中.
   		 }  else if (events[i].events & EPOLLIN) {
				//对此fd 进行读操作
	    }  else if (events[i].events & EPOLLOUT) {
				//对此fd 进行写操作
 	   }
  }

在对比看现在fuchsia的async. 就两行代码, 一行构造loop对象,一行是loop.run进入阻塞。 问题来了

1. loop对象能监听什么样的事件,事件怎么添加进来?

2. 有事件后,上层业务代码是怎么响应,上层业务和底层机制怎么打通, 完全没看到这部分代码?

接下来,探秘async

## async lib源码

代码位置在两个目录

第一个zircon/system/ulib/async-loop会编译成库async-loop-cpp和库async-loop-default

第二个zircon/system/ulib/async会编译成库async-cpp。 这个从编译BUILD.gn文件里能看到.

95a1733f208f6e5f05341a9066dc87dd.png

be064ab31d01d39f9e785f37479ac310.png

## async-loop源码

### c++层Loop类

找到loop对象定义和实现,分别位于cpp/loop.h, loop_wrapper.cc. 它是C++的类,但是实际只是一个c的结构体包装, 真正的逻辑是在async_loop_t结构里

class Loop {
 public:
  explicit Loop(const async_loop_config_t* config);
  async_loop_t* loop() const { return loop_; }
  async_dispatcher_t* dispatcher() const { return async_loop_get_dispatcher(loop_); }
  void Shutdown();
  zx_status_t Run(zx::time deadline = zx::time::infinite(), bool once = false);
  zx_status_t RunUntilIdle();
  void Quit();
  zx_status_t ResetQuit();
  async_loop_state_t GetState() const;
  zx_status_t StartThread(const char* name = nullptr, thrd_t* out_thread = nullptr);
  void JoinThreads();
 private:
  async_loop_t* loop_;
};

在Loop对象的构造函数里,创建async_loop_t实例

Loop::Loop(const async_loop_config_t* config) {
  zx_status_t status = async_loop_create(config, &loop_);
  ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status);
}

在Loop对象的run方法里,调用async_loop_run

zx_status_t Loop::Run(zx::time deadline, bool once) {
  return async_loop_run(loop_, deadline.get(), once);
}

### c层async_loop

#### 结构体定义

既然具体代码在c里,看c的头文件loop.h 和loop.c

typedef struct async_loop async_loop_t;

typedef struct async_loop {
  async_dispatcher_t dispatcher;  // 事件分发处理的函数结构体
  async_loop_config_t config;     // immutable 配置信息
  zx_handle_t port;               // immutable  port是接收从kernel的事件的端口,类似linux epoll fd
  zx_handle_t timer;              // immutable  定时器的描述符

  _Atomic async_loop_state_t state;
  atomic_uint active_threads;  // number of active dispatch threads 当前正在做事件处理的线程数

  mtx_t lock;                  // guards the lists and the dispatching tasks flag 互斥锁
  bool dispatching_tasks;      // true while the loop is busy dispatching tasks
  list_node_t wait_list;       // most recently added first 被监听的对象列表
  list_node_t task_list;       // pending tasks, earliest deadline first, 需要执行的异步任务列表
  list_node_t due_list;        // due tasks, earliest deadline first 需要执行的超时异步任务列表
  list_node_t thread_list;     // earliest created thread first
  list_node_t irq_list;        // list of IRQs
  list_node_t paged_vmo_list;  // most recently added first
  bool timer_armed;            // true if timer has been set and has not fired yet
} async_loop_t;

struct async_loop是最核心的数据结构。

#### async_loop的创建过程

- 分配async_loop_t结构体内存

- 初始化各个链表

- 创建接收kernel上报事件的端口port

zx_status_t async_loop_create(const async_loop_config_t* config, async_loop_t** out_loop) {
  async_loop_t* loop = calloc(1u, sizeof(async_loop_t));  // 分配内存
  if (!loop)
    return ZX_ERR_NO_MEMORY;
  //初始化各个属性字段,和链表
  atomic_init(&loop->state, ASYNC_LOOP_RUNNABLE);
  atomic_init(&loop->active_threads, 0u);

  loop->dispatcher.ops = (const async_ops_t*)&async_loop_ops;
  loop->config = *config;
  mtx_init(&loop->lock, mtx_plain);
  list_initialize(&loop->wait_list);
  list_initialize(&loop->irq_list);
  list_initialize(&loop->task_list);
  list_initialize(&loop->due_list);
  list_initialize(&loop->thread_list);
  list_initialize(&loop->paged_vmo_list);
 // 创建监听端口, 事件是从kernel通过port上报的
  zx_status_t status =
      zx_port_create(config->irq_support ? ZX_PORT_BIND_TO_INTERRUPT : 0, &loop->port);
  if (status == ZX_OK)
    status = zx_timer_create(ZX_TIMER_SLACK_LATE, ZX_CLOCK_MONOTONIC, &loop->timer);
  if (status == ZX_OK) {
    *out_loop = loop;
    if (loop->config.make_default_for_current_thread) {
      loop->config.default_accessors.setter(&loop->dispatcher);
    }
  } else {
    // Adjust this flag so we don't trip an assert trying to clear a default dispatcher we never
    // installed.
    loop->config.make_default_for_current_thread = false;
    async_loop_destroy(loop);
  }
  return status;
}

#### 事件监听循环和分发过程

async_loop_runs是读取底层上报事件循环体。

zx_status_t async_loop_run(async_loop_t* loop, zx_time_t deadline, bool once) {
  ZX_DEBUG_ASSERT(loop);

  zx_status_t status; 
  atomic_fetch_add_explicit(&loop->active_threads, 1u, memory_order_acq_rel);// 当前线程进入循环体,+1
  do {
    status = async_loop_run_once(loop, deadline);
  } while (status == ZX_OK && !once);
  atomic_fetch_sub_explicit(&loop->active_threads, 1u, memory_order_acq_rel);// 当前线程退出循环体,-1
  return status;
}

async_loop_run_once每次阻塞地读取一个事件,然后解析事件包,分发给对应函数处理。

static zx_status_t async_loop_run_once(async_loop_t* loop, zx_time_t deadline) {
  async_loop_state_t state = atomic_load_explicit(&loop->state, memory_order_acquire);//检查当前状态
  if (state == ASYNC_LOOP_SHUTDOWN)
    return ZX_ERR_BAD_STATE;
  if (state != ASYNC_LOOP_RUNNABLE)
    return ZX_ERR_CANCELED;

  zx_port_packet_t packet;//阻塞地从port上读取事件
  zx_status_t status = zx_port_wait(loop->port, deadline, &packet);
  if (status != ZX_OK)
    return status;

  if (packet.key == KEY_CONTROL) {// KEY_CONTROL=0
    // Handle wake-up packets.
    if (packet.type == ZX_PKT_TYPE_USER)
      return ZX_OK;

    // Handle task timer expirations. 定时器任务
    if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE && packet.signal.observed & ZX_TIMER_SIGNALED) {
      return async_loop_dispatch_tasks(loop);
    }
  } else { // packet.key > 0
    // Handle wait completion packets.
    if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE) {
      async_wait_t* wait = (void*)(uintptr_t)packet.key;
      mtx_lock(&loop->lock);
      list_delete(wait_to_node(wait));
      mtx_unlock(&loop->lock);
      return async_loop_dispatch_wait(loop, wait, packet.status, &packet.signal);
    }

    // Handle queued user packets.
    if (packet.type == ZX_PKT_TYPE_USER) {
      async_receiver_t* receiver = (void*)(uintptr_t)packet.key;
      return async_loop_dispatch_packet(loop, receiver, packet.status, &packet.user);
    }

    // Handle guest bell trap packets.
    if (packet.type == ZX_PKT_TYPE_GUEST_BELL) {
      async_guest_bell_trap_t* trap = (void*)(uintptr_t)packet.key;
      return async_loop_dispatch_guest_bell_trap(loop, trap, packet.status, &packet.guest_bell);
    }

    // Handle interrupt packets.
    if (packet.type == ZX_PKT_TYPE_INTERRUPT) {
      async_irq_t* irq = (void*)(uintptr_t)packet.key;
      return async_loop_dispatch_irq(loop, irq, packet.status, &packet.interrupt);
    }
    // Handle pager packets.
    if (packet.type == ZX_PKT_TYPE_PAGE_REQUEST) {
      async_paged_vmo_t* paged_vmo = (void*)(uintptr_t)packet.key;
      return async_loop_dispatch_paged_vmo(loop, paged_vmo, packet.status, &packet.page_request);
    }
  }

  ZX_DEBUG_ASSERT(false);
  return ZX_ERR_INTERNAL;
}

事件类型涵盖

- 定时器任务   由async_loop_dispatch_tasks处理

- 等待变量wait  由async_loop_dispatch_wait处理

- 数据包事件   由async_loop_dispatch_packet处理

- irq事件     由async_loop_dispatch_irq处理

- 内存共享事件  由async_loop_dispatch_paged_vmo处理

#### 如何添加事件监听

等待变量wait的监听有这两个函数操作.

// 添加该wait的监听
static zx_status_t async_loop_begin_wait(async_dispatcher_t* async, async_wait_t* wait) {
  async_loop_t* loop = (async_loop_t*)async;//检查当前状态
  if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
    return ZX_ERR_BAD_STATE;

  mtx_lock(&loop->lock);
// 添加监听object, zx_object_wait_async是系统调用
  zx_status_t status =
      zx_object_wait_async(wait->object, loop->port, (uintptr_t)wait, wait->trigger, wait->options);
  if (status == ZX_OK) { // 把该wait加到列表里
    list_add_head(&loop->wait_list, wait_to_node(wait));
  } else {
    ZX_ASSERT_MSG(status == ZX_ERR_ACCESS_DENIED, "zx_object_wait_async: status=%d", status);
  }

  mtx_unlock(&loop->lock);
  return status;
}
// 取消监听
static zx_status_t async_loop_cancel_wait(async_dispatcher_t* async, async_wait_t* wait) {
  async_loop_t* loop = (async_loop_t*)async;
  mtx_lock(&loop->lock);
  // First, confirm that the wait is actually pending.,从列表里找到要删除掉结点
  list_node_t* node = wait_to_node(wait);
  if (!list_in_list(node)) {
    mtx_unlock(&loop->lock);
    return ZX_ERR_NOT_FOUND;
  }

  // Next, cancel the wait.  This may be racing with another thread that
  // has read the wait's packet but not yet dispatched it.  So if we fail
  // to cancel then we assume we lost the race.
    // zx_port_cancel 是系统调用
  zx_status_t status = zx_port_cancel(loop->port, wait->object, (uintptr_t)wait);// 取消监听
  if (status == ZX_OK) {
    list_delete(node);
  } else {
    ZX_ASSERT_MSG(status == ZX_ERR_NOT_FOUND, "zx_port_cancel: status=%d", status);
  }

  mtx_unlock(&loop->lock);
  return status;
}

其中添加wait事件监听需要调用者构造一个async_wait_t结构

struct async_wait {
  // Private state owned by the dispatcher, initialize to zero with |ASYNC_STATE_INIT|.
  async_state_t state;
  // The wait's handler function.
  async_wait_handler_t* handler;
  // The object to wait for signals on.
  zx_handle_t object;
  // The set of signals to wait for.
  zx_signals_t trigger;
  // Wait options, see zx_object_wait_async().
  uint32_t options;
};

发送和取消定时器异步任务的两个函数操作

static zx_status_t async_loop_post_task(async_dispatcher_t* async, async_task_t* task) {
  async_loop_t* loop = (async_loop_t*)async;
  ZX_DEBUG_ASSERT(loop);
  ZX_DEBUG_ASSERT(task);
//检查当前状态
  if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
    return ZX_ERR_BAD_STATE;
  mtx_lock(&loop->lock);
  async_loop_insert_task_locked(loop, task);//加入task到链表,在这个链表里的task是按照时间顺序排列的,最新执行的放最前面
  if (!loop->dispatching_tasks && task_to_node(task)->prev == &loop->task_list) {
      //如果该任务是task list头部元素,重新设置定时器超时时间
    // Task inserted at head.  Earliest deadline changed.
    async_loop_restart_timer_locked(loop);
  }

  mtx_unlock(&loop->lock);
  return ZX_OK;
}
// 取消定时器任务
static zx_status_t async_loop_cancel_task(async_dispatcher_t* async, async_task_t* task) {
  async_loop_t* loop = (async_loop_t*)async;
// 从task列表里找到要删除的task
  mtx_lock(&loop->lock);
  list_node_t* node = task_to_node(task);
  if (!list_in_list(node)) {
    mtx_unlock(&loop->lock);
    return ZX_ERR_NOT_FOUND;
  }

  // Determine whether the head task was canceled and following task has
  // a later deadline.  If so, we will bump the timer along to that deadline.
    // 如果该task是列表的首个元素,  
  bool must_restart =
      !loop->dispatching_tasks && node->prev == &loop->task_list &&
      (node->next == &loop->task_list || node_to_task(node->next)->deadline > task->deadline);
  list_delete(node);// 删除结点
  if (must_restart)// 重新设置定时器超时时间
    async_loop_restart_timer_locked(loop);

  mtx_unlock(&loop->lock);
  return ZX_OK;
}

往端口发送数据包

static zx_status_t async_loop_queue_packet(async_dispatcher_t* async, async_receiver_t* receiver,
                                           const zx_packet_user_t* data) {
  async_loop_t* loop = (async_loop_t*)async;
//状态检查
  if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
    return ZX_ERR_BAD_STATE;
// 构造包
  zx_port_packet_t packet = {.key = (uintptr_t)receiver, .type = ZX_PKT_TYPE_USER, .status = ZX_OK};
  if (data)
    packet.user = *data;
    // 发送到端口上,zx_port_queue是系统调用
  return zx_port_queue(loop->port, &packet);
}

其它类型的中断事件irq,和内存 vmo就不列举了

static zx_status_t async_loop_bind_irq(async_dispatcher_t* dispatcher, async_irq_t* irq);
static zx_status_t async_loop_unbind_irq(async_dispatcher_t* dispatcher, async_irq_t* irq);
static zx_status_t async_loop_create_paged_vmo(async_dispatcher_t* async,
                                               async_paged_vmo_t* paged_vmo, uint32_t options,
                                               zx_handle_t pager, uint64_t vmo_size,
                                               zx_handle_t* vmo_out);
static zx_status_t async_loop_detach_paged_vmo(async_dispatcher_t* dispatcher,
                                               async_paged_vmo_t* paged_vmo);

#### 事件处理过程

等待变量wait, 直接调用了在handler函数来处理。这个handler是由调用者在添加事件监听时,构造async_wait_t传入

static zx_status_t async_loop_dispatch_wait(async_loop_t* loop, async_wait_t* wait,
                                            zx_status_t status, const zx_packet_signal_t* signal) {
  async_loop_invoke_prologue(loop);
  wait->handler((async_dispatcher_t*)loop, wait, status, signal);
  async_loop_invoke_epilogue(loop);
  return ZX_OK;
}

类似的,定时器任务处理也是通过由调用者在添加事件监听时,构造async_task_t传入handler函数

static void async_loop_dispatch_task(async_loop_t* loop, async_task_t* task, zx_status_t status) {
  // Invoke the handler.  Note that it might destroy itself.
  async_loop_invoke_prologue(loop);
  task->handler((async_dispatcher_t*)loop, task, status);
  async_loop_invoke_epilogue(loop);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值