我正試圖編寫一個由SWI-Prolog中的互斥量守護的關鍵部分,並一直在尋找使用setup_call_cleanup/3
和setup_call_catcher_cleanup/4
。序言:臨界區,回溯,錯誤處理
我的問題是,我的目標是操作序列,其中任何可能失敗,這意味着該系統回溯到的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])).
在第一種情況一切正常 - 我可以看到完成的所有步驟。但在第二種情況下,我無法看到Step1
和Step2
已經執行。我想看看它,因爲它們可能有回溯無法撤消的外部副作用。另外,我不希望在目標中包含錯誤處理,以使關鍵部分儘可能精簡和快速。
我有兩個想法:
- 裝飾與
nb_setval
每一步存儲的值來表示完成的步驟, - 重新對碼步驟,讓他們扔攜帶問題的細節例外。
前者會使代碼相當臃腫,而後者似乎過重了我的需要。有什麼像setup_nb_call_cleanup
?
第二種方法肯定已經比第一個建議好多了!處理異常時,總是要考慮* nested *調用發生的情況。像全球更新這樣的不純謂詞使得這成爲一場噩夢,甚至不可能變得正確。 – mat
@mat:嗯,是的,沒有。如果某些步驟與「assert(some_fact)」一樣簡單,那麼使用throw子句包裝這些步驟可能會使它比需要的更復雜,我想。另外,與'nb_setval'相比,我不確定'throw'和'catch'的成本......我真的很想讓關鍵部分變快。 – Jacek
請使用'time/1'或'statistics/2'來測試兩種方法的性能。這將確保您使用最快的版本。非常頻繁地,不純的解決方案也是最慢的。 – mat