非同期 I/O

nmoshの非同期I/O APIにModern IO APIという名前を振った。非同期 I/Oでaioにすると検索性が悪いのと、非同期 I/Oを基本とするけど同期I/Oも混ぜて書けるので。(アイデアとしてはGround Central Dispatchからパクっている)
プロセスやI/Oルーチンの起動は非常にパラメタが多いので、Rubyのspawnと同様にキーワードを取って動作をカスタマイズできるプリミティブと、それらをwrapする便利なイディオム手続きの組み合わせという形にする。

(launch!
  (exec "ls" "-al")
  (env-add '("LANG" . "C"))
  (chdir "/home/oku")
  (stdout/bin (^[buf offset count] ...))
  (finish (^[status] ...))

execやenv-addがキーワードに相当する。launch!はcaseのような構文で、これらキーワードはquote不要。(^ はlambdaの別名。これはGauche由来。)
残念ながらstdoutやstdinにはモードがある(テキストモード/バイナリモード)。バイナリの場合、↑のように3引数の手続きを与えると、プロセスがなにかを出力するたびにcallbackされる。
結果をまとめて(同期的に)うけとるには、finishに指定する。

(launch!
  (exec "ls" "-al")
  (env-add '("LANG" . "C"))
  (chdir "/home/oku")
  ((finish stdout/bin) (^[status out] ...))

launch!構文でのキーワードは、identifier的にはマッチされない(= renameできない)。キーワード部に変数を書くことは出来ないので依然launch!構文はhygenicではある。
launch!構文はprocess以外にtcp-serverのようなI/Oノードも用意する予定。

(listen-tcp! serv ;; ← 1つめの引数で、制御用のハンドル名を指定できる
  (port "http")
  (bind "0.0.0.0" "::")
  (accept (^[socket name] ...)))

制御用ハンドルは、動作中のI/Oノードを内部から制御するときに使用する。これは、↓の糖衣構文。

(letrec ((serv (listen-tcp! (port ...) ...))))

Default Queueと同期I/O

Modern I/O APIでは、スレッド1つにつきひとつのDefault Queueを自動的に確保する。このアイデアもGCD由来で、通常のシチュエーションでは複数のQueueを使うことは殆どないことを利用している。
同期、非同期にかかわらず、ModernIOによって発行されるI/OリクエストはすべてこのDefault Queueにsubmitされる。よって、同期I/Oは、発行したI/Oオペレーションそのものを待つのではなく、Default Queueを待ちつつ当該オペレーションが終わるまで単にループすれば良いことになる。
将来的には、Schemeのportもここの同期I/Oに統合したいと考えている。