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
}

もう 1 つの可能性は、成功するまで失敗を想定することです。

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 に答える