I tried to construct a function template that I can use in other packages with package-specific parameters. The gist of what I tried to achieve this is as follows:
;;; FSM
(in-package #:fsm)
(defmacro %cas (flag old new)
#+sbcl `(sb-ext:compare-and-swap ,flag ,old ,new)
#+ecl `(mp:compare-and-swap ,flag ,old ,new)
)
(defmacro control! (fsm task flag)
`(let ((*task-category* (tag ,task)))
(unless (%cas ,flag nil t)
(lambda () (submit-task (channel (cqueue-prio-out ,fsm)) (fn ,task))))))
;;; REPL
(in-package #:repl)
(defparameter *controller-active* nil)
(control! fsm control-task *controller-active*)
;;; USB-SP
(in-package #:usb-sp)
(defparameter *controller-active* nil)
(control! fsm control-task *controller-active*)
Apparently, this does not work:
Unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1001640703}>:
Invalid place to CAS: CNC-HOST/FSM::FLAG -> CNC-HOST/FSM::FLAG
How is this construct properly done?
After receiving feedback on the freenode lisp channel, it became clear to me that the macro construct works as intended:
(defpackage #:fsm (:use #:cl) (:export #:control!! #:%cas))
(defpackage #:repl (:use #:cl #:fsm) (:export #:test-in-repl))
(defpackage #:usb-sp (:use #:cl #:fsm) (:export #:test-in-usb-sp))
;;; FSM
(in-package #:fsm)
(defmacro %cas (flag old new)
#+sbcl `(sb-ext:compare-and-swap ,flag ,old ,new)
#+ecl `(mp:compare-and-swap ,flag ,old ,new))
(defmacro control!! (flag pkg)
`(lambda () (if (%cas ,flag nil t)
(format nil "~A : skip task" ,pkg)
(format nil "~A : task run" ,pkg))))
;;; REPL
(in-package #:repl)
(defparameter *controller-active* nil)
(defun test-in-repl (pkg) (funcall (control!! *controller-active* pkg)))
(assert (string= "repl : task run" (test-in-repl "repl")))
(assert *controller-active*)
;;; USB-SP
(in-package #:usb-sp)
(defparameter *controller-active* nil)
(defun test-in-usb-sp (pkg) (funcall (control!! usb-sp::*controller-active* pkg)))
(assert (string= "usb-sp : task run" (test-in-usb-sp "usb-sp")))
(assert *controller-active*)
(in-package #:cl-user)
(assert (string= "repl : skip task" (repl:test-in-repl "repl")))
(assert (string= "usb-sp : skip task" (usb-sp:test-in-usb-sp "usb-sp")))
The compiler message made me think that I had an error in the macros - instead I overlooked that in my use case control!!
should have returned the function call result instead of the lambda
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.