Concurrent Hello World

Below is another example of Concurrent Hello World. The macros receive and run are just 9 lines each, given below the fold.

(defpackage :example (:use :cl :node))
(in-package :example)

(defun hello (hello-queue world-queue)
  (receive hello-queue
    (:say-hello (n)
      (cond ((plusp n)
             (format t "Hello ")
             (send world-queue :say-world n))
            (t
             (send world-queue :quit)
             (return))))))

(defun world (world-queue hello-queue)
  (receive world-queue
    (:say-world (n)
      (format t "World!~%")
      (send hello-queue :say-hello (- n 1)))
    (:quit ()
      (return))))

(defun main (n)
  (let ((hello-queue (make-queue))
        (world-queue (make-queue)))
    (run
      (make-node 'hello hello-queue world-queue)
      (make-node 'world world-queue hello-queue)
      (send hello-queue :say-hello n))))

(defpackage :node
  (:use :cl :alexandria :lparallel.kernel :lparallel.queue)
  (:export :send :receive :run :make-node :make-queue))
(in-package :node)

(defun send (queue label &rest args)
  (push-queue (cons label args) queue))

(defmacro receive (queue &body clauses)
  (once-only (queue)
    (with-gensyms (label args)
      `(loop (destructuring-bind (,label . ,args) (pop-queue ,queue)
               (case ,label
                 ,@(loop :for (clause-label params . body) :in clauses
                         :collect `(,clause-label
                                    (destructuring-bind ,params ,args
                                      ,@body)))))))))

(defmacro run (&body body)
  (with-gensyms (channel task-count)
    `(let ((,channel (make-channel))
           (,task-count 0))
       (flet ((make-node (name &rest args)
                (apply 'submit-task ,channel name args)
                (incf ,task-count)))
         (multiple-value-prog1 (progn ,@body)
           (loop :repeat ,task-count :do (receive-result ,channel)))))))
This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Concurrent Hello World

  1. Nice example. Just one thing: where does `make-queue` come from?

  2. lparallel says:

    Hi, make-queue is in the lparallel.queue package. It’s re-exported by the node package.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s