Added taskvent.lisp, taskwork.lisp and tasksink.lisp examples. Updated build scripts.
-- --ska
From e0632b7c40fe207df89dda40a5032cb2dbab293d Mon Sep 17 00:00:00 2001 From: Kamil Shakirov <kamil...@gmail.com> Date: Mon, 4 Oct 2010 14:39:41 +0700 Subject: [PATCH] Add taskvent.lisp, taskwork.lisp and tasksink.lisp examples. --- examples/C/.gitignore | 3 + examples/Common Lisp/.gitignore | 4 ++ examples/Common Lisp/build | 2 +- examples/Common Lisp/build.lisp | 16 +++++- examples/Common Lisp/compile | 6 +- examples/Common Lisp/hwclient.lisp | 8 ++-- examples/Common Lisp/hwserver.lisp | 4 +- examples/Common Lisp/tasksink.lisp | 65 ++++++++++++++++++++++---- examples/Common Lisp/taskvent.lisp | 52 +++++++++++++++++---- examples/Common Lisp/taskwork.lisp | 53 +++++++++++++++++---- examples/Common Lisp/wuclient.lisp | 10 ++-- examples/Common Lisp/wuserver.lisp | 3 - examples/Common Lisp/zhelpers.lisp | 88 +++++++++++++++++++++++++++++------- 13 files changed, 247 insertions(+), 67 deletions(-) diff --git a/examples/C/.gitignore b/examples/C/.gitignore index 2335456..44f149d 100644 --- a/examples/C/.gitignore +++ b/examples/C/.gitignore @@ -1,4 +1,7 @@ +core *.o +*.lst + hwclient hwserver msgqueue diff --git a/examples/Common Lisp/.gitignore b/examples/Common Lisp/.gitignore index 23d0a05..85f8a80 100644 --- a/examples/Common Lisp/.gitignore +++ b/examples/Common Lisp/.gitignore @@ -1,5 +1,8 @@ # ignore file +/tasksink +/taskvent +/taskwork /hwclient /hwserver /wuclient @@ -7,3 +10,4 @@ /zversion *.fas* +*.*fsl diff --git a/examples/Common Lisp/build b/examples/Common Lisp/build index 8b415fd..95aa989 100755 --- a/examples/Common Lisp/build +++ b/examples/Common Lisp/build @@ -10,7 +10,7 @@ if [ /$1/ = /all/ ]; then done elif [ /$1/ = /clean/ ]; then echo "Cleaning Common Lisp examples directory..." - rm -f *.fas* core + rm -f *.fas* *.*fsl core for MAIN in `egrep -l main *.lisp`; do rm -f `basename $MAIN .lisp` done diff --git a/examples/Common Lisp/build.lisp b/examples/Common Lisp/build.lisp index 5b7e89d..0eec089 100644 --- a/examples/Common Lisp/build.lisp +++ b/examples/Common Lisp/build.lisp @@ -5,6 +5,12 @@ ;;; Kamil Shakirov <kamil...@gmail.com> ;;; +(in-package :cl-user) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (require :split-sequence) + (require :zeromq)) + (defpackage #:zguide.build (:nicknames #:build) (:use #:cl) @@ -13,6 +19,10 @@ (in-package :zguide.build) -(defun build (app-name app-entry) - #+sbcl (sb-ext:save-lisp-and-die app-name :executable t :toplevel app-entry) - #+ccl (ccl:save-application app-name :prepend-kernel t :toplevel-function app-entry)) +(defun build (app-name) + (load (compile-file "zhelpers")) + (load (compile-file app-name)) + + (let ((app-entry (find-symbol "MAIN" (string-upcase app-name)))) + #+sbcl (sb-ext:save-lisp-and-die app-name :executable t :toplevel app-entry) + #+ccl (ccl:save-application app-name :prepend-kernel t :toplevel-function app-entry))) diff --git a/examples/Common Lisp/compile b/examples/Common Lisp/compile index 0000fc0..9bc7162 100755 --- a/examples/Common Lisp/compile +++ b/examples/Common Lisp/compile @@ -11,10 +11,10 @@ LISP_OPTS= case $LISP in sbcl) - LISP_OPTS="--load build.lisp --load zhelpers.lisp --load $1.lisp --eval" + LISP_OPTS="--load build.lisp --eval" ;; ccl) - LISP_OPTS="--load build.lisp --load zhelpers.lisp --load $1.lisp --eval" + LISP_OPTS="--load build.lisp --eval" ;; *) echo "'LISP=$LISP' is not supported!" @@ -22,4 +22,4 @@ case $LISP in ;; esac -$LISP $LISP_OPTS "(build:build \"$1\" #'$1:main)" +$LISP $LISP_OPTS "(build:build \"$1\")" diff --git a/examples/Common Lisp/hwclient.lisp b/examples/Common Lisp/hwclient.lisp index e0d005f..3a71925 100644 --- a/examples/Common Lisp/hwclient.lisp +++ b/examples/Common Lisp/hwclient.lisp @@ -18,19 +18,19 @@ ;; Prepare our context and socket (zmq:with-context (context 1) (zmq:with-socket (socket context zmq:req) - (format t "Connecting to hello world server...~%") + (message "Connecting to hello world server...~%") (zmq:connect socket "tcp://localhost:5555") ;; Do 10 requests, waiting each time for a response (dotimes (request-nbr 10) (let ((request (make-instance 'zmq:msg :data "Hello"))) - (format t "Sending request ~D...~%" request-nbr) + (message "Sending request ~D...~%" request-nbr) (zmq:send socket request)) ;; Get the reply (let ((response (make-instance 'zmq:msg))) (zmq:recv socket response) - (format t "Received reply ~D: [~A]~%" - request-nbr (zmq:msg-data-as-string response)))))) + (message "Received reply ~D: [~A]~%" + request-nbr (zmq:msg-data-as-string response)))))) (cleanup)) diff --git a/examples/Common Lisp/hwserver.lisp b/examples/Common Lisp/hwserver.lisp index 3371905..6bb4cef 100644 --- a/examples/Common Lisp/hwserver.lisp +++ b/examples/Common Lisp/hwserver.lisp @@ -24,8 +24,8 @@ (let ((request (make-instance 'zmq:msg))) ;; Wait for next request from client (zmq:recv socket request) - (format t "Received request: [~A]~%" - (zmq:msg-data-as-string request)) + (message "Received request: [~A]~%" + (zmq:msg-data-as-string request)) ;; Do some 'work' (sleep 1) diff --git a/examples/Common Lisp/tasksink.lisp b/examples/Common Lisp/tasksink.lisp index 5a2b8fa..8b17a63 100644 --- a/examples/Common Lisp/tasksink.lisp +++ b/examples/Common Lisp/tasksink.lisp @@ -1,13 +1,58 @@ -No-one has translated the tasksink example into Common Lisp yet. Be the first to create -tasksink in Common Lisp and get one free Internet! If you're the author of the Common Lisp -binding, this is a great way to get people to use 0MQ in Common Lisp. +;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; -*- +;;; +;;; Task sink +;;; Binds PULL socket to tcp://localhost:5558 +;;; Collects results from workers via that socket +;;; +;;; 'with-stopwatch' macro is taken from 'cl-zmq' +;;; by Vitaly Mayatskikh <v.mayats...@gmail.com> +;;; +;;; Kamil Shakirov <kamil...@gmail.com> +;;; -To submit a new translation email it to zeromq-...@lists.zeromq.org. Please: +(defpackage #:zguide.tasksink + (:nicknames #:tasksink) + (:use #:cl #:zhelpers) + (:export #:main)) -* Stick to identical functionality and naming used in examples so that readers - can easily compare languages. -* You MUST place your name as author in the examples so readers can contact you. -* You MUST state in the email that you license your code under the MIT/X11 - license. +(in-package :zguide.tasksink) -Subscribe to this list at http://lists.zeromq.org/mailman/listinfo/zeromq-dev. +(defmacro with-stopwatch (&body body) + (let ((sec0 (gensym)) + (sec1 (gensym)) + (usec0 (gensym)) + (usec1 (gensym))) + `(multiple-value-bind (,sec0 ,usec0) + (isys:gettimeofday) + (unwind-protect + (progn ,@body)) + (multiple-value-bind (,sec1 ,usec1) + (isys:gettimeofday) + (+ (* 1e6 (- ,sec1 ,sec0)) + ,usec1 (- ,usec0)))))) + +(defun main () + ;; Prepare our context and socket + (zmq:with-context (context 1) + (zmq:with-socket (receiver context zmq:pull) + (zmq:bind receiver "tcp://*:5558") + + ;; Wait for start of batch + (let ((msg (make-instance 'zmq:msg))) + (zmq:recv receiver msg) + (let ((string (zmq:msg-data-as-string msg))) + ;; Start our clock now + (let ((elapsed-time + (with-stopwatch + (dotimes (task-nbr 100) + (zmq:recv receiver msg) + (setf string (zmq:msg-data-as-string msg)) + + (if (= 1 (denominator (/ task-nbr 10))) + (message ":") + (message ".")))))) + + ;; Calculate and report duration of batch + (message "Total elapsed time: ~F msec~%" (/ elapsed-time 1000.0))))))) + + (cleanup)) diff --git a/examples/Common Lisp/taskvent.lisp b/examples/Common Lisp/taskvent.lisp index 0b49d2d..1f344ad 100644 --- a/examples/Common Lisp/taskvent.lisp +++ b/examples/Common Lisp/taskvent.lisp @@ -1,13 +1,45 @@ -No-one has translated the taskvent example into Common Lisp yet. Be the first to create -taskvent in Common Lisp and get one free Internet! If you're the author of the Common Lisp -binding, this is a great way to get people to use 0MQ in Common Lisp. +;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; -*- +;;; +;;; Task ventilator +;;; Binds PUSH socket to tcp://localhost:5557 +;;; Sends batch of tasks to workers via that socket +;;; +;;; Kamil Shakirov <kamil...@gmail.com> +;;; -To submit a new translation email it to zeromq-...@lists.zeromq.org. Please: +(defpackage #:zguide.taskvent + (:nicknames #:taskvent) + (:use #:cl #:zhelpers) + (:export #:main)) -* Stick to identical functionality and naming used in examples so that readers - can easily compare languages. -* You MUST place your name as author in the examples so readers can contact you. -* You MUST state in the email that you license your code under the MIT/X11 - license. +(in-package :zguide.taskvent) -Subscribe to this list at http://lists.zeromq.org/mailman/listinfo/zeromq-dev. +(defun main () + (zmq:with-context (context 1) + ;; Socket to send messages on + (zmq:with-socket (sender context zmq:push) + (zmq:bind sender "tcp://*:5557") + + (message "Press Enter when the workers are ready: ") + (read-char) + (message "Sending tasks to workers...~%") + + ;; The first message is "0" and signals start of batch + (let ((msg (make-instance 'zmq:msg :data "0"))) + (zmq:send sender msg)) + + ;; Send 100 tasks + (let ((total-msec 0)) + (loop :repeat 100 :do + ;; Random workload from 1 to 100 msecs + (let ((workload (within 100))) + (incf total-msec workload) + (let ((msg (make-instance 'zmq:msg + :data (format nil "~D" workload)))) + (zmq:send sender msg)))) + + (message "Total expected cost: ~D msec~%" total-msec) + ;; Give 0MQ time to deliver + (sleep 1)))) + + (cleanup)) diff --git a/examples/Common Lisp/taskwork.lisp b/examples/Common Lisp/taskwork.lisp index 0b600b9..feb1c21 100644 --- a/examples/Common Lisp/taskwork.lisp +++ b/examples/Common Lisp/taskwork.lisp @@ -1,13 +1,46 @@ -No-one has translated the taskwork example into Common Lisp yet. Be the first to create -taskwork in Common Lisp and get one free Internet! If you're the author of the Common Lisp -binding, this is a great way to get people to use 0MQ in Common Lisp. +;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; -*- +;;; +;;; Task worker +;;; Connects PULL socket to tcp://localhost:5557 +;;; Collects workloads from ventilator via that socket +;;; Connects PUSH socket to tcp://localhost:5558 +;;; Sends results to sink via that socket +;;; +;;; Kamil Shakirov <kamil...@gmail.com> +;;; -To submit a new translation email it to zeromq-...@lists.zeromq.org. Please: +(defpackage #:zguide.taskwork + (:nicknames #:taskwork) + (:use #:cl #:zhelpers) + (:export #:main)) -* Stick to identical functionality and naming used in examples so that readers - can easily compare languages. -* You MUST place your name as author in the examples so readers can contact you. -* You MUST state in the email that you license your code under the MIT/X11 - license. +(in-package :zguide.taskwork) -Subscribe to this list at http://lists.zeromq.org/mailman/listinfo/zeromq-dev. +(defun main () + (zmq:with-context (context 1) + ;; Socket to receive messages on + (zmq:with-socket (receiver context zmq:pull) + (zmq:connect receiver "tcp://localhost:5557") + + ;; Socket to send messages to + (zmq:with-socket (sender context zmq:push) + (zmq:connect sender "tcp://localhost:5558") + + ;; Process tasks forever + (loop + (let ((pull-msg (make-instance 'zmq:msg))) + (zmq:recv receiver pull-msg) + + (let* ((string (zmq:msg-data-as-string pull-msg)) + (delay (* (parse-integer string) 1000))) + ;; Simple progress indicator for the viewer + (message "~A." string) + + ;; Do the work + (isys:usleep delay) + + ;; Send results to sink + (let ((push-msg (make-instance 'zmq:msg :data ""))) + (zmq:send sender push-msg)))))))) + + (cleanup)) diff --git a/examples/Common Lisp/wuclient.lisp b/examples/Common Lisp/wuclient.lisp index e60bc32..778dde0 100644 --- a/examples/Common Lisp/wuclient.lisp +++ b/examples/Common Lisp/wuclient.lisp @@ -16,21 +16,21 @@ (defun main () (zmq:with-context (context 1) - (format t "Collecting updates from weather server...~%") + (message "Collecting updates from weather server...~%") ;; Socket to talk to server (zmq:with-socket (subscriber context zmq:sub) (zmq:connect subscriber "tcp://localhost:5556") ;; Subscribe to zipcode, default is NYC, 10001 - (let ((filter (or (nth 1 (cmd-args)) "10001"))) + (let ((filter (or (first (cmd-args)) "10001 "))) (zmq:setsockopt subscriber zmq:subscribe filter) ;; Process 100 updates (let ((number-updates 100) (total-temp 0.0)) - (dotimes (update-nbr number-updates) + (loop :repeat number-updates :do (let ((update (make-instance 'zmq:msg))) (zmq:recv subscriber update) @@ -40,7 +40,7 @@ (declare (ignore zipcode_ relhumidity_)) (incf total-temp (parse-integer temperature))))) - (format t "Average temperature for zipcode ~A was ~FF~%" - filter (/ total-temp number-updates)))))) + (message "Average temperature for zipcode ~A was ~FF~%" + filter (/ total-temp number-updates)))))) (cleanup)) diff --git a/examples/Common Lisp/wuserver.lisp b/examples/Common Lisp/wuserver.lisp index a8b2637..f0b2dae 100644 --- a/examples/Common Lisp/wuserver.lisp +++ b/examples/Common Lisp/wuserver.lisp @@ -14,9 +14,6 @@ (in-package :zguide.wuserver) -(defun within (num) - (1+ (random num))) - (defun main () ;; Prepare our context and socket (zmq:with-context (context 1) diff --git a/examples/Common Lisp/zhelpers.lisp b/examples/Common Lisp/zhelpers.lisp index 61373ef..1722439 100644 --- a/examples/Common Lisp/zhelpers.lisp +++ b/examples/Common Lisp/zhelpers.lisp @@ -5,24 +5,38 @@ ;;; Kamil Shakirov <kamil...@gmail.com> ;;; -(eval-when (:compile-toplevel :load-toplevel :execute) - (require :split-sequence) - (require :zeromq)) - (defpackage #:zguide.zhelpers (:nicknames #:zhelpers) (:use #:cl) (:export - #:version + #:cmd-args + #:message #:cleanup - #:cmd-args)) + #:within + #:version + #:set-socket-id + #:dump-message + #:dump-socket)) (in-package :zguide.zhelpers) -(defun version () - (format t "Current 0MQ version is ~A~%" (zmq:version))) +(defun cmd-args () + "Return command line arguments." + (rest + (or + #+sbcl sb-ext:*posix-argv* + #+ccl ccl:*command-line-argument-list* + #+clisp ext:*args* + #+lispworks system:*line-arguments-list* + #+ecl (ext:command-args) + nil))) + +(defun message (fmt &rest args) + (apply #'format t fmt args) + (finish-output)) (defun cleanup () + "Cleanup and exit." (tg:gc) #+sbcl (sb-ext:quit) #+ccl (ccl:quit) @@ -30,11 +44,53 @@ #+lispworks (lispworks:quit) #+ecl (ext:quit)) -(defun cmd-args () - (or - #+sbcl sb-ext:*posix-argv* - #+ccl ccl:*command-line-argument-list* - #+clisp ext:*args* - #+lispworks system:*line-arguments-list* - #+ecl (ext:command-args) - nil)) +(defun within (num) + "Provide random number from 1..num." + (1+ (random num))) + +(defun version () + "Report 0MQ version number." + (message "Current 0MQ version is ~A~%" (zmq:version))) + +(defun set-socket-id (socket) + "Set simple random printable identity on socket." + (zmq:setsockopt socket zmq:identity + (format nil "~4,'0X-~4,'0X" + (within #x10000) (within #x10000)))) + +(defun text-message-p (msg) + (let ((data (zmq:msg-data-as-is msg))) + (loop :for i :from 0 :to (1- (zmq:msg-size msg)) + :with char = (cffi:mem-ref data :char i) :do + (when (or (< char 32) (> char 127)) + (return-from text-message-p nil))) + (values t))) + +(defun dump-binary-message (msg) + (let ((data (zmq:msg-data-as-array msg))) + (loop :for x :across data :do + (format t "~2,'0X" x)))) + +(defun dump-message (msg) + (format t "[~3,'0D] " (zmq:msg-size msg)) + (if (text-message-p msg) + (write-string (zmq:msg-data-as-string msg)) + (dump-binary-message msg)) + (terpri)) + +(defun dump-socket (socket) + "Receive all message parts from socket, print neatly." + (format t "----------------------------------------~%") + + (loop + ;; Process all parts of the message + (let ((message (make-instance 'zmq:msg))) + (zmq:recv socket message) + + ;; Dump the message as text or binary + (dump-message message) + (finish-output) + + ;; Multipart detection + (when (zerop (zmq:getsockopt socket zmq:rcvmore)) + (return))))) -- 1.7.0.4
_______________________________________________ zeromq-dev mailing list zeromq-dev@lists.zeromq.org http://lists.zeromq.org/mailman/listinfo/zeromq-dev