… | |
… | |
83 | pools are created by fork+exec, after which such modules can again be |
83 | pools are created by fork+exec, after which such modules can again be |
84 | loaded. |
84 | loaded. |
85 | |
85 | |
86 | =back |
86 | =back |
87 | |
87 | |
|
|
88 | =head1 CONCEPTS |
|
|
89 | |
|
|
90 | This module can create new processes either by executing a new perl |
|
|
91 | process, or by forking from an existing "template" process. |
|
|
92 | |
|
|
93 | Each such process comes with its own file handle that can be used to |
|
|
94 | communicate with it (it's actually a socket - one end in the new process, |
|
|
95 | one end in the main process), and among the things you can do in it are |
|
|
96 | load modules, fork new processes, send file handles to it, and execute |
|
|
97 | functions. |
|
|
98 | |
|
|
99 | There are multiple ways to create additional processes to execute some |
|
|
100 | jobs: |
|
|
101 | |
|
|
102 | =over 4 |
|
|
103 | |
|
|
104 | =item fork a new process from the "default" template process, load code, |
|
|
105 | run it |
|
|
106 | |
|
|
107 | This module has a "default" template process which it executes when it is |
|
|
108 | needed the first time. Forking from this process shares the memory used |
|
|
109 | for the perl interpreter with the new process, but loading modules takes |
|
|
110 | time, and the memory is not shared with anything else. |
|
|
111 | |
|
|
112 | This is ideal for when you only need one extra process of a kind, with the |
|
|
113 | option of starting and stipping it on demand. |
|
|
114 | |
|
|
115 | =item fork a new template process, load code, then fork processes off of |
|
|
116 | it and run the code |
|
|
117 | |
|
|
118 | When you need to have a bunch of processes that all execute the same (or |
|
|
119 | very similar) tasks, then a good way is to create a new template process |
|
|
120 | for them, loading all the modules you need, and then create your worker |
|
|
121 | processes from this new template process. |
|
|
122 | |
|
|
123 | This way, all code (and data structures) that can be shared (e.g. the |
|
|
124 | modules you loaded) is shared between the processes, and each new process |
|
|
125 | consumes relatively little memory of its own. |
|
|
126 | |
|
|
127 | The disadvantage of this approach is that you need to create a template |
|
|
128 | process for the sole purpose of forking new processes from it, but if you |
|
|
129 | only need a fixed number of proceses you can create them, and then destroy |
|
|
130 | the template process. |
|
|
131 | |
|
|
132 | =item execute a new perl interpreter, load some code, run it |
|
|
133 | |
|
|
134 | This is relatively slow, and doesn't allow you to share memory between |
|
|
135 | multiple processes. |
|
|
136 | |
|
|
137 | The only advantage is that you don't have to have a template process |
|
|
138 | hanging around all the time to fork off some new processes, which might be |
|
|
139 | an advantage when there are long time spans where no extra processes are |
|
|
140 | needed. |
|
|
141 | |
|
|
142 | =back |
|
|
143 | |
|
|
144 | =head1 FUNCTIONS |
|
|
145 | |
88 | =over 4 |
146 | =over 4 |
89 | |
147 | |
90 | =cut |
148 | =cut |
91 | |
149 | |
92 | package AnyEvent::ProcessPool; |
150 | package AnyEvent::ProcessPool; |
… | |
… | |
127 | undef |
185 | undef |
128 | ] |
186 | ] |
129 | } |
187 | } |
130 | |
188 | |
131 | sub queue_cmd { |
189 | sub queue_cmd { |
132 | my ($queue, $cmd) = @_; |
190 | my $queue = shift; |
133 | |
191 | |
134 | push @{ $queue->[2] }, pack "N/a", $cmd; |
192 | push @{ $queue->[2] }, pack "N/a", pack "a (w/a)*", @_; |
135 | |
193 | |
136 | $queue->[3] ||= AE::io $queue->[1], 1, sub { |
194 | $queue->[3] ||= AE::io $queue->[1], 1, sub { |
137 | if (ref $queue->[2][0]) { |
195 | if (ref $queue->[2][0]) { |
138 | AnyEvent::ProcessPool::Util::fd_send fileno $queue->[1], fileno ${ $queue->[2][0] } |
196 | AnyEvent::ProcessPool::Util::fd_send fileno $queue->[1], fileno ${ $queue->[2][0] } |
139 | and shift @{ $queue->[2] }; |
197 | and shift @{ $queue->[2] }; |