🔖

Verse言語の設計思想を読み解きたい(12)非同期処理④ race式/rush式

2023/04/14に公開
2

前回はこちら
https://zenn.dev/t_tutiya/articles/394e71dab546c2
並行処理式の続きです。

race式(構造型並行処理式)

https://dev.epicgames.com/documentation/ja-jp/uefn/race-in-verse
race式(race expression)[1]」はコードブロックを取る並行処理式です。

race式のコードブロックには2個以上の非同期式を記述しなければなりません(0~1個だとコンパイルエラー)。sync式と異なり、イミディエイト式を記述する事はできません。

race式が評価されると、コードブロック内の非同期式が同時に実行されます。各非同期式のいずれかが処理を完了すると、その時点でrace式は終了し、次の処理に進みます。

この時、処理がまだ完了していない(中断している最中の)非同期式はそのまま処理が終了になります(ロールバックと混同しないように注意)。

race式は値を返します。返し値は、最初に完了した式になります。結果の型は、コードブロック内の各非同期式を包括出来る型になります。

サンプルコードで挙動を確認してみます。前回のコードの"sync"を"race"に差し替えました。race式ではコードブロックにイミディエイト式を記述出来ないので、Print()関数呼び出しをコメントアウトしています。

func1 := race:
    AsyncFunction("A", 5)
    #Print("B")
    AsyncFunction("C", 2)
    #Print("D")
Print("end")
Sleep(1.0)

実行結果は以下になります。

LogVerse: : async function:A 1
LogVerse: : async function:C 1 #<--- 1st update
LogVerse: : async function:A 2
LogVerse: : async function:C 2 #<--- 2nd update
LogVerse: : async function:A 3
#ココでCがSleep()から復帰して処理が完了する
LogVerse: : end                #<--- 3rd update

AsyncFunction("A", 5)が最後まで実行されずにrace式が終了している事が分かります。race式が終了するタイミングに注意してください。

rush式(構造型並行処理式)

https://dev.epicgames.com/documentation/ja-jp/uefn/rush-in-verse
rush式(race expression)[2]」はコードブロックを取る並行処理式です。

rush式のコードブロックには2個以上の非同期式を記述しなければなりません(0~1個だとコンパイルエラー)。イミディエイト式を記述する事はできません。

rush式が評価されると、コードブロック内の非同期式が同時に実行されます。各非同期式のいずれかが処理を完了すると、その時点でrush式は終了して次の処理に進みます。この時、まだ処理が完了していない(中断している最中の)他の非同期式は、(race式と異なり)引き続き非同期処理を続行します。

rush式は値を返します。返し値は、最初に完了した式になります。結果の型は、コードブロック内の各非同期式を包括出来る型になります。

サンプルコードです。"race"を"rush"に差し替えただけです。

func1 := rush:
    AsyncFunction("A", 5)
    #Print("B")
    AsyncFunction("C", 2)
    #Print("D")
Print("end")
Sleep(1.0)

実行結果は以下になります。

LogVerse: : async function:A 1
LogVerse: : async function:C 1 #<--- 1st update
LogVerse: : async function:A 2
LogVerse: : async function:C 2 #<--- 2nd update
LogVerse: : async function:A 3 #<--- 3rd update
LogVerse: : end 
#sleep(1.0)が無い場合ここで終わり
LogVerse: : async function:A 4 #<--- 4th update
LogVerse: : async function:A 5 #<--- 5th update

"end"が出力される所まではrace式と同じですが、その後もAの処理が続くのが分かります。
ちなみに、Sleep(1.0)が無い場合、"end"を出力した時点でOnBegin()関数が完了してしまい、それによってAの処理も終わってしまいます。

次回は非同期処理最終回。bruch/spwan/taskについてです。

続き

https://zenn.dev/t_tutiya/articles/fdbc95dc315d57


お知らせ

verse言語とUEFNの記事を他にも書いているので御覧下さい。
https://zenn.dev/t_tutiya

最後まで読んで頂きありがとうございました。この記事がお役に立てたようであれば、是非LIKEとフォローをお願いします(今後の執筆のモチベーションに繋がります)。

#Verse #UEFN #Fortnite #Verselang #UnrealEngine

宣伝

「Unityシェーダープログラミングの教科書」シリーズ1~5をBOOTHで頒布中です。
https://s-games.booth.pm/

脚注
  1. raceは「競争」の意味 ↩︎

  2. rushは「突進」の意味 ↩︎

Discussion

美しい馬美しい馬

分かりやすい記事をありがとうございます。

rush式の説明にて表記ミスかもしれないので共有いたします(勘違いでしたらすいません)

rush式が評価されると、コードブロック内の非同期式が同時に実行されます。各非同期式のいずれかが処理を完了すると、その時点でrace式は終了し、次の処理に進みます。
rush式と異なり、この時まだ処理が完了していない(中断している最中の)非同期式は引き続き非同期処理を続行します。

raceとその後に続くrushの記述が逆の気がするのですが如何でしょうか?

t_tutiyat_tutiya

こちら誤記でした&修正しました。ご指摘感謝します!><