]> code.delx.au - gnu-emacs/blob - lisp/emacs-parallel/README.org
Recognize more format variation. Automatically reshow decrypted text.
[gnu-emacs] / lisp / emacs-parallel / README.org
1 * Emacs Parallel
2
3 Emacs Parallel is yet another library to simulate parallel
4 computations in Emacs (because it lacks threads support in Elisp).
5
6 * STARTED HowTo
7
8 You can execute a simple function a retrive the result like this:
9 #+BEGIN_SRC emacs-lisp
10 (parallel-get-result (parallel-start (lambda () (* 42 42))))
11 ⇒ 1764
12 #+END_SRC
13
14 Though you won't benefit from the parallelism because
15 ~parallel-get-result~ is blocking, that is it waits for the function
16 to be executed.
17
18 So you can use define a callback to be called when the function is
19 finished:
20 #+BEGIN_SRC emacs-lisp
21 (parallel-start (lambda () (sleep-for 4.2) "Hello World")
22 :post-exec (lambda (results _status)
23 (message (first results))))
24 ⊣ Hello World
25 #+END_SRC
26
27 Here, why ~(first results)~ and not ~result~? Because you can send
28 data from the remote instance while it's running with
29 ~parallel-remote-send~:
30 #+BEGIN_SRC emacs-lisp
31 (parallel-start (lambda ()
32 (parallel-remote-send "Hello")
33 (sleep-for 4.2)
34 "World")
35 :post-exec (lambda (results _status)
36 (message "%s"
37 (mapconcat #'identity (reverse results) " "))))
38 ⊣ Hello World
39 #+END_SRC
40 As you may have noticed the results are pushed in a list, so the
41 first element is the result returned by the function called, the
42 second is the last piece of data send, and so on...
43
44 And of course you can execute some code when you receive data from
45 the remote instance:
46 #+BEGIN_SRC emacs-lisp
47 (parallel-start (lambda ()
48 (parallel-remote-send 42)
49 (sleep-for 4.2) ; heavy computation to compute PI
50 pi)
51 :on-event (lambda (data)
52 (message "Received %S" data)))
53 ⊣ Received 42
54 ⊣ Received 3.141592653589793
55 #+END_SRC
56
57 Because the function is executed in another Emacs instance (in Batch
58 Mode by default), the environment isn't the same. However you can
59 send some data with the ~env~ parameter:
60 #+BEGIN_SRC emacs-lisp
61 (let ((a 42)
62 (b 12))
63 (parallel-get-result (parallel-start (lambda (a b) (+ a b))
64 :env (list a b))))
65 ⇒ 54
66 #+END_SRC
67
68 By default, the remote Emacs instance is exited when the function is
69 executed, but you can keep it running with the
70 ~:continue-when-executed~ option and send new code to be executed
71 with ~parellel-send~.
72 #+BEGIN_SRC emacs-lisp
73 (let ((task (parallel-start (lambda () 42)
74 :continue-when-executed t)))
75 (sleep-for 4.2)
76 (parallel-send task (lambda () (setq parallel-continue-when-executed nil) 12))
77 (parallel-get-results task))
78 ⇒ (12 42)
79 #+END_SRC
80
81 As you can see, to stop the remote instance you have to set the
82 variable ~parallel-continue-when-executed~ to nil.
83
84 * Modules
85
86 ** Parallel XWidget
87
88 [[http://www.emacswiki.org/emacs/EmacsXWidgets][Emacs XWidget]] is an experimental branch which permits to embed GTK+
89 widget inside Emacs buffers. For instance, it is possible to use it
90 to render an HTML page using the webkit engine within an Emacs
91 buffer.
92
93 With this module, you can configure your "main" Emacs to use
94 another one to render web pages.
95
96 Let's assume that you've cloned [[https://github.com/jave/xwidget-emacs][the Emacs XWidget repository]] in
97 ~$HOME/src/emacs-xwidget/~. Once you've compiled it, an Emacs
98 executable is available ~$HOME/src/emacs-xwidget/src/emacs~.
99
100 Configure ~parallel-xwidget~ to use it:
101 #+BEGIN_SRC emacs-lisp
102 (setq parallel-xwidget-config (list :emacs-path
103 (concat (getenv "HOME")
104 "/src/emacs-xwidget/src/emacs")))
105 #+END_SRC
106
107 Then configure your current Emacs to use it:
108 #+BEGIN_SRC emacs-lisp
109 (setq browse-url-browser-function 'parallel-xwidget-browse-url)
110 #+END_SRC
111
112 You can check it out with M-x browse-url RET google.com RET.
113
114 * Tips & Tricks
115
116 If your windows manager is smart enough (like StumpwWM) you can use
117 it to move graphical windows (Emacs frames) in another desktop.
118
119 For example, I use this to move Emacs frames (with the title
120 "emacs-debug") to the group (aka desktop) 9:
121 #+BEGIN_SRC lisp
122 (define-frame-preference "9"
123 (0 nil t :title "emacs-debug"))
124 #+END_SRC
125
126 And this to specify the title of the frame:
127 #+BEGIN_SRC emacs-lisp
128 (parallel-start (lambda () 42)
129 :no-batch t
130 :emacs-args '("-T" "emacs-debug"))
131 #+END_SRC
132
133 * TODO How does it work?
134
135 * Known limitations
136
137 You can only send data to the remote (with the ~env~ parameter) or
138 from the remote (with ~parallel-send~ and ~parallel-remote-send~)
139 that have a printed representation (see [[info:elisp#Printed%20Representation][info:elisp#Printed
140 Representation]]).
141
142 So you can pass around numbers, symbols, strings, lists, vectors,
143 hash-table but you can't pass buffers, windows, frames...
144
145
146 It lacks documentation, tests and probably a clean API, but I'm
147 working on it!