186 lines
4.7 KiB
EmacsLisp
186 lines
4.7 KiB
EmacsLisp
|
;;; Sample code for concurrent.el -*- lexical-binding: t; -*-
|
|||
|
|
|||
|
;; Evaluate following code in the scratch buffer.
|
|||
|
|
|||
|
(require 'cl-lib)
|
|||
|
(require 'concurrent)
|
|||
|
|
|||
|
;;==================================================
|
|||
|
;;; generator
|
|||
|
|
|||
|
(defvar fib-list nil)
|
|||
|
|
|||
|
(defvar fib-gen ; Create a generator object.
|
|||
|
(let ((a1 0) (a2 1))
|
|||
|
(cc:generator
|
|||
|
(lambda (x) (push x fib-list)) ; receiving values
|
|||
|
(yield a1)
|
|||
|
(yield a2)
|
|||
|
(while t
|
|||
|
(let ((next (+ a1 a2)))
|
|||
|
(setq a1 a2
|
|||
|
a2 next)
|
|||
|
(yield next))))))
|
|||
|
|
|||
|
(funcall fib-gen) ; Generate 5 times
|
|||
|
(funcall fib-gen) (funcall fib-gen)
|
|||
|
(funcall fib-gen) (funcall fib-gen)
|
|||
|
|
|||
|
fib-list ;=> (3 2 1 1 0)
|
|||
|
|
|||
|
|
|||
|
;;==================================================
|
|||
|
;;; thread
|
|||
|
|
|||
|
(let ((count 0) (anm "-/|\\-")
|
|||
|
(end 50) (pos (point)))
|
|||
|
(cc:thread
|
|||
|
60
|
|||
|
(message "Animation started.")
|
|||
|
(while (> end (cl-incf count))
|
|||
|
(save-excursion
|
|||
|
(when (< 1 count)
|
|||
|
(goto-char pos) (delete-char 1))
|
|||
|
(insert (char-to-string
|
|||
|
(aref anm (% count (length anm)))))))
|
|||
|
(save-excursion
|
|||
|
(goto-char pos) (delete-char 1))
|
|||
|
(message "Animation finished.")))
|
|||
|
|
|||
|
;; Play the simple character animation here.
|
|||
|
|
|||
|
|
|||
|
;;==================================================
|
|||
|
;;; semaphore
|
|||
|
|
|||
|
;; create a semaphore object with permit=1.
|
|||
|
(defvar smp (cc:semaphore-create 1))
|
|||
|
|
|||
|
;; executing three tasks...
|
|||
|
(deferred:nextc (cc:semaphore-acquire smp)
|
|||
|
(lambda (_)
|
|||
|
(message "go1")))
|
|||
|
(deferred:nextc (cc:semaphore-acquire smp)
|
|||
|
(lambda (_)
|
|||
|
(message "go2")))
|
|||
|
(deferred:nextc (cc:semaphore-acquire smp)
|
|||
|
(lambda (_)
|
|||
|
(message "go3")))
|
|||
|
|
|||
|
;; => Only the fist task is executed and displays "go1".
|
|||
|
|
|||
|
(cc:semaphore-release smp)
|
|||
|
|
|||
|
;; => The second task is executed and displays "go2".
|
|||
|
|
|||
|
(cc:semaphore-waiting-deferreds smp) ; return the deferred object that displays "go3".
|
|||
|
|
|||
|
(cc:semaphore-release-all smp) ; => reset permit count and return the deferred object that displays "go3".
|
|||
|
|
|||
|
(cc:semaphore-waiting-deferreds smp) ; => nil
|
|||
|
|
|||
|
|
|||
|
;;==================================================
|
|||
|
;; Dataflow
|
|||
|
|
|||
|
;; create a parent environment and bind "aaa" to 256.
|
|||
|
(defvar dfenv-parent (cc:dataflow-environment))
|
|||
|
(cc:dataflow-set dfenv-parent "aaa" 256)
|
|||
|
|
|||
|
;; create an environment with the parent one.
|
|||
|
(defvar dfenv (cc:dataflow-environment dfenv-parent))
|
|||
|
|
|||
|
;; Return the parent value.
|
|||
|
(cc:dataflow-get-sync dfenv "aaa") ; => 256
|
|||
|
|
|||
|
(deferred:$
|
|||
|
(cc:dataflow-get dfenv "abc")
|
|||
|
(deferred:nextc it
|
|||
|
(lambda (x) (message "Got abc : %s" x))))
|
|||
|
;; => This task is blocked
|
|||
|
|
|||
|
(cc:dataflow-set dfenv "abc" 256) ; bind 256 to "abc"
|
|||
|
|
|||
|
;; => The blocked task is executed and displays "Got abc : 256".
|
|||
|
|
|||
|
(cc:dataflow-get-sync dfenv "abc") ; => 256
|
|||
|
|
|||
|
;; unbind the variable "abc"
|
|||
|
(cc:dataflow-clear dfenv "abc")
|
|||
|
|
|||
|
(cc:dataflow-get-sync dfenv "abc") ; => nil
|
|||
|
|
|||
|
|
|||
|
;; complicated key (`equal' can compare nested lists.)
|
|||
|
|
|||
|
(deferred:$
|
|||
|
(cc:dataflow-get dfenv '("http://example.com/a.jpg" 300))
|
|||
|
(deferred:nextc it
|
|||
|
(lambda (x) (message "a.jpg:300 OK %s" x))))
|
|||
|
|
|||
|
(cc:dataflow-set dfenv '("http://example.com/a.jpg" 300) 'jpeg)
|
|||
|
|
|||
|
;; waiting for two variables
|
|||
|
|
|||
|
(deferred:$
|
|||
|
(deferred:parallel
|
|||
|
(cc:dataflow-get dfenv "abc")
|
|||
|
(cc:dataflow-get dfenv "def"))
|
|||
|
(deferred:nextc it
|
|||
|
(lambda (values)
|
|||
|
(apply 'message "Got values : %s, %s" values)
|
|||
|
(apply '+ values)))
|
|||
|
(deferred:nextc it
|
|||
|
(lambda (x) (insert (format ">> %s" x)))))
|
|||
|
|
|||
|
(cc:dataflow-get-waiting-keys dfenv) ; => ("def" "abc")
|
|||
|
(cc:dataflow-get-avalable-pairs dfenv) ; => (("aaa" . 256))
|
|||
|
|
|||
|
(cc:dataflow-set dfenv "abc" 128)
|
|||
|
(cc:dataflow-set dfenv "def" 256)
|
|||
|
|
|||
|
;; => "Got values : 128, 256"
|
|||
|
;; inserted ">> 384"
|
|||
|
|
|||
|
(cc:dataflow-get-avalable-pairs dfenv)
|
|||
|
|
|||
|
(cc:dataflow-clear-all dfenv)
|
|||
|
|
|||
|
(cc:dataflow-get-avalable-pairs dfenv)
|
|||
|
|
|||
|
|
|||
|
;;==================================================
|
|||
|
;; Signal
|
|||
|
|
|||
|
(progn
|
|||
|
(defvar parent-channel (cc:signal-channel "parent"))
|
|||
|
(cc:signal-connect
|
|||
|
parent-channel 'parent-load
|
|||
|
(lambda (event) (message "Parent Signal : %s" event)))
|
|||
|
(cc:signal-connect
|
|||
|
parent-channel t
|
|||
|
(lambda (event) (message "Parent Listener : %s" event)))
|
|||
|
|
|||
|
(defvar channel (cc:signal-channel "child" parent-channel))
|
|||
|
(cc:signal-connect
|
|||
|
channel 'window-load
|
|||
|
(lambda (event) (message "Signal : %s" event)))
|
|||
|
(cc:signal-connect
|
|||
|
channel t
|
|||
|
(lambda (event) (message "Listener : %s" event)))
|
|||
|
(deferred:$
|
|||
|
(cc:signal-connect channel 'window-load)
|
|||
|
(deferred:nextc it
|
|||
|
(lambda (x) (message "Deferred Signal : %s" x))))
|
|||
|
)
|
|||
|
|
|||
|
(cc:signal-send channel 'window-load "hello signal!")
|
|||
|
(cc:signal-send channel 'some "some signal!")
|
|||
|
|
|||
|
(cc:signal-send parent-channel 'parent-load "parent hello!")
|
|||
|
(cc:signal-send parent-channel 'window-load "parent hello!")
|
|||
|
(cc:signal-send parent-channel 'some "parent some hello!")
|
|||
|
(cc:signal-send-global channel 'some "parent some hello!")
|
|||
|
|
|||
|
(cc:signal-disconnect-all channel)
|