- 主题:boost asio用stream_descriptor访问fifo时,读写不会完成
我看你的代码的意图本质上是想写一个阻塞函数,但是中间io操作希望通过asio来调用OS层面的异步模型来进行,所以本身wait这个动作就需要一个阻塞等待,没有必要用deadline timer这个async_wait
--
FROM 125.119.102.*
如果你的意图是想把io_context变成一个thread_pool来用,那你需要一个work guard,你可以看一下asio里关于work guard的参考,具体来说一个work guard保证io_context里事件队列清空以后,线程不会退出run
不知道你asio用的是哪个版本,我记得在1.73之后的版本里,加了asio::thread_pool这个executor,你可以用这个来代替io_context
【 在 z16166 的大作中提到: 】
: 我需要尽可能复用io_context,毕竟每次分配新的io_context对象有开销
: 之前我试过,只要执行了io_context.stop()后,如果再执行io_context.restart()和io_context.run(),会不正常,卡住,此时就不能复用io_context对象。
: 所以在一定范围内改为只要执行了stop(),就释放掉io_context,重新分配一个新的io_context。
: ...................
--
FROM 125.119.102.*
改之前是这样的,单开一个线程执行run。
m_thread = new std::thread([&]() { m_io->run(); });
本来这种单线程带超时的,用select()搞一下就行。用asio是杀鸡用牛刀了。
【 在 ziqin 的大作中提到: 】
: 1. 你的代码里没有看见io_context.run()在哪儿,你说把io_context.run放到WaitEvent之前,是指你手动改的代码?那你原来代码里io_context.run()是在哪儿运行的?
: 2. 如果你至始至终只有一个线程运行io_context.run(),那显然你不能阻塞这个线程。因为io_context本身不是thread_pool,是不带worker的,哪个线程运行run,哪个线程是worker,io_context本身只是一个事件队列而已。
:
--
修改:z16166 FROM 222.131.206.*
FROM 222.131.206.*
感觉你贴出来的代码坑不少。ipc我直接用shared memory多,named pipe我不太有经验。这个函数会不会被并行调用?kernel层面对named pipe会有加锁/排队之类的操作吗?如果没有,那在user层面多少需要有个排队加锁的结构,那用asio的确没问题。
不过,就你这个情况来说,你现在需要一个work guard,但是相应的,你在关闭的时候需要有一个机制来reset这个work guard,不然你程序不能正常退出
【 在 z16166 的大作中提到: 】
: 改之前是这样的,单开一个线程执行run。
: m_thread = new std::thread([&]() { m_io->run(); });
: 本来这种单线程带超时的,用select()搞一下就行。用asio是杀鸡用牛刀了。
: ...................
--
FROM 115.205.236.*
本青看了两本 asio的电子书, 就很开心用起来了
还是因为boost的缘故,增强了本青对asio的信心,新版本还不需要编译
你这一说,准备去研究下libuv
【 在 hgoldfish 的大作中提到: 】
: 那个接口太捉急了。抽象得难以理解。
: 真的,你不一定要从 epoll() 开始撸,用 libuv/libev 怎么都比 asio 简单些。
:
--
FROM 101.230.135.*
libuv就是大名鼎鼎的nodejs的基础库。性能绝对一流。编程接口相当简单。
强烈推荐。
【 在 looseleaf 的大作中提到: 】
: 本青看了两本 asio的电子书, 就很开心用起来了
: 还是因为boost的缘故,增强了本青对asio的信心,新版本还不需要编译
:
: ...................
--来自微微水木3.5.12
--
FROM 222.64.92.*
我在这个函数的外面加了互斥锁的,进入SendMessageInternal()之前。
回头我把代码扒出来弄个最小demo
之前用async_pipe操作匿名管道时,有个同事反馈退出时会卡住,我还没重现(现在经过你的指点,知道原因应该是没加work guard,导致执行run()的那线程没活儿干退出了,而进程退出时会给对端发送一条退出消息通知对端退出,发的这条消息没人执行了,卡在wait event上了),就改成命名管道了。
进程收到退出信号,最终会调用io_context.stop()通知退出。
下面改之前的这句,确实需要加一个work_guard,防止run()没活儿干时就自动退出了
m_thread = new std::thread([&]() { m_io->run(); });
改之后的那个放在SendMessageInternal()里的run(),就是需要它干完活儿就退出,所以不加work guard。
所以最开始的这个问题就清楚了:
执行m_io->run()的这个线程退出了,那么其他线程搞的aysnc_wait、async_write之类的异步请求根本就没线程会去给它们执行了,那当然也就不会完成了。
结帖散花,谢谢大家。后续还是要好好看看asio的文档的。
【 在 ziqin 的大作中提到: 】
: 感觉你贴出来的代码坑不少。ipc我直接用shared memory多,named pipe我不太有经验。这个函数会不会被并行调用?kernel层面对named pipe会有加锁/排队之类的操作吗?如果没有,那在user层面多少需要有个排队加锁的结构,那用asio的确没问题。
: 不过,就你这个情况来说,你现在需要一个work guard,但是相应的,你在关闭的时候需要有一个机制来reset这个work guard,不然你程序不能正常退出
:
--
修改:z16166 FROM 222.131.206.*
FROM 222.131.206.*