ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Multicore/perlmulticore.h
(Generate patch)

Comparing Coro-Multicore/perlmulticore.h (file contents):
Revision 1.2 by root, Sat Jun 27 19:36:39 2015 UTC vs.
Revision 1.8 by root, Sun Jun 28 18:37:52 2015 UTC

1TODO: if () acquire example
2/* 1/*
3 * Author: Marc A. Lehmann <xsthreadpool@schmorp.de> 2 * Author: Marc A. Lehmann <xsthreadpool@schmorp.de>
4 * License: public domain, or where this is not possible/at your option, 3 * License: public domain, or where this is not possible/at your option,
5 * CC0 (https://creativecommons.org/publicdomain/zero/1.0/) 4 * CC0 (https://creativecommons.org/publicdomain/zero/1.0/)
6 */ 5 */
7 6
8#ifndef PERL_MULTICORE_H 7#ifndef PERL_MULTICORE_H
9#define PERL_MULTICORE_H 8#define PERL_MULTICORE_H
10 9
11#if 0 10/*
12 11
13=head1 NAME 12=head1 NAME
14 13
15perlmulticore.h - release the perl interpreter for other uses while doing hard work 14perlmulticore.h - the Perl Multicore Specification and Implementation
16 15
17=head1 SYNOPSIS 16=head1 SYNOPSIS
18 17
19 #include "perlmultiore.h" 18 #include "perlmultiore.h"
20 19
35applicability. 34applicability.
36 35
37The newest version of this document can be found at 36The newest version of this document can be found at
38L<http://pod.tst.eu/http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. 37L<http://pod.tst.eu/http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>.
39 38
40The nwest version of the header fgile itself, which 39The newest version of the header file itself, which
41includes this documentation, can be downloaded from 40includes this documentation, can be downloaded from
42L<http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. 41L<http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>.
43 42
44=head1 HOW DO I USE THIS IN MY MODULES? 43=head1 HOW DO I USE THIS IN MY MODULES?
45 44
59perl's built-in C<flock>, it allows other threads (for example, those 58perl's built-in C<flock>, it allows other threads (for example, those
60provided by L<Coro>) to execute, instead of blocking the whole perl 59provided by L<Coro>) to execute, instead of blocking the whole perl
61interpreter. For the sake of this example, it requires a file descriptor 60interpreter. For the sake of this example, it requires a file descriptor
62instead of a handle. 61instead of a handle.
63 62
64 #include "perlmulticore.h" /* this header file */ 63 #include "perlmulticore.h" // this header file
65 64
66 // and in the XS portion 65 // and in the XS portion
67 int flock (int fd, int operation) 66 int flock (int fd, int operation)
68 CODE: 67 CODE:
69 perlinterp_release (); 68 perlinterp_release ();
119 if (res) 118 if (res)
120 { 119 {
121 // error, assume lock is held by another process and do it the slow way 120 // error, assume lock is held by another process and do it the slow way
122 perlinterp_release (); 121 perlinterp_release ();
123 res = fcntl (fd, F_SETLKW, &flock); 122 res = fcntl (fd, F_SETLKW, &flock);
124 perlinterp_release (); 123 perlinterp_acquire ();
125 } 124 }
126 125
127=head1 THE HARD AND FAST RULES 126=head1 THE HARD AND FAST RULES
128 127
129As with everything, there are a number of rules to follow. 128As with everything, there are a number of rules to follow.
199 pthread_mutex_lock (&my_mutex); 198 pthread_mutex_lock (&my_mutex);
200 do_your_non_thread_safe_thing (); 199 do_your_non_thread_safe_thing ();
201 pthread_mutex_unlock (&my_mutex); 200 pthread_mutex_unlock (&my_mutex);
202 perlinterp_acquire (); 201 perlinterp_acquire ();
203 202
204This isn't as trivial as it looks though, as you need to find out which
205threading system is in use (with L<Coro::Multicore>, it currently is
206always pthreads).
207
208=item I<Don't> get confused by having to release first. 203=item I<Don't> get confused by having to release first.
209 204
210In many real world scenarios, you acquire a resource, do something, then 205In many real world scenarios, you acquire a resource, do something, then
211release it again. Don't let this confuse you, with this, you already own 206release it again. Don't let this confuse you, with this, you already own
212the resource (the perl interpreter) so you have to I<release> first, and 207the resource (the perl interpreter) so you have to I<release> first, and
257first are two memory accesses and a predictable function call of an empty 252first are two memory accesses and a predictable function call of an empty
258function. 253function.
259 254
260Of course, the overhead is much higher when these functions actually 255Of course, the overhead is much higher when these functions actually
261implement anything useful, but you always get what you pay for. 256implement anything useful, but you always get what you pay for.
257
258With L<Coro::Multicore>, every release/acquire involves two pthread
259switches, two coro thread switches, a bunch of syscalls, and sometimes
260interacting with the event loop.
261
262A dedicated thread pool such as the one L<IO::AIO> uses could reduce
263these overheads, and would also reduce the dependencies (L<AnyEvent> is a
264smaller and more portable dependency than L<Coro>), but it would require a
265lot more work on the side of the module author wanting to support it than
266this solution.
262 267
263=item Low Code and Data Size Overhead 268=item Low Code and Data Size Overhead
264 269
265On a 64 bit system, F<perlmulticore.h> uses exactly C<8> octets (one 270On a 64 bit system, F<perlmulticore.h> uses exactly C<8> octets (one
266pointer) of your data segment, to store the C<perl_multicore_api> 271pointer) of your data segment, to store the C<perl_multicore_api>
295efficient when not needed, low code and data size overhead and broad 300efficient when not needed, low code and data size overhead and broad
296applicability. 301applicability.
297 302
298=back 303=back
299 304
305
306=head1 DISABLING PERL MULTICORE AT COMPILE TIME
307
308You can disable the complete perl multicore API by defining the
309symbol C<PERL_MULTICORE_DISABLE> to C<1> (e.g. by specifying
310F<-DPERL_MULTICORE_DISABLE> as compiler argument).
311
312This will leave no traces of the API in the compiled code, suitable
313"empty" C<perl_release> and C<perl_acquire> definitions will be provided.
314
315This could be added to perl's C<CPPFLAGS> when configuring perl on
316platforms that do not support threading at all for example.
317
318
300=head1 AUTHOR 319=head1 AUTHOR
301 320
302 Marc A. Lehmann <perlmulticore@schmorp.de> 321 Marc A. Lehmann <perlmulticore@schmorp.de>
322 http://perlmulticore.schmorp.de/
303 323
304=head1 LICENSE 324=head1 LICENSE
305 325
306The F<perlmulticore.h> is put into the public domain. Where this is legally 326The F<perlmulticore.h> header file is put into the public
327domain. Where this is legally not possible, or at your
307not possible, or at your option, it can be licensed under creativecommons 328option, it can be licensed under creativecommons CC0
308CC0 license: L<https://creativecommons.org/publicdomain/zero/1.0/>. 329license: L<https://creativecommons.org/publicdomain/zero/1.0/>.
309 330
310=cut 331=cut
311 332
312#endif 333*/
313 334
335#if PERL_MULTICORE_DISABLE
336
337#define perlinterp_release() do { } while (0)
338#define perlinterp_acquire() do { } while (0)
339
340#else
341
342/* this struct is shared between all modules, and currently */
343/* contain only the two function pointers for release/acquire */
314struct perl_multicore_api 344struct perl_multicore_api
315{ 345{
316 void (*pmapi_release)(void); 346 void (*pmapi_release)(void);
317 void (*pmapi_acquire)(void); 347 void (*pmapi_acquire)(void);
318}; 348};
325 = (struct perl_multicore_api *)&perl_multicore_api_init; 355 = (struct perl_multicore_api *)&perl_multicore_api_init;
326 356
327#define perlinterp_release() perl_multicore_api->pmapi_release () 357#define perlinterp_release() perl_multicore_api->pmapi_release ()
328#define perlinterp_acquire() perl_multicore_api->pmapi_acquire () 358#define perlinterp_acquire() perl_multicore_api->pmapi_acquire ()
329 359
360/* this is the release/acquire implementation used as fallback */
330static void 361static void
331perl_multicore_nop (void) 362perl_multicore_nop (void)
332{ 363{
333} 364}
334 365
366/* this is the initial implementation of "release" - it initialises */
367/* the api and then calls the real release function */
335static void 368static void
336perl_multicore_init (void) 369perl_multicore_init (void)
337{ 370{
338 dTHX; 371 dTHX;
339 372
357 /* call the real (or dummy) implementation now */ 390 /* call the real (or dummy) implementation now */
358 perlinterp_release (); 391 perlinterp_release ();
359} 392}
360 393
361#endif 394#endif
395
396#endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines