Commit | Line | Data |
adfe19db |
1 | ################################################################################ |
2 | ## |
a745474a |
3 | ## $Revision: 8 $ |
adfe19db |
4 | ## $Author: mhx $ |
a745474a |
5 | ## $Date: 2004/09/08 21:12:15 +0200 $ |
adfe19db |
6 | ## |
7 | ################################################################################ |
8 | ## |
9 | ## Version 3.x, Copyright (C) 2004, Marcus Holland-Moritz. |
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 | |
35 | #ifndef START_MY_CXT |
36 | |
37 | /* |
38 | * Boilerplate macros for initializing and accessing interpreter-local |
39 | * data from C. All statics in extensions should be reworked to use |
40 | * this, if you want to make the extension thread-safe. See ext/re/re.xs |
41 | * for an example of the use of these macros. |
42 | * |
43 | * Code that uses these macros is responsible for the following: |
44 | * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" |
45 | * 2. Declare a typedef named my_cxt_t that is a structure that contains |
46 | * all the data that needs to be interpreter-local. |
47 | * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. |
48 | * 4. Use the MY_CXT_INIT macro such that it is called exactly once |
49 | * (typically put in the BOOT: section). |
50 | * 5. Use the members of the my_cxt_t structure everywhere as |
51 | * MY_CXT.member. |
52 | * 6. Use the dMY_CXT macro (a declaration) in all the functions that |
53 | * access MY_CXT. |
54 | */ |
55 | |
56 | #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ |
57 | defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) |
58 | |
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 | |
a745474a |
90 | /* Clones the per-interpreter data. */ |
91 | #define MY_CXT_CLONE \ |
92 | dMY_CXT_SV; \ |
93 | my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ |
94 | Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ |
95 | sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) |
96 | |
adfe19db |
97 | /* This macro must be used to access members of the my_cxt_t structure. |
98 | * e.g. MYCXT.some_data */ |
99 | #define MY_CXT (*my_cxtp) |
100 | |
101 | /* Judicious use of these macros can reduce the number of times dMY_CXT |
102 | * is used. Use is similar to pTHX, aTHX etc. */ |
103 | #define pMY_CXT my_cxt_t *my_cxtp |
104 | #define pMY_CXT_ pMY_CXT, |
105 | #define _pMY_CXT ,pMY_CXT |
106 | #define aMY_CXT my_cxtp |
107 | #define aMY_CXT_ aMY_CXT, |
108 | #define _aMY_CXT ,aMY_CXT |
109 | |
110 | #else /* single interpreter */ |
111 | |
112 | #define START_MY_CXT static my_cxt_t my_cxt; |
113 | #define dMY_CXT_SV dNOOP |
114 | #define dMY_CXT dNOOP |
115 | #define MY_CXT_INIT NOOP |
a745474a |
116 | #define MY_CXT_CLONE NOOP |
adfe19db |
117 | #define MY_CXT my_cxt |
118 | |
119 | #define pMY_CXT void |
120 | #define pMY_CXT_ |
121 | #define _pMY_CXT |
122 | #define aMY_CXT |
123 | #define aMY_CXT_ |
124 | #define _aMY_CXT |
125 | |
126 | #endif |
127 | |
128 | #endif /* START_MY_CXT */ |
129 | |
130 | =xsmisc |
131 | |
132 | #define MY_CXT_KEY "Devel::PPPort::_guts" XS_VERSION |
133 | |
134 | typedef struct { |
135 | /* Put Global Data in here */ |
136 | int dummy; |
137 | } my_cxt_t; |
138 | |
139 | START_MY_CXT |
140 | |
141 | =xsboot |
142 | |
143 | { |
144 | MY_CXT_INIT; |
145 | /* If any of the fields in the my_cxt_t struct need |
146 | * to be initialised, do it here. |
147 | */ |
148 | MY_CXT.dummy = 42; |
149 | } |
150 | |
151 | =xsubs |
152 | |
153 | int |
154 | MY_CXT_1() |
155 | CODE: |
156 | dMY_CXT; |
157 | RETVAL = MY_CXT.dummy == 42; |
158 | ++MY_CXT.dummy; |
159 | OUTPUT: |
160 | RETVAL |
161 | |
162 | int |
163 | MY_CXT_2() |
164 | CODE: |
165 | dMY_CXT; |
166 | RETVAL = MY_CXT.dummy == 43; |
167 | OUTPUT: |
168 | RETVAL |
169 | |
170 | =tests plan => 2 |
171 | |
172 | ok(&Devel::PPPort::MY_CXT_1()); |
173 | ok(&Devel::PPPort::MY_CXT_2()); |
174 | |