为什么`libpq`使用轮询而不是数据提取通知?

时间:2013-10-12 14:42:32

标签: postgresql libpq

我正在阅读libpq参考。它同时具有同步和异步方法。我发现了一些奇怪的东西。

当我看到PQsendQuery函数时,它似乎发送一个查询并立即返回。我期望一个回调函数得到通知,但没有这样的事情,手册说民意调查的数据可用性。

我不明白为什么异步方法是用轮询方式编写的。无论如何,由于libp是官方客户端实现,我相信这个设计应该有充分的理由。那是什么?或者我错过了其他地方提到的正确回调的东西?

2 个答案:

答案 0 :(得分:6)

在单线程程序的执行模型中,执行流不能被从异步查询返回的数据中断,或者更一般地说是网络套接字。只有信号(SIGTERM和朋友)可能会中断流量,但信号无法挂钩到来的数据。

这就是为什么不能通过回调来获得传入数据的通知。如果您的代码没有调用它,那么发送回调所必需的libpq中的代码段将永远不会运行。如果你不得不打电话,它就会打败回调的全部内容。

有像Qt这样的库提供回调,但它们从头开始构建一个充当事件处理器的主循环。用户代码在回调中组织,并且可以对基于事件的输入数据进行处理。但在这种情况下,库获取执行流的所有权,这意味着它的主循环轮询数据源。这只是将责任转移到libpq之外的另一段代码。

答案 1 :(得分:-1)

此页面描述了如何通知异步结果获取。

http://www.postgresql.org/docs/9.3/static/libpq-events.html#LIBPQ-EVENTS-PROC

  

PGEVT_RESULTCREATE

     

结果创建事件在响应任何查询执行时被触发   生成结果的函数,包括PQgetResult。这个事件   只有在成功创建结果后才会触发。

     

typedef struct {       PGconn * conn;       PGresult *结果; PGEventResultCreate;收到PGEVT_RESULTCREATE事件时,应将evtInfo指针强制转换为a   PGEventResultCreate *。 conn是用于生成的连接   结果。这是初始化任何instanceData的理想位置   需要与结果相关联。如果事件过程失败,   结果将被清除,故障将被传播。该   事件过程不得尝试PQclear自己的结果对象。   返回失败代码时,所有清理必须执行为no   将发送PGEVT_RESULTDESTROY事件。