ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Multicore/perlmulticore.h
Revision: 1.11
Committed: Fri Jul 3 02:35:48 2015 UTC (8 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.10: +32 -223 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * Author: Marc A. Lehmann <xsthreadpool@schmorp.de>
3     * License: public domain, or where this is not possible/at your option,
4     * CC0 (https://creativecommons.org/publicdomain/zero/1.0/)
5 root 1.11 *
6     * Full documentation can be found at http://perlmulticore.schmorp.de/
7     * The newest version of this header can be downloaded from
8     * http://perlmulticore.schmorp.de/perlmulticore.h
9 root 1.1 */
10    
11     #ifndef PERL_MULTICORE_H
12     #define PERL_MULTICORE_H
13    
14 root 1.3 /*
15 root 1.5
16 root 1.1 =head1 NAME
17    
18 root 1.11 perlmulticore.h - implements the Perl Multicore Specification
19 root 1.1
20     =head1 SYNOPSIS
21    
22     #include "perlmultiore.h"
23    
24     // in your XS function:
25    
26     perlinterp_release ();
27     do_the_C_thing ();
28     perlinterp_acquire ();
29    
30     =head1 DESCRIPTION
31    
32 root 1.11 This documentation is the abridged version of the full documention at
33     L<http://perlmulticore.schmorp.de/>. It's recommended to go there instead
34     of reading this document.
35    
36     This header file implements a very low overhead (both in code and runtime)
37     mechanism for XS modules to allow re-use of the perl interpreter for other
38     threads while doing some lengthy operation, such as cryptography, SQL
39     queries, disk I/O and so on.
40    
41     The newest version of the header file itself, can be downloaded from
42     L<http://perlmulticore.schmorp.de/perlmulticore.h>.
43 root 1.1
44     =head1 HOW DO I USE THIS IN MY MODULES?
45    
46 root 1.2 The usage is very simple - you include this header file in your XS module. Then, before you
47 root 1.1 do your lengthy operation, you release the perl interpreter:
48    
49     perlinterp_release ();
50    
51     And when you are done with your computation, you acquire it again:
52    
53     perlinterp_acquire ();
54    
55     And that's it. This doesn't load any modules and consists of only a few
56 root 1.2 machine instructions when no module to take advantage of it is loaded.
57 root 1.1
58 root 1.11 More documentation and examples can be found at the perl multicore site at
59     L<http://perlmulticore.schmorp.de>.
60 root 1.1
61     =head1 THE HARD AND FAST RULES
62    
63     As with everything, there are a number of rules to follow.
64    
65     =over 4
66    
67     =item I<Never> touch any perl data structures after calling C<perlinterp_release>.
68    
69 root 1.11 Anything perl is completely off-limits after C<perlinterp_release>, until
70     you call C<perlinterp_acquire>, after which you can access perl stuff
71     again.
72 root 1.1
73     That includes anything in the perl interpreter that you didn't prove to be
74     safe, and didn't prove to be safe in older and future versions of perl:
75     global variables, local perl scalars, even if you are sure nobody accesses
76 root 1.11 them and you only try to "read" their value.
77 root 1.1
78     =item I<Always> call C<perlinterp_release> and C<perlinterp_acquire> in pairs.
79    
80     For each C<perlinterp_release> call there must be a C<perlinterp_acquire>
81     call. They don't have to be in the same function, and you can have
82     multiple calls to them, as long as every C<perlinterp_release> call is
83 root 1.11 followed by exactly one C<perlinterp_acquire> call at runtime.
84 root 1.1
85     =item I<Never> nest calls to C<perlinterp_release> and C<perlinterp_acquire>.
86    
87     That simply means that after calling C<perlinterp_release>, you must
88     call C<perlinterp_acquire> before calling C<perlinterp_release>
89     again. Likewise, after C<perlinterp_acquire>, you can call
90     C<perlinterp_release> but not another C<perlinterp_acquire>.
91    
92     =item I<Always> call C<perlinterp_release> first.
93    
94 root 1.11 You I<must not> call C<perlinterp_acquire> without having called
95     C<perlinterp_release> before.
96 root 1.1
97     =item I<Never> underestimate threads.
98    
99     While it's easy to add parallel execution ability to your XS module, it
100     doesn't mean it is safe. After you release the perl interpreter, it's
101     perfectly possible that it will call your XS function in another thread,
102     even while your original function still executes. In other words: your C
103     code must be thread safe, and if you use any library, that library must be
104     thread-safe, too.
105    
106     Always assume that the code between C<perlinterp_release> and
107     C<perlinterp_acquire> is executed in parallel on multiple CPUs at the same
108 root 1.11 time.
109 root 1.1
110     =back
111    
112 root 1.8
113     =head1 DISABLING PERL MULTICORE AT COMPILE TIME
114    
115     You can disable the complete perl multicore API by defining the
116     symbol C<PERL_MULTICORE_DISABLE> to C<1> (e.g. by specifying
117     F<-DPERL_MULTICORE_DISABLE> as compiler argument).
118    
119     This could be added to perl's C<CPPFLAGS> when configuring perl on
120     platforms that do not support threading at all for example.
121    
122    
123 root 1.1 =head1 AUTHOR
124    
125     Marc A. Lehmann <perlmulticore@schmorp.de>
126 root 1.6 http://perlmulticore.schmorp.de/
127 root 1.1
128     =head1 LICENSE
129    
130 root 1.6 The F<perlmulticore.h> header file is put into the public
131     domain. Where this is legally not possible, or at your
132     option, it can be licensed under creativecommons CC0
133     license: L<https://creativecommons.org/publicdomain/zero/1.0/>.
134 root 1.1
135     =cut
136 root 1.6
137 root 1.3 */
138 root 1.1
139 root 1.9 #define PERL_MULTICORE_MAJOR 1 /* bumped on incompatible changes */
140     #define PERL_MULTICORE_MINOR 0 /* bumped on every change */
141    
142 root 1.7 #if PERL_MULTICORE_DISABLE
143    
144     #define perlinterp_release() do { } while (0)
145     #define perlinterp_acquire() do { } while (0)
146    
147     #else
148    
149 root 1.11 START_EXTERN_C
150    
151 root 1.6 /* this struct is shared between all modules, and currently */
152     /* contain only the two function pointers for release/acquire */
153 root 1.1 struct perl_multicore_api
154     {
155     void (*pmapi_release)(void);
156     void (*pmapi_acquire)(void);
157     };
158    
159     static void perl_multicore_init (void);
160    
161 root 1.11 static const struct perl_multicore_api perl_multicore_api_init
162     = { perl_multicore_init, 0 };
163 root 1.1
164     static struct perl_multicore_api *perl_multicore_api
165     = (struct perl_multicore_api *)&perl_multicore_api_init;
166    
167     #define perlinterp_release() perl_multicore_api->pmapi_release ()
168     #define perlinterp_acquire() perl_multicore_api->pmapi_acquire ()
169    
170 root 1.6 /* this is the release/acquire implementation used as fallback */
171 root 1.1 static void
172     perl_multicore_nop (void)
173     {
174     }
175    
176 root 1.6 /* this is the initial implementation of "release" - it initialises */
177     /* the api and then calls the real release function */
178 root 1.1 static void
179     perl_multicore_init (void)
180     {
181     dTHX;
182    
183     /* check for existing API struct in PL_modglobal */
184     SV **api_svp = hv_fetch (PL_modglobal, "perl_multicore_api", sizeof ("perl_multicore_api") - 1, 1);
185    
186     if (SvPOKp (*api_svp))
187     perl_multicore_api = (struct perl_multicore_api *)SvPVX (*api_svp); /* we have one, use the existing one */
188     else
189     {
190     /* create a new one with a dummy nop implementation */
191     SV *api_sv = NEWSV (0, sizeof (*perl_multicore_api));
192     SvCUR_set (api_sv, sizeof (*perl_multicore_api));
193     SvPOK_only (api_sv);
194     perl_multicore_api = (struct perl_multicore_api *)SvPVX (api_sv);
195     perl_multicore_api->pmapi_release =
196     perl_multicore_api->pmapi_acquire = perl_multicore_nop;
197     *api_svp = api_sv;
198     }
199    
200     /* call the real (or dummy) implementation now */
201     perlinterp_release ();
202     }
203    
204 root 1.11 END_EXTERN_C
205    
206 root 1.1 #endif
207 root 1.7
208     #endif