Можем ли мы использовать деструктор исключения в качестве места для размещения кода очистки?
Таким образом, мы можем позволить клиенту контролировать этап завершения в отличие от RAII.
Это хороший или плохой дизайн?
Это правильное решение в контексте ООП и C ++?
В настоящее время я работаю над асинхронной процедурой, которая сама запускает асинхронно несколько задач.
Шаблон выглядит следующим образом:
struct IAsyncResult
{
...
virtual void EndCall() const;
}
typedef std::shared_ptr<IAsyncResult> IAsyncResultPtr;
struct IAsyncTask
{
virtual IAsyncResultPtr BeginTask() = 0;
virtual void EndTask(IAsyncResultPtr async) const = 0;
}
class CompositeTask : public IAsyncTask
{
…
}
К сожалению, я не могу гарантировать, что метод BeginTask каждой подзадачи не завершится с ошибкой. Таким образом, возможно, что подзадачи N-1 начнутся успешно, а N-й сбой.
В общем, важно убедиться, что никакие фоновые задачи не выполняются до завершения кода клиента. Но иногда клиенту все равно, что некоторые задачи не выполняются.
Таким образом, мое текущее решение включает в себя пользовательское исключение, которое выдается из метода BeginAsync CompositeTask в случае, если не удалось запустить одну задачу. Это позволяет клиенту контролировать этап очистки:
class composite_async_exception : public std::exception
{
std::vector<IAsyncResultPtr> successfully_started_tasks;
mutable bool manage_cleanup;
public:
composite_async_exception(std::vector<IAsyncResultPtr> const& _successfully_started_tasks)
: successfully_started_tasks(_successfully_started_tasks)
, manage_cleanup(true)
{
}
virtual ~composite_async_exception() throw()
{
if(!manage_cleanup)
return;
for( auto task = successfully_started_tasks.begin(); task != successfully_started_tasks.end(); ++task)
{
task->CancelTask();
}
}
void Giveup() const throw()
{
manage_cleanup = false;
}
};
И клиент использует код, как показано:
try
{
compositeTask.BeginAsync();
}
catch(composite_async_exception const& ex)
{
//prevent the exception to cancel tasks
ex.Giveup();
// some handling
}
Существуют ли передовые практики для разрешения такой ситуации?