… | |
… | |
9 | |
9 | |
10 | /* |
10 | /* |
11 | |
11 | |
12 | =head1 NAME |
12 | =head1 NAME |
13 | |
13 | |
14 | perlmulticore.h - the Perl Multicore Specification |
14 | perlmulticore.h - the Perl Multicore Specification and Implementation |
15 | |
15 | |
16 | =head1 SYNOPSIS |
16 | =head1 SYNOPSIS |
17 | |
17 | |
18 | #include "perlmultiore.h" |
18 | #include "perlmultiore.h" |
19 | |
19 | |
… | |
… | |
34 | applicability. |
34 | applicability. |
35 | |
35 | |
36 | The newest version of this document can be found at |
36 | The newest version of this document can be found at |
37 | L<http://pod.tst.eu/http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. |
37 | L<http://pod.tst.eu/http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. |
38 | |
38 | |
39 | The nwest version of the header fgile itself, which |
39 | The newest version of the header file itself, which |
40 | includes this documentation, can be downloaded from |
40 | includes this documentation, can be downloaded from |
41 | L<http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. |
41 | L<http://cvs.schmorp.de/Coro-Multicore/perlmulticore.h>. |
42 | |
42 | |
43 | =head1 HOW DO I USE THIS IN MY MODULES? |
43 | =head1 HOW DO I USE THIS IN MY MODULES? |
44 | |
44 | |
… | |
… | |
118 | if (res) |
118 | if (res) |
119 | { |
119 | { |
120 | // 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 |
121 | perlinterp_release (); |
121 | perlinterp_release (); |
122 | res = fcntl (fd, F_SETLKW, &flock); |
122 | res = fcntl (fd, F_SETLKW, &flock); |
123 | perlinterp_release (); |
123 | perlinterp_acquire (); |
124 | } |
124 | } |
125 | |
125 | |
126 | =head1 THE HARD AND FAST RULES |
126 | =head1 THE HARD AND FAST RULES |
127 | |
127 | |
128 | As with everything, there are a number of rules to follow. |
128 | As with everything, there are a number of rules to follow. |
… | |
… | |
198 | pthread_mutex_lock (&my_mutex); |
198 | pthread_mutex_lock (&my_mutex); |
199 | do_your_non_thread_safe_thing (); |
199 | do_your_non_thread_safe_thing (); |
200 | pthread_mutex_unlock (&my_mutex); |
200 | pthread_mutex_unlock (&my_mutex); |
201 | perlinterp_acquire (); |
201 | perlinterp_acquire (); |
202 | |
202 | |
203 | This isn't as trivial as it looks though, as you need to find out which |
|
|
204 | threading system is in use (with L<Coro::Multicore>, it currently is |
|
|
205 | always pthreads). |
|
|
206 | |
|
|
207 | =item I<Don't> get confused by having to release first. |
203 | =item I<Don't> get confused by having to release first. |
208 | |
204 | |
209 | In many real world scenarios, you acquire a resource, do something, then |
205 | In many real world scenarios, you acquire a resource, do something, then |
210 | release it again. Don't let this confuse you, with this, you already own |
206 | release it again. Don't let this confuse you, with this, you already own |
211 | the resource (the perl interpreter) so you have to I<release> first, and |
207 | the resource (the perl interpreter) so you have to I<release> first, and |
… | |
… | |
307 | =back |
303 | =back |
308 | |
304 | |
309 | =head1 AUTHOR |
305 | =head1 AUTHOR |
310 | |
306 | |
311 | Marc A. Lehmann <perlmulticore@schmorp.de> |
307 | Marc A. Lehmann <perlmulticore@schmorp.de> |
|
|
308 | http://perlmulticore.schmorp.de/ |
312 | |
309 | |
313 | =head1 LICENSE |
310 | =head1 LICENSE |
314 | |
311 | |
315 | The F<perlmulticore.h> is put into the public domain. Where this is legally |
312 | The F<perlmulticore.h> header file is put into the public |
|
|
313 | domain. Where this is legally not possible, or at your |
316 | not possible, or at your option, it can be licensed under creativecommons |
314 | option, it can be licensed under creativecommons CC0 |
317 | CC0 license: L<https://creativecommons.org/publicdomain/zero/1.0/>. |
315 | license: L<https://creativecommons.org/publicdomain/zero/1.0/>. |
318 | |
316 | |
319 | =cut |
317 | =cut |
|
|
318 | |
320 | */ |
319 | */ |
321 | |
320 | |
|
|
321 | /* this struct is shared between all modules, and currently */ |
|
|
322 | /* contain only the two function pointers for release/acquire */ |
322 | struct perl_multicore_api |
323 | struct perl_multicore_api |
323 | { |
324 | { |
324 | void (*pmapi_release)(void); |
325 | void (*pmapi_release)(void); |
325 | void (*pmapi_acquire)(void); |
326 | void (*pmapi_acquire)(void); |
326 | }; |
327 | }; |
… | |
… | |
333 | = (struct perl_multicore_api *)&perl_multicore_api_init; |
334 | = (struct perl_multicore_api *)&perl_multicore_api_init; |
334 | |
335 | |
335 | #define perlinterp_release() perl_multicore_api->pmapi_release () |
336 | #define perlinterp_release() perl_multicore_api->pmapi_release () |
336 | #define perlinterp_acquire() perl_multicore_api->pmapi_acquire () |
337 | #define perlinterp_acquire() perl_multicore_api->pmapi_acquire () |
337 | |
338 | |
|
|
339 | /* this is the release/acquire implementation used as fallback */ |
338 | static void |
340 | static void |
339 | perl_multicore_nop (void) |
341 | perl_multicore_nop (void) |
340 | { |
342 | { |
341 | } |
343 | } |
342 | |
344 | |
|
|
345 | /* this is the initial implementation of "release" - it initialises */ |
|
|
346 | /* the api and then calls the real release function */ |
343 | static void |
347 | static void |
344 | perl_multicore_init (void) |
348 | perl_multicore_init (void) |
345 | { |
349 | { |
346 | dTHX; |
350 | dTHX; |
347 | |
351 | |