@@ -251,16 +251,16 @@ <h2 id="synchronous-asynchronous-execution">Synchronous & Asynchronous Execu
251
251
Task 8 done
252
252
Task 9 done
253
253
Asynchronous:
254
- Task 0 done
255
- Task 2 done
254
+ Task 8 done
255
+ Task 5 done
256
256
Task 6 done
257
+ Task 3 done
258
+ Task 9 done
259
+ Task 2 done
257
260
Task 7 done
261
+ Task 0 done
258
262
Task 1 done
259
263
Task 4 done
260
- Task 3 done
261
- Task 5 done
262
- Task 8 done
263
- Task 9 done
264
264
</ pre > </ code > </ p >
265
265
< p > In the synchronous case all the tasks are run sequentially,
266
266
which results in the main programming < em > blocking</ em > (
@@ -946,11 +946,11 @@ <h2 id="groups-and-pools">Groups and Pools</h2>
946
946
< p > </ code >
947
947
< pre > < code class ="python ">
948
948
Size of group 3
949
- Hello from Greenlet 14533328
949
+ Hello from Greenlet 22721552
950
950
Size of group 3
951
- Hello from Greenlet 14533808
951
+ Hello from Greenlet 22722672
952
952
Size of group 3
953
- Hello from Greenlet 14534768
953
+ Hello from Greenlet 22724432
954
954
Ordered
955
955
('task', 0)
956
956
('task', 1)
@@ -1142,8 +1142,9 @@ <h2 id="thread-locals">Thread Locals</h2>
1142
1142
idea of using thread locals as local session storage is nonetheless the
1143
1143
same.</ p >
1144
1144
< h2 id ="subprocess "> Subprocess</ h2 >
1145
- < p > As of Gevent 1.0, support has been added for cooperative waiting
1146
- on subprocess.</ p >
1145
+ < p > As of gevent 1.0, < code > gevent.subprocess</ code > -- a patched version of Python's
1146
+ < code > subprocess</ code > module -- has been added. It supports cooperative waiting on
1147
+ subprocesses.</ p >
1147
1148
< pre >
1148
1149
< code class ="python "> import gevent
1149
1150
from gevent.subprocess import Popen, PIPE
@@ -1154,18 +1155,23 @@ <h2 id="subprocess">Subprocess</h2>
1154
1155
1155
1156
output = read_output.join()
1156
1157
print(output.value)
1157
- < code >
1158
+ </ code >
1158
1159
</ pre >
1159
1160
1160
1161
< pre >
1161
1162
< code class ="python "> Linux
1162
- < code >
1163
+ </ code >
1163
1164
</ pre >
1164
1165
1165
- < p > Many people also want to use gevent and multiprocessing together. This
1166
- can be done as most multiprocessing objects expose the underlying file
1167
- descriptors.</ p >
1168
- < pre > < code class ="python ">
1166
+ < p > Many people also want to use < code > gevent</ code > and < code > multiprocessing</ code > together. One of
1167
+ the most obvious challenges is that inter-process communication provided by
1168
+ < code > multiprocessing</ code > is not cooperative by default. Since
1169
+ < code > multiprocessing.Connection</ code > -based objects (such as < code > Pipe</ code > ) expose their
1170
+ underlying file descriptors, < code > gevent.socket.wait_read</ code > and < code > wait_write</ code > can
1171
+ be used to cooperatively wait for ready-to-read/ready-to-write events before
1172
+ actually reading/writing:</ p >
1173
+ < pre >
1174
+ < code class ="python ">
1169
1175
import gevent
1170
1176
from multiprocessing import Process, Pipe
1171
1177
from gevent.socket import wait_read, wait_write
@@ -1198,11 +1204,29 @@ <h2 id="subprocess">Subprocess</h2>
1198
1204
g1 = gevent.spawn(get_msg)
1199
1205
g2 = gevent.spawn(put_msg)
1200
1206
gevent.joinall([g1, g2], timeout=1)
1207
+ </ code >
1201
1208
</ pre >
1202
1209
1203
- < p > </ code >
1204
- < pre > < code class ="python ">
1205
- </ pre > </ code > </ p >
1210
+ < p > Note, however, that the combination of < code > multiprocessing</ code > and gevent brings
1211
+ along certain OS-dependent pitfalls, among others:</ p >
1212
+ < ul >
1213
+ < li > After < a href ="http://linux.die.net/man/2/fork "> forking</ a > on POSIX-compliant systems
1214
+ gevent's state in the child is ill-posed. One side effect is that greenlets
1215
+ spawned before < code > multiprocessing.Process</ code > creation run in both, parent and
1216
+ child process.</ li >
1217
+ < li > < code > a.send()</ code > in < code > put_msg()</ code > above might still block the calling thread
1218
+ non-cooperatively: a ready-to-write event only ensures that one byte can be
1219
+ written. The underlying buffer might be full before the attempted write is
1220
+ complete.</ li >
1221
+ < li > The < code > wait_write()</ code > / < code > wait_read()</ code > -based approach as indicated above does
1222
+ not work on Windows (< code > IOError: 3 is not a socket (files are not supported)</ code > ),
1223
+ because Windows cannot watch pipes for events.</ li >
1224
+ </ ul >
1225
+ < p > The Python package < a href ="http://pypi.python.org/pypi/gipc "> gipc</ a > overcomes these
1226
+ challenges for you in a largely transparent fashion on both, POSIX-compliant and
1227
+ Windows systems. It provides gevent-aware < code > multiprocessing.Process</ code > -based
1228
+ child processes and gevent-cooperative inter-process communication based on
1229
+ pipes.</ p >
1206
1230
< h2 id ="actors "> Actors</ h2 >
1207
1231
< p > The actor model is a higher level concurrency model popularized
1208
1232
by the language Erlang. In short the main idea is that you have a
0 commit comments