割とタイムリーな話題というか、ここ一週間ぐらい、実行時エラーやら例外やらが発生したとき
どうやったらプログラムを安全に再開するか考えてた
で、至った考えは、ひとまとまりの一連の処理を二つに分割して
まず前半はread onlyセクションで、プログラム本体の状態を書き換えてはならないが
そのかわり例外が発生したら、無かったことに出来る(なのでread onlyにしておく)
後半はwritableセクションで結果をプログラム本体に反映させるが、その代わり例外(失敗)は許さない
bool func(){
  hoge_type result;
  try{ result = sub1(); sub2(); }catch(...){ /*リカバリ可能*/ return false; }
  try{ hoge = result; }catch(...){ /*リカバリ不可*/ abort(); } return true;
}
ただこれでもあまりうまくいかなくて、sub1()とsub2()が上記ルールに従ってたとしても
sub1()は成功してsub2()は失敗した場合に困る
全体としては失敗だけどsub1()は既に成功していて結果も反映されているので
sub1()の実行を無かったことにして巻き戻すのは難しい
sub1()をsub1_read_only()とsub1_writable()に分解するという方法もあるかもしれないが
データの受け渡しで苦労するし、可読性が落ちるうえ、複雑なことはしにくくなる

もう一つの別の要求もあって、重たい処理は別スレッドで実行して即座にGUIスレッドに制御を返したい
ということはユーザーは重い処理のキャンセルが出来るだろうが
処理のキャンセルは例外からのリカバリと本質的には全く同じこと
また、先ほどのread onlyセクションはプログラム本体の状態を書き換えない前提なので
別スレッドで実行したり非同期に同時並行で実行したりが出来る
(ただし、誰かがwritableセクションを実行したら、そいつ以外の処理結果は無効になる
 古いデータに基づいて処理した結果ということになるので・・)