Shammer's Philosophy

My private adversaria

Clozure CL で Thread を使ってみる【その2】

Clozure CL で Thread を使ってみる【その1】 - Shammerismの実装では、無限ループ状態になってしまい top で CPU 100% となってしまったのでそうならないように修正を考える。Java の 1.4.2 が最初に本格的に取り組んだ言語だったこともあり、マルチスレッドは wait/notify モデルに慣れていたけれども、Java 5.0 以降は concurrent Package ができて、wait/notify からは徐々にフェードアウトしていったように思われる。なので、あえて wait/notify モデルにこだわらずにセマフォを使ってやってみようと思う。
おそらく、以下を使用すればできるのではないかと。

  • make-semaphore
  • signal-semaphore
  • wait-on-semaphore

とりあえず、以下のようにやってみる。キューにオブジェクトを入れてから semaphore をカウントアップし、キューからオブジェクトを取り出したら semaphore をデクリメントする。と言っても、デクリメントは wait-on-semaphore のブロックを抜けると自動で行われるから意識しなくても大丈夫。

(defparameter *running* t)

(defparameter *semaphore* (make-semaphore))

(defmethod take-from-queue ((q queue))
  (do ()
      ((not *running*))
      (when (wait-on-semaphore *semaphore*)
	(format t "Take client socket.~%")
	(let ((client (de-queue q)))
	  (do ()
	      ()
	    (let ((line (read-line client nil 'eof)))
	      (when (equal line 'eof) (return))
	      (format t "~A~%" line)))
	  (close-client-socket client)))))

(let ((my-queue (create-queue)))
  (process-run-function "take" 'take-from-queue my-queue)
  (with-open-passive-socket (server "127.0.0.1" 7001)
    (let ((client (accept-client-socket server)))
      (format t "Enqueue Client socket.~%")
      (en-queue my-queue client)
      (signal-semaphore)))
  (format t "finish.~%"))

このファイルを動作させて、nc 127.0.0.1 7001 で接続後に何らかの文字列を送ってみる。結果は以下のようになった。

$ ccl64 -l semaphore-test.lisp
Enqueue Client socket.
Take client socket.
TEST
TEST
...

そして、今回の最重要事項、top ではどのようになるかも確認してみたが、CPU は常時 0 % だった。

437  dx86cl64     0.0  00:01.74 4    0    369   4176  14M    14M    0B     0B

これでよし。これに少しずつ改良を加えていけばいいだろう。