SBCLのnon-blocking I/O
SBCLでnon-blocking I/Oを使いたくなったので少し調べてみた。
serve-eventというものが利用可能らしい。
SBCL自体のマニュアルにはこれに関数詳しい説明はなく、CMUCLのドキュメント(CMUCL User's Manual: Event Dispatching with SERVE-EVENT)を参照する必要がある。
以下、簡単な使用例。
;; non-bloking I/O を使って、ファイルの内容を出力するコード (let ((input (open "/path/to/file")) ; 対象ファイル (handler nil)) ;; 対象ファイル(FD)とイベントコールバック関数を登録 ;; コールバック関数は、対象ファイルが 読み込み可能 or 書き込み可能 になった際に呼び出される。 (setf handler (sb-sys:add-fd-handler (sb-sys:fd-stream-fd input) #| 対象ファイルディスクリプタ |# :input #| 入力イベントをハンドル |# (lambda (fd) #| コールバック関数: 行を一つ読み込んで出力する |# (declare (ignore fd)) (if (not (listen input)) ; EOF判定: 読み込み可能なデータない場合はEOFと判断する ※ この方法が適切かどうかは不明 (progn (print :eof) (sb-sys:remove-fd-handler handler) ; 読み込みが終了したので登録解除 (close input)) ; ファイルクローズ (print (read-line input)))))) ;; 全てのイベントが処理されるのを待機 (sb-sys:serve-all-events))
ローカルファイルに対して使ってもほとんど意味がないけど、ソケット通信と組み合わせると便利そう。