线程间消息传递的最佳风格?
Best style for message passing between threads?
我想异步调用各种线程中的函数,每个线程都有特定的 state
,因此我将消息发送到给定线程并让该线程对这些消息进行操作。我想知道的是,这些消息最合理的样式是什么。我可以想到三种可能性。 (所有例子都排除了线程机制,以免复杂化。)
- 基于关键字的消息,根据状态和关键字进行调度。
(defclass state () ())
(defgeneric dispatch (object method args))
(defmethod dispatch ((object state) (method (eql :bazinga)) args)
(destructuring-bind (arg1 arg2) args
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2)))
(let ((state (make-instance 'state))
(msg '(:bazinga 10 20))) ; message example
(dispatch state (car msg) (cdr msg)))
- 基于函数的消息,根据状态进行调度。
(defclass state () ())
(defgeneric bazinga (object arg1 arg2))
(defmethod bazinga ((object state) arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (list #'bazinga 10 20))) ; message example
(apply (car msg) state (cdr msg)))
2.1 基于函数的消息,具有状态调度和通过闭包传递的参数(来自 RowPJ 的评论)
(defclass state () ())
(defgeneric bazinga (object arg1 arg2))
(defmethod bazinga ((object state) arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (lambda (obj) (bazinga obj 10 20))))
(funcall msg state))
- 基于函数的消息,"hardcoded dispatch"。
(defclass state () ()) ; could be a structure instead
(defun state-bazinga (object arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (list #'state-bazinga 10 20))) ; message example
(apply (car msg) state (cdr msg)))
3.1 - 与 2.1 类似,此处略过。
我不太可能有任何类型的对象层次结构,所以我觉得这些样式之间没有真正的区别。那么,这真的只是个人喜好问题,还是有 objective 利弊?随着程序的发展,这些样式中的任何一种都可能更易于使用,还是会受到更多限制?我知道这不是一个明确的问题,但希望它仍然相当清楚我在问什么。
call functions in various threads
一个基本模型是一个等待循环,它监视自己的队列/邮箱并执行放入该队列/邮箱的功能。
将您想要的任何函数放入该队列。
这可以扩展为将函数及其参数入队。
LispWorks GUI 库使用该模型:apply-in-pane-process。
心智模型很简单,就是APPLY
在一个特定的进程中执行:apply-in-process <process> <function> <args>
。在 Lisp 中,我首先想到的是函数式。 APPLY 是一个基本的函数调用操作符。现在使用类似的版本,它只是在特定进程中应用。然后可以应用 lambda、闭包、命名函数、CLOS 函数,...
有了它,就可以实现自己想要的各种调用约定。
我想异步调用各种线程中的函数,每个线程都有特定的 state
,因此我将消息发送到给定线程并让该线程对这些消息进行操作。我想知道的是,这些消息最合理的样式是什么。我可以想到三种可能性。 (所有例子都排除了线程机制,以免复杂化。)
- 基于关键字的消息,根据状态和关键字进行调度。
(defclass state () ())
(defgeneric dispatch (object method args))
(defmethod dispatch ((object state) (method (eql :bazinga)) args)
(destructuring-bind (arg1 arg2) args
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2)))
(let ((state (make-instance 'state))
(msg '(:bazinga 10 20))) ; message example
(dispatch state (car msg) (cdr msg)))
- 基于函数的消息,根据状态进行调度。
(defclass state () ())
(defgeneric bazinga (object arg1 arg2))
(defmethod bazinga ((object state) arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (list #'bazinga 10 20))) ; message example
(apply (car msg) state (cdr msg)))
2.1 基于函数的消息,具有状态调度和通过闭包传递的参数(来自 RowPJ 的评论)
(defclass state () ())
(defgeneric bazinga (object arg1 arg2))
(defmethod bazinga ((object state) arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (lambda (obj) (bazinga obj 10 20))))
(funcall msg state))
- 基于函数的消息,"hardcoded dispatch"。
(defclass state () ()) ; could be a structure instead
(defun state-bazinga (object arg1 arg2)
(format t "arg1 = ~a, arg2 = ~a~%" arg1 arg2))
(let ((state (make-instance 'state))
(msg (list #'state-bazinga 10 20))) ; message example
(apply (car msg) state (cdr msg)))
3.1 - 与 2.1 类似,此处略过。
我不太可能有任何类型的对象层次结构,所以我觉得这些样式之间没有真正的区别。那么,这真的只是个人喜好问题,还是有 objective 利弊?随着程序的发展,这些样式中的任何一种都可能更易于使用,还是会受到更多限制?我知道这不是一个明确的问题,但希望它仍然相当清楚我在问什么。
call functions in various threads
一个基本模型是一个等待循环,它监视自己的队列/邮箱并执行放入该队列/邮箱的功能。
将您想要的任何函数放入该队列。
这可以扩展为将函数及其参数入队。
LispWorks GUI 库使用该模型:apply-in-pane-process。
心智模型很简单,就是APPLY
在一个特定的进程中执行:apply-in-process <process> <function> <args>
。在 Lisp 中,我首先想到的是函数式。 APPLY 是一个基本的函数调用操作符。现在使用类似的版本,它只是在特定进程中应用。然后可以应用 lambda、闭包、命名函数、CLOS 函数,...
有了它,就可以实现自己想要的各种调用约定。