SWI-Prologのミューテックスで保護されたクリティカルセクションを作成しようとしており、setup_call_cleanup/3
とsetup_call_catcher_cleanup/4
を使用しています。Prolog:クリティカルセクション、バックトラッキング、エラー処理
私が持っている問題は、私のゴールは、いずれかが失敗する可能性があるの一連の操作であることであり、それは、システムがsetup_call_cleanup
の先頭にバックトラックとクリーンアップ呼び出すことを意味します。残念ながら、バックトラッキングではエラーを適切に報告できません。
setup_call_cleanup(
mutex_lock(mtx),
(Step1 = true, Step2 = true, Step3 = true),
(mutex_unlock(mtx), writeln([Step1, Step2, Step3])).
をし、次のと比較:説明するために、私の問題は、のは、この単純な例を考えてみましょう最初のケースで
setup_call_cleanup(
mutex_lock(mtx),
(Step1 = true, Step2 = true, fail, Step3 = true),
(mutex_unlock(mtx), writeln([Step1, Step2, Step3])).
をすべてはokです - 私は行って、すべての手順を見ることができます。しかし、2番目のケースでは、私はStep1
とStep2
が実行されていることがわかりません。私はバックトラックが取り消すことができない外部の副作用があるかもしれないので、それを見たいと思います。また、私はゴールにエラー処理を含めたくないので、クリティカルセクションを可能な限り速く、速くするようにします。
私は2つのアイデアを持っている:
- は、完了したステップを示す値を格納する
nb_setval
との各ステップを飾る - 再コードのステップなので、彼らは、問題の詳細を伝える例外をスローします。
前者はコードがむしろ肥大化しますが、後者は自分の必要性に対して重すぎるようです。 setup_nb_call_cleanup
のようなものはありますか?
第2のアプローチは、最初の提案よりもはるかに優れています。例外を扱うときは、常にネストされた*呼び出しで何が起きるか考えてください。グローバルな更新のような不確かな述語は、これを悪夢にしたり、正しくすることも不可能です。 – mat
@mat:うーん、はい、いいえ。いくつかのステップが 'assert(some_fact)'のように単純な場合、それらをthrow節でラップすると、必要以上に複雑になる可能性があります。また、 'nb_setval'と比較して' throw'と 'catch'のコストについてはわかりません...私は本当にクリティカルセクションを速くしたいと思っていました。 – Jacek
両方のアプローチのパフォーマンスをテストするには、 'time/1'または' statistics/2'を使用してください。これは、あなたが最も速いバージョンを使用することを確認します。非常に頻繁に、不純なソリューションも最も遅いです。 – mat