2012-02-21 9 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番目のサブタスクが失敗する可能性があります。

一般に、クライアントのコードが終了する前にバックグラウンドタスクが実行されていないことを確認することが重要です。しかし、クライアントによっては、いくつかのタスクが失敗しても気にしないことがあります。

私の現在のソリューションは、1つのタスクの開始に失敗した場合に備えて、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(<いくつかの子タスクID>、BOOL aSuccess、BOOL&aContinue)= 0。 }; クライアントはこのインターフェイスを実装し、複合タスクでインスタンスと登録できます。今、クライアントは通知を受け取り、クライアントは続行するかどうかを決定できます。 – PermanentGuest

+0

私の質問は間違って策定されています。だから私はそれを変更しました。 –

答えて

1
  • 例外はコピーすることができますが、デストラクタは複数回呼び出されます。あなたの場合、それは問題ではないようです。
  • 例外処理メカニズムは、一時例外オブジェクトを破棄してタスクを停止させる可能性があります。

この1つは私が行うにはあまりにも怠惰なんだこれは、標準読むべきかどうかを確認します。