如何在ABCL中生成背景(命名)子流程/线程?也就是说,我想生成子进程(或线程)以在后台运行并让顶级评估免费用于其他处理。
使用(apropos'进程/线程)我找到了下面列出的未记录的函数,但我无法弄清楚语法。我正在寻找运行示例代码来关注/修改。我似乎已经创建了一个具有以下make-process函数的进程,但是当我尝试杀死它时出现错误,并且它在前台运行。 ABCL手册中没有关于make-process的条目。列出MAKE-THREAD,但未记录。
ABCL手册中列出的所有功能的文档/示例在哪里?#34; 未记录"指定? (还有那些与apropos一起发现的那些?)
作为一个单独但相关的问题,是否有一个在线ABCL特定运行代码示例的存储库,涵盖了像这样的边缘案例问题?
在其他常见的lisps中,我会使用以下函数:
pmap
或
(activate-process *initial-process*)
在ABCL,我已经糊里糊涂了不远处:
#+(:and MULTITASKING :lucid)
(defun mpd (&optional (reinit nil))
(user::make-process :name "Pdraw-proc" :function #'pd::pdraw :args (list reinit)))
和
CL-USER> (setf uu (make-thread (my-reader))) <-- runs at the top level / hogs read loop
CL-USER> (setf jj (system::%make-process (foo)))
#S(SYSTEM:PROCESS :JPROCESS 3 :INPUT NIL :OUTPUT NIL :ERROR NIL)
CL-USER> jj
#S(SYSTEM:PROCESS :JPROCESS 3 :INPUT NIL :OUTPUT NIL :ERROR NIL)
SYSTEM::MAKE-PROCESS (fbound)
SYSTEM::%PROCESS-KILL (fbound)
SYSTEM::%MAKE-PROCESS (fbound)
和
THREADS:MAKE-THREAD (fbound)
THREADS:DESTROY-THREAD (fbound)
[为线程创建必要的流的语法/示例可能?]
提前感谢指针或代码。
答案 0 :(得分:4)
我将ABCL与roswell一起使用,因此很容易与quicklisp结合使用,但是还有一个that的项目,但我认为您可以在ABCL中轻松使用quicklisp或加载库。有很多库可以在ABCL上加载来自quicklisp,遗憾的是并非所有(Quicklisp都是通过linux和SBCL测试的),但是对于并发性,你可以加载两个我通常使用的优秀库bordeaux-threads(常见的lisp中的常见威胁库和Chanl一个端口可以移植到常见的lisp的库。还有其他一些你可以尝试,但我不确定他们是否工作lparallel,cl-actors ......
让我们用这个库做一个例子:
CL-USER> (lisp-implementation-type)
"Armed Bear Common Lisp"
CL-USER> (lisp-implementation-version)
"1.5.0"
"Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.8.0_162-b12"
"x86_64-Mac_OS_X-10.12.6"
CL-USER> (ql:quickload 'bt-semaphore)
To load "bt-semaphore":
Load 1 ASDF system:
bt-semaphore
; Loading "bt-semaphore"
[package bt-semaphore]
(BT-SEMAPHORE)
CL-USER> bt:*supports-threads-p*
T
CL-USER> (defparameter *counter* 0)
*COUNTER*
CL-USER> (defun test-update-global-variable ()
(bt:make-thread
(lambda ()
(sleep 10)
(incf *counter*)))
*counter*)
TEST-UPDATE-GLOBAL-VARIABLE
CL-USER> *counter*
0 (0 bits, #x0, #o0, #b0)
CL-USER> (test-update-global-variable)
0 (0 bits, #x0, #o0, #b0)
CL-USER> *counter*
0 (0 bits, #x0, #o0, #b0)
CL-USER> (+ 2 3)
5 (3 bits, #x5, #o5, #b101)
CL-USER> (format t "I'm wainting for counter")
I'm wainting for counter
NIL
CL-USER> (format t "let'see the counter value ~a~%" *counter*)
let'see the counter value 1
NIL
CL-USER> (ql:quickload :chanl)
To load "chanl":
Load 1 ASDF system:
chanl
; Loading "chanl"
(:CHANL)
CL-USER> (chanl:pcall (lambda () (sleep 10) (incf *counter*)))
#<CHANL:TASK Anonymous task [ALIVE] {2360938E}>
CL-USER> *counter*
1 (1 bit, #x1, #o1, #b1)
CL-USER> ;; waiting
; No values
CL-USER> *counter*
2 (2 bits, #x2, #o2, #b10)
请注意,这只是示例purpouses一个全局变量不是很好用于威胁,也可以查看库以获取进一步的文档,这应该可以工作,而且你在ABCL中很容易使用java库,所以也许你可以使用akka actors或其他java并发库
另外,当您指出ABCL有威胁包时,它很容易使用,如下所示:
CL-USER> (threads:make-thread (lambda () (sleep 10) (incf *counter*)) :name 'patata)
#<THREAD "PATATA" {49998577}>
CL-USER> *counter*
2 (2 bits, #x2, #o2, #b10)
CL-USER> ; wait
; No values
CL-USER> *counter*
3 (2 bits, #x3, #o3, #b11)
它还实施了mailbox个威胁,将消息传递给线程
答案 1 :(得分:0)
随着Vibhu的提示我找到了Anquegi提出的相同原生解决方案。感谢:name arg!
CL-USER> (lisp-implementation-type)
"Armed Bear Common Lisp"
CL-USER> (lisp-implementation-version)
"1.3.3"
"Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.8.0_161-b12"
"amd64-Windows_7-6.1"
CL-USER>
(setf my-val 1)
;;; Output to *standard-output* for Inferior Lisp, so careful with SLIME:
(defun make-my-thread ()
(setf q
(threads:make-thread
#'(lambda ()
(format t "I am alive!~%")
(sleep 15)
(format t "Goodbye Cruel World~%")
(setf my-val (1+ my-val))))))
;;; Works, but takes a while:
(defun kill-it () (threads:destroy-thread q))
(defun alivep () (THREADS:THREAD-ALIVE-P q))
(make-my-thread)在后台运行,不会占用标准输入
可以查询my-val ,直到睡眠后才设置。
(alivep)返回T,直到线程完成 或者直到(kill-it)之后几秒钟,然后是NIL。
因此,这个最小的功能现在允许我在后台运行线程具有很大的灵活性。