我正在编写一个阻止来自两个istreams
的输入的应用程序。
从istream
读取是一个同步(阻塞)调用,因此,我决定创建两个Boost::thread
来进行读取。
这些线程中的任何一个都可以到达“结束”(基于接收的一些输入),并且一旦达到“结束”,两个输入流都停止接收。不幸的是,我不知道哪个会这样做。
因此,我在两个线程上都不能join()
,因为只有一个线程(不能预先确定哪一个)将实际返回(解除阻塞)。
我必须以某种方式强迫对方退出,但是它被阻止等待输入,所以它本身不能决定是时候返回(条件变量或什么不是)。
他们是否可以:
istream
为“失败”或注意:
istreams
是cin
编辑:
谢谢!
答案 0 :(得分:4)
我认为没有办法跨平台做到这一点,但pthread_cancel应该是你想要的。使用boost线程,您可以从线程获取native_handle,并在其上调用pthread_cancel。
此外,更好的方法可能是在多个文件上使用相当于select调用的boost asio。这样一个线程将被阻塞等待输入,但它可能来自任一输入流。我不知道用iostreams做这样的事情是多么容易。
答案 1 :(得分:4)
是的!
boost::thread::terminate()
将根据您的要求完成工作。
它将导致目标线程抛出异常。假设它没有被捕获,堆栈将正确地解除所有资源并终止线程执行。
终止不是即时的。 (无论如何,错误的线程正在运行。)
它发生在预定义的条件下 - 对你来说最方便的可能就是调用boost::this_thread::sleep();
,你可以定期做这个帖子。
答案 2 :(得分:4)
如果增强线程在i / o操作上阻塞(例如cin>>whatever
),boost::thread::terminate()
将不会终止该线程。 cin
i / o不是有效的终止点。赶上22。
答案 3 :(得分:1)
在Linux上,我使用pthread_signal(SIGUSR1),因为它会中断阻塞IO。我在移植代码时发现,在Windows上没有这样的调用。套接字读取调用中只有一个已弃用的。在Windows中,您必须明确定义将中断阻塞调用的事件。所以没有这样的东西(AFAIK)作为中断阻塞IO的通用方法。
boost.thread设计通过管理明确的中断点来处理这个问题。我不太了解boost.asio,似乎你不想依赖它。如果您不想重构使用非阻塞范例,那么您可以做的是在非阻塞(轮询)和阻塞IO之间使用某些东西。那就是(伪代码?):
while(!stopped && !interrupted)
{
io.blockingCall(timeout);
if(!stopped && !interrupted)
{
doSomething();
}
}
然后你打断你的两个线程并加入它们......
也许你的情况更简单?如果你有一个知道一个线程结束的主线程你只需要关闭另一个线程的IO?
编辑: 顺便说一下,我对最终解决方案感兴趣...
答案 4 :(得分:1)
我自己也遇到过类似的问题并且达到了这个问题,这个问题的其他一些读者可能会觉得有用:
假设您正在使用带有wait()命令的条件变量,重要的是要知道在Boost中,wait()语句是一个自然的中断点。因此,只需使用wait语句在代码周围放置一个try / catch块,并允许函数在catch块中正常终止。
现在,假设你有一个带有线程指针的容器,迭代你的线程指针并在每个线程上调用interrupt(),然后是join()。
现在所有线程都会正常终止,任何与Boost相关的内存清理都应该干净利落。
答案 5 :(得分:0)
而不是试图杀死你的线程,你总是可以尝试加入线程,如果它失败了,你可以加入另一个线程。 (假设您将始终能够加入两个线程中的至少一个)。
在boost:thread中你正在寻找timed_join函数。
但是,如果你想查看正确的答案,那就是使用非阻塞的io和定时等待。允许您获取同步io的流结构,同时禁止异步io。
你谈论从istream中读取形式,但是istream只是一个接口。对于stdin,您可以只关闭stdin文件描述符来中断读取。至于另一个,它取决于你在哪里读...
答案 6 :(得分:0)
在Windows下,使用QueueUserAPC对引发异常的proc进行排队。这种方法对我来说很好。
HOWEVER :我刚刚发现在win32上提升互斥锁等“不可警告”,因此QueueUserAPC无法中断它们。
答案 7 :(得分:0)
似乎线程无法帮助您以简单的方式执行您想要的操作。如果Boost.Asio不符合您的喜好,请考虑使用select()
。
想法是获取两个文件描述符并使用select()
告诉您哪些输入可用。 cin
的文件描述符通常为STDIN_FILENO
;如何获取另一个取决于您的具体情况(如果它是一个文件,只是open()
而不是ifstream
)。
在循环中调用select()
以找出要读取的输入,以及何时停止,只需退出循环。
答案 8 :(得分:0)
很晚,但是在Windows中(对于那些重复这些事情的人而言,它是像VMS或RSX这样的前身)我会使用类似ReadFileEx的东西,完成例程在完成时发出信号,如果读取需要提前取消,则使用CancelIO 。
Linux / BSD有一个完全不同的底层API,不够灵活。使用pthread_kill发送信号对我有用,这将停止读/打开操作。
值得在每个平台上为这个领域实现不同的代码,恕我直言。