Использование uncaught_exception для обработки ошибок - PullRequest
1 голос
/ 07 декабря 2011

У меня следующая проблема.

У меня есть соединение с базой данных, которое перерабатывается (помещается обратно в пул).

Например:

{
 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 в другом случае. Я также не вижу никаких ошибок в моем коде, приведенные примеры приведены.

Есть ли какие-либо возможные проблемы с этимcode.

Примечание:

  1. Я хочу, чтобы это изменение было ненавязчивым, чтобы сервер SQL мог генерировать и не проверять каждый случай, еслиэто критично или нет.
  2. Я не хочу, чтобы пользователь предпринимал какие-либо действия по этому поводу, чтобы это было прозрачно для него.

1 Ответ

2 голосов
/ 07 декабря 2011

Я не вижу преимущества вашего метода перед чем-то более простым:

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 при вызове из деструктора, который вызывается при отмене исключения.

Кажется, он делает именно то, что ожидал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...