1

我有以下问题。

我有被回收的数据库连接(放回池中)。

例如:

{
 session sql(conn_str); // take connection from pool

 sql.exec("insert into ...")
} // at the end of the scope return connection to pool

然而,在某些情况下,回收可能是错误的——例如断开连接或其他一些重大错误。

所以我想自动防止连接被回收。我想使用以下技术实现std::uncaught_exception- 因此 exec() 函数将检测异常并防止回收:

session::exec(...)
{
   guard g(this)

   real_exec(...);
}

守卫在哪里:

class guard {
public:
   guard(session *self) : self_(self) {}
   ~guard() {
      if(std::uncaught_exception()) {
        self->mark_as_connection_that_should_not_go_to_pool();
      }
   }
}

现在,我知道http://www.gotw.ca/gotw/047.htm不建议 std::uncaught_exception在其他情况下使用我也没有看到我的代码有任何问题,提供了讨论的示例。

这段代码是否有任何可能的问题。

笔记:

  1. 我希望此更改是非侵入性的,以便 SQL 后端能够抛出而不检查每个案例是否至关重要。
  2. 我不希望用户对此采取任何行动,因此对他来说是透明的。
4

1 回答 1

2

我认为您的方法与更简单的方法相比没有任何优势:

session::exec()
{
    try
    {
        real_exec();
    }
    catch(...)
    {
        mark_as_connection_that_should_not_go_to_pool();
        throw;
    }
}

如果这个解决方案的冗长困扰你,我会注意到他们还没有从 C++ 中删除宏。我不喜欢这个版本,因为它掩盖了底层代码并且有点难看。

#define GUARD try {
#define ENDGUARD } catch(...) { mark_as_connection_that_should_not_go_to_pool(); throw; }

session::exec()
{
    GUARD
    real_exec();
    ENDGUARD
}

另一种可能性是假设失败,直到取得成功。

session::exec()
{
    mark_as_connection_that_should_not_go_to_pool();
    real_exec();
    mark_as_connection_that_may_go_to_pool();
}

最后,为了回答是否uncaught_exception会像您所概述的那样工作的问题,我将引用 Microsoft 的函数文档:

特别是,当从异常展开期间调用的析构函数调用时, uncaught_exception将返回true 。

它似乎完全符合您的预期。

于 2011-12-07T16:56:37.397 回答