本文展现开源 C 语言库 Melon 中的 I / O 线程模型。在 Melon 中存在三种线程模型,本篇仅对 I / O 线程模型进行阐明。
对于 Melon 库,这是一个开源的 C 语言库,它具备:开箱即用、无第三方依赖、装置部署简略、中英文文档齐全等劣势。
Github repo
简介
首先简略介绍一些什么是 I / O 线程模型。这一话题将引入图形界面或挪动 APP 开发进行阐明。
在惯例的波及网络通信的图形界面客户端程序(如微信、QQ 等等)中,客户端既要负责界面展现,也要负责网络数据传输。然而网络传输操作实际上是会存在拥塞和丢包等不稳固因素,因而就存在了阻塞通信与非阻塞通信。在图形界面的程序开发中,很多图形接口的应用与非阻塞 I / O 很难交融于一个线程内。因而,如果一个线程即负责图形渲染,又负责 IO 通信,则会呈现界面卡顿甚至卡死。
很显然,这样的人机交互界面很不敌对,因而就呈现了渲染与 IO 拆散,分为了两个线程。即主线程做界面渲染,子线程做 IO 通信。这也就是 I / O 线程这一名词的由来。
Melon 反对 I / O 线程模型不仅仅是为了图形界面开发的须要,也是为了兼顾一些中间件的开发须要。上面咱们来一起看一下其应用。
应用
咱们先给出代码,再进行阐明。
#include "mln_iothread.h"
#include <string.h>
#include <stdio.h>
#include <errno.h>
static void msg_handler(mln_iothread_t *t, mln_iothread_ep_type_t from, mln_iothread_msg_t *msg)
{mln_u32_t type = mln_iothread_msg_type(msg);
printf("msg type: %u\n", type);
}
static void *entry(void *args)
{
int n;
mln_iothread_t *t = (mln_iothread_t *)args;
while (1) {n = mln_iothread_recv(t, user_thread);
printf("recv %d message(s)\n", n);
}
return NULL;
}
int main(void)
{
int i, rc;
mln_iothread_t t;
struct mln_iothread_attr tattr;
tattr.nthread = 1;
tattr.entry = (mln_iothread_entry_t)entry;
tattr.args = &t;
tattr.handler = (mln_iothread_msg_process_t)msg_handler;
if (mln_iothread_init(&t, &tattr) < 0) {fprintf(stderr, "iothread init failed\n");
return -1;
}
for (i = 0; i < 1000000; ++i) {if ((rc = mln_iothread_send(&t, i, NULL, io_thread, 1)) < 0) {fprintf(stderr, "send failed\n");
return -1;
} else if (rc > 0)
continue;
}
sleep(1);
mln_iothread_destroy(&t);
sleep(3);
printf("DONE\n");
return 0;
}
main
中的流程大抵如下:
- 初始化 I / O 线程
- 对 I / O 线程发送 100 万次音讯
- 休眠 1 秒钟
- 销毁 I / O 线程
- 休眠三秒钟
- 输入实现并退出
这里对 I / O 线程初始化阐明一下:
struct mln_iothread_attr {
mln_u32_t nthread; // 拉起几个 I / O 线程
mln_iothread_entry_t entry; //I/ O 线程入口函数
void *args; //I/ O 线程入口参数
mln_iothread_msg_process_t handler; // 音讯处理函数
};
音讯处理函数 handler
是当主线程或 I / O 线程调用 mln_iothread_recv
接管到音讯后被调用,用于让用户自定义对音讯的解决。
本例中,I/ O 线程死循环调用 mln_iothread_recv
接管从主线程发来的音讯,而后在该函数中调用回调 msg_handler
来解决主线程发来的音讯。
同时,能够看到初始化属性构造中蕴含一个名为 nthread
的属性,示意 I / O 线程能够有多个。而 Melon 中的事件散发模型 (mln_event.h
) 是反对多线程的,因而利用 I / O 线程模型能够实现:基于同一个事件散发模型,多线程处理事件散发模型上的事件的能力。
除此之外,mln_iothread_send
还反对了阻塞发送和非阻塞发送。阻塞发送示意,只有对端线程接管了音讯,这个函数才会返回,而非阻塞则是发送后不期待对方接管立刻返回。
结语
I/ O 模型当初在 Melang 脚本语言启动器中被应用,用于使 Melang 脚本能够启动多个线程来解决脚本程序,有点相似 Go 中协程在线程间漂移。
欢送各位对 Melon 感兴趣的读者拜访其 Github 仓库。
感激浏览!