タイトル通りですね。処理を外部処理にしておけば同期が可能になります。処理を実行し、その結果を判断する、というブロックをメソッドに渡します。まず pre_sleep 秒だけスリープして遅延し、ブロックが false を返すと return(return if execution.call
にすれば返値 true で return)して終了。最後の処理の結果は作用しません。 post_sleep を0以上にしていれば判断後にスリープします。
limit に設定する回数は0以上。少なくとも1回は実行するので、それ以降に何度実行したいか、を limit に設定。
def recursive_execution_with_limit(limit: 0, pre_sleep: 1, post_sleep: 0, &execution) sleep pre_sleep return unless execution.call sleep post_sleep if limit > 0 recursive_execution_with_limit(limit: limit - 1, pre_sleep: pre_sleep, post_sleep: post_sleep, &execution) end end
使い方例(limit に2を設定したので、最低1回/最高3回実行する):
> recursive_execution_with_limit(limit: 2) { p r = rand(2); r == 1 } 1 1 0 #=> nil > recursive_execution_with_limit(limit: 2) { p r = rand(2); r == 1 } 0 #=> nil > recursive_execution_with_limit(limit: 2) { p r = rand(2); r == 1 } 1 0 #=> nil > recursive_execution_with_limit(limit: 2) { p r = rand(2); r == 1 } 0 #=> nil > recursive_execution_with_limit(limit: 2) {p r = rand(2); r == 1 } 1 1 1 #=> nil