Commit | Line | Data |
adfe19db |
1 | ################################################################################ |
2 | ## |
4a582685 |
3 | ## $Revision: 11 $ |
adfe19db |
4 | ## $Author: mhx $ |
4a582685 |
5 | ## $Date: 2005/03/10 18:08:41 +0100 $ |
adfe19db |
6 | ## |
7 | ################################################################################ |
8 | ## |
9132e1a3 |
9 | ## Version 3.x, Copyright (C) 2004-2005, Marcus Holland-Moritz. |
adfe19db |
10 | ## Version 2.x, Copyright (C) 2001, Paul Marquess. |
11 | ## Version 1.x, Copyright (C) 1999, Kenneth Albanowski. |
12 | ## |
13 | ## This program is free software; you can redistribute it and/or |
14 | ## modify it under the same terms as Perl itself. |
15 | ## |
16 | ################################################################################ |
17 | |
18 | =provides |
19 | |
20 | START_MY_CXT |
21 | dMY_CXT_SV |
22 | dMY_CXT |
23 | MY_CXT_INIT |
a745474a |
24 | MY_CXT_CLONE |
adfe19db |
25 | MY_CXT |
26 | pMY_CXT |
27 | pMY_CXT_ |
28 | _pMY_CXT |
29 | aMY_CXT |
30 | aMY_CXT_ |
31 | _aMY_CXT |
32 | |
33 | =implementation |
34 | |
adfe19db |
35 | /* |
36 | * Boilerplate macros for initializing and accessing interpreter-local |
37 | * data from C. All statics in extensions should be reworked to use |
38 | * this, if you want to make the extension thread-safe. See ext/re/re.xs |
39 | * for an example of the use of these macros. |
40 | * |
41 | * Code that uses these macros is responsible for the following: |
42 | * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" |
43 | * 2. Declare a typedef named my_cxt_t that is a structure that contains |
44 | * all the data that needs to be interpreter-local. |
45 | * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. |
46 | * 4. Use the MY_CXT_INIT macro such that it is called exactly once |
47 | * (typically put in the BOOT: section). |
48 | * 5. Use the members of the my_cxt_t structure everywhere as |
49 | * MY_CXT.member. |
50 | * 6. Use the dMY_CXT macro (a declaration) in all the functions that |
51 | * access MY_CXT. |
52 | */ |
53 | |
54 | #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ |
55 | defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) |
56 | |
e4c28a9f |
57 | #ifndef START_MY_CXT |
58 | |
adfe19db |
59 | /* This must appear in all extensions that define a my_cxt_t structure, |
60 | * right after the definition (i.e. at file scope). The non-threads |
61 | * case below uses it to declare the data as static. */ |
62 | #define START_MY_CXT |
63 | |
64 | #if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 )) |
65 | /* Fetches the SV that keeps the per-interpreter data. */ |
66 | #define dMY_CXT_SV \ |
67 | SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE) |
68 | #else /* >= perl5.004_68 */ |
69 | #define dMY_CXT_SV \ |
70 | SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ |
71 | sizeof(MY_CXT_KEY)-1, TRUE) |
72 | #endif /* < perl5.004_68 */ |
73 | |
74 | /* This declaration should be used within all functions that use the |
75 | * interpreter-local data. */ |
76 | #define dMY_CXT \ |
77 | dMY_CXT_SV; \ |
78 | my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) |
79 | |
80 | /* Creates and zeroes the per-interpreter data. |
81 | * (We allocate my_cxtp in a Perl SV so that it will be released when |
82 | * the interpreter goes away.) */ |
83 | #define MY_CXT_INIT \ |
84 | dMY_CXT_SV; \ |
85 | /* newSV() allocates one more than needed */ \ |
86 | my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ |
87 | Zero(my_cxtp, 1, my_cxt_t); \ |
88 | sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) |
89 | |
90 | /* This macro must be used to access members of the my_cxt_t structure. |
91 | * e.g. MYCXT.some_data */ |
92 | #define MY_CXT (*my_cxtp) |
93 | |
94 | /* Judicious use of these macros can reduce the number of times dMY_CXT |
95 | * is used. Use is similar to pTHX, aTHX etc. */ |
96 | #define pMY_CXT my_cxt_t *my_cxtp |
97 | #define pMY_CXT_ pMY_CXT, |
98 | #define _pMY_CXT ,pMY_CXT |
99 | #define aMY_CXT my_cxtp |
100 | #define aMY_CXT_ aMY_CXT, |
101 | #define _aMY_CXT ,aMY_CXT |
102 | |
e4c28a9f |
103 | #endif /* START_MY_CXT */ |
104 | |
105 | #ifndef MY_CXT_CLONE |
106 | /* Clones the per-interpreter data. */ |
107 | #define MY_CXT_CLONE \ |
108 | dMY_CXT_SV; \ |
109 | my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ |
110 | Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ |
111 | sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) |
112 | #endif |
113 | |
adfe19db |
114 | #else /* single interpreter */ |
115 | |
e4c28a9f |
116 | #ifndef START_MY_CXT |
117 | |
adfe19db |
118 | #define START_MY_CXT static my_cxt_t my_cxt; |
119 | #define dMY_CXT_SV dNOOP |
120 | #define dMY_CXT dNOOP |
121 | #define MY_CXT_INIT NOOP |
122 | #define MY_CXT my_cxt |
123 | |
124 | #define pMY_CXT void |
125 | #define pMY_CXT_ |
126 | #define _pMY_CXT |
127 | #define aMY_CXT |
128 | #define aMY_CXT_ |
129 | #define _aMY_CXT |
130 | |
adfe19db |
131 | #endif /* START_MY_CXT */ |
132 | |
e4c28a9f |
133 | #ifndef MY_CXT_CLONE |
134 | #define MY_CXT_CLONE NOOP |
135 | #endif |
136 | |
137 | #endif |
138 | |
adfe19db |
139 | =xsmisc |
140 | |
141 | #define MY_CXT_KEY "Devel::PPPort::_guts" XS_VERSION |
4a582685 |
142 | |
adfe19db |
143 | typedef struct { |
144 | /* Put Global Data in here */ |
4a582685 |
145 | int dummy; |
adfe19db |
146 | } my_cxt_t; |
4a582685 |
147 | |
148 | START_MY_CXT |
adfe19db |
149 | |
150 | =xsboot |
151 | |
152 | { |
153 | MY_CXT_INIT; |
154 | /* If any of the fields in the my_cxt_t struct need |
155 | * to be initialised, do it here. |
156 | */ |
157 | MY_CXT.dummy = 42; |
158 | } |
159 | |
160 | =xsubs |
161 | |
162 | int |
163 | MY_CXT_1() |
164 | CODE: |
165 | dMY_CXT; |
166 | RETVAL = MY_CXT.dummy == 42; |
167 | ++MY_CXT.dummy; |
168 | OUTPUT: |
169 | RETVAL |
170 | |
171 | int |
172 | MY_CXT_2() |
173 | CODE: |
174 | dMY_CXT; |
175 | RETVAL = MY_CXT.dummy == 43; |
176 | OUTPUT: |
177 | RETVAL |
178 | |
e4c28a9f |
179 | int |
180 | MY_CXT_CLONE() |
181 | CODE: |
182 | MY_CXT_CLONE; |
183 | RETVAL = 42; |
184 | OUTPUT: |
185 | RETVAL |
186 | |
187 | =tests plan => 3 |
adfe19db |
188 | |
189 | ok(&Devel::PPPort::MY_CXT_1()); |
190 | ok(&Devel::PPPort::MY_CXT_2()); |
e4c28a9f |
191 | ok(&Devel::PPPort::MY_CXT_CLONE()); |
adfe19db |
192 | |