2011-12-21 50 views
4

Spirit是否提供使用非阻塞IO的能力?如何在Boost Spirit中使用非阻塞或异步IO?

提供更具体的示例:我想使用Boost's Spirit解析框架来解析从非阻塞模式下的网络套接字进入的数据。如果数据不完全可用,我希望能够使用该线程执行其他工作而不是阻塞。

简单的答案是在调用Spirit之前简单地读取所有数据,但可能需要从套接字接收和分析可能的千兆字节数据。

看来,为了在解析时支持非阻塞I/O,Spirit需要一些能够部分解析数据并且能够在没有更多数据可用时暂停并保存其解析状态。另外,当数据变得可用时,它需要能够从保存的分析状态恢复分析。或者我可能让这个过于复杂?

回答

4

待办事项会发布一个简单的单线程“基于事件”的解析模型的例子。这在很大程度上微不足道,但可能只是您需要的。

的东西少琐碎,请注意下列事项/提示/提示:


你会如何被消耗的结果呢?无论如何,你将不会拥有综合属性,或者你打算在飞行中使用语义动作?

由于回溯,这通常不能很好地工作。这些警告可以通过小心谨慎地使用qi :: hold,qi :: locals来解决,并且在不会回溯的站点处使用带有副作用的语义动作只有。换句话说:

  • 这势必会很容易出错
  • 自然适用于有限的一组唯一的语法(具有丰富的上下文信息的语法不会借给自己也为这个处理)。

现在,一切都可以被迫,当然,但在一般情况下,有经验的程序员应该已经学会了避免上游游泳。

现在,如果你仍然想这样做:

您应该能够通过定义BOOST_SPIRIT_THREADSAFE并链接到libboost_thread获得精神库线程安全/折返。 注意这使得Spirit线程安全使用的gobals(以罚款锁定为代价),但不是您的解析器:您不能在线程间共享您自己的解析器/规则/子语法/表达式。事实上,只有在线程安全的情况下,您才可以共享您自己的(Phoenix/Fusion)仿函数,并且应该为线程安全性审核在核心Spirit库之外定义的任何其他扩展。

如果管理上面,我认为是迄今为止最好的办法似乎

  • 使用boost ::精神:: istream_iterator(或二进制/原始字符流我宁愿定义类似的boost::spirit::istreambuf_iterator使用boost::spirit::multi_pass<>模板类)来消费输入。请注意,根据你的语法,相当多的内存可用于缓冲和性能欠佳
  • 在它自己的线程(或逻辑线程,例如升压短耳“”或著名的运行解析器'stackless coprocedures')
  • 使用如上所示的粗粒度语义操作将消息传递给执行实际处理的另一个逻辑线程。

一些更宽松的指针:

  • 你可以很容易地“导火索”某些功能使用BOOST_FUSION_ADAPT_FUNCTION和朋友处理您的语义动作处理的懒评价;这减少了你必须写得到一些简单的工作就像在语义动作正常的C++重载决议的克鲁夫特的量 - 尤其是当你不使用的C++ 0x和BOOST_RESULT_OF_USE_DECLTYPE
  • 因为你会希望避免与侧语义动作 - 的影响,你应该看看继承属性和qi::locals<>协调'纯粹功能时尚'规则的状态。
+0

谢谢!我期待看到你的榜样。我很高兴你突出了与回溯有关的一些观点。其中一个与我一起工作的语法有很多期望点,所以我可以在那里,但是对我来说,了解其他语法的这一点很有用。 – Emanuel 2011-12-21 21:39:33

+0

至于我如何去消费结果,我还没有到那个地步,但这确实是它自己的问题。我打算做一个深入了解语义动作和/或属性兼容性规则,以确定是否有某种方式,我可以“流”的预期点后的属性出来为止。 – Emanuel 2011-12-21 21:44:07

+0

@Emanuel:恩。不,关于消费结果的问题_defines_流式传输是否有意义。你应该有一个设计/模型,以免不必要地使分析器步骤复杂化,非常感谢。有迹象表明,根本无法进行流许多操作(想了XSLT变换,或者干脆倒车过滤器LA ['tac'(http://linux.die.net/man/1/tac) - 你不能击败熵,即使你非常努力地尝试多线程和消息队列,你会得到很多锁定线程或长队列)。 – sehe 2011-12-21 21:48:08