2012-02-21 4 views
2

예외의 소멸자를 정리 코드를 넣을 장소로 사용할 수 있습니까?C++ 예외의 소멸자 코드 정리

이렇게하면 클라이언트가 RAII와 반대되는 최종 단계를 제어 할 수 있습니다. 좋은 디자인입니까 아니면 나쁜 디자인입니까? OOP 및 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 번째 작업이 실패 할 수 있습니다.

일반적으로 클라이언트 코드가 완료되기 전에 백그라운드 작업이 실행되고 있지 않은지 확인하는 것이 중요합니다. 그러나 때로는 클라이언트가 일부 작업이 실패하더라도 걱정하지 않습니다.

그래서 내 현재 솔루션은 한 작업을 시작하지 못한 경우를 대비해 CompositeTask의 BeginAsync 메서드에서 발생하는 사용자 지정 예외를 포함합니다. 이것은 클라이언트가 청소 단계 제어 할 수 있습니다 :

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 
} 

이러한 상황을 처리하는 몇 가지 모범 사례가 있습니까를?

+0

하나의 가능성은 각 하위 작업의 진행을 줄 수있는에 ITaskProgress 인터페이스를 가지고있다 클래스 ITaskProgress { 공개 : 무효의 UpdateProgress (<어떤 자식 작업을 식별>, 부울 aSuccess, 부울 & aContinue) = 0; }; 클라이언트는이 인터페이스를 구현하고 복합 작업으로 인스턴스 및 등록 할 수 있습니다. 이제 클라이언트는 알림을 받고 클라이언트는 계속할지 여부를 결정할 수 있습니다. – PermanentGuest

+0

제 질문이 잘못 공식화되었음을 압니다. 그래서 나는 그것을 바꿨다. –

답변

1
  • 예외는 복사 할 수 있으며 소멸자는 여러 번 호출됩니다. 당신의 경우에는 문제가되지 않는 것 같습니다.
  • 예외 처리 메커니즘은 임시 예외 개체를 파기하여 작업을 중단 할 수 있습니다.

이 내용을 확인하려면 표준을 읽어야합니다. 너무 게으르다.