の使用方法によって動作が異なる Common Lisp プログラムがあります*standard-input*
。詳細は次のとおりです。
(if input-stream?
(process)
(with-open-file (*standard-input* up :element-type 'unsigned-byte)
(process)))
このprocess
関数は複数のスレッドを開始します。各スレッドは標準入力の一部を読み取り、それをファイルに書き込み (すべてロック内)、結果のファイルを並行して処理します (ロック外)。実際、結果のファイルを並行して処理するのは、それ以外の場合にのみ、input-stream?
順次false
処理します。
(defun process ()
(let ((psize 4194304)
(stream *standard-input*)
(result-lock (bt:make-lock))
(input-stream-lock (bt:make-lock))
eof)
(flet ((add-job (fname)
(make-thread
#'(lambda ()
(do () (eof)
(when (bt:with-lock-held (input-stream-lock)
(unless eof
(setq eof (write-input-stream-to-file stream fname psize))
t))
(sleep 0.1)
(bt:with-lock-held (result-lock)
(display-progress))))))))
(mapcar
#'join-thread
(loop for i from 1 to 10
collect (add-job
(make-pathname :directory "/tmp"
:name "test"
:type (princ-to-string i))))))))
(let ((counter 0))
(defun display-progress ()
(if (zerop (mod (incf counter) 10))
(format t " ~a " counter)
(write-char #\+))))
(defun write-input-stream-to-file (stream fname psize-bytes)
(with-open-file (out fname
:direction :output
:element-type 'unsigned-byte
:if-exists :supersede)
(do ((byte (read-byte stream nil nil)
(read-byte stream nil nil))
(offset 0 (1+ offset)))
((or (= offset psize-bytes) (null byte)) (not byte))
(write-byte byte out))))
(mkfifo を使用して) FIFO を作成し、ファイルをそこにコピーして、代わりにそれを使用してプログラムを実行すると、再び並列処理が観察されます。
上記のプログラムは、ECL を使用してコマンド ライン ユーティリティとしてビルドされ、Linux で実行されます。次のいずれかの方法で実行します。
- 猫「ビッグファイル」 | マイプログラム
- 私のプログラム「ビッグファイル」
並列処理はケース 2 でのみ発生します。
問題は、なぜ違いがあるのかということです。
アップデート:
- 私の質問に間違いがありました。これでOKです。
process
関数を追加し、プログラムの実行方法を説明しました