This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Rename ext/Devel/PPPort to ext/Devel-PPPort
[perl5.git] / ext / Devel-PPPort / parts / inc / MY_CXT
1 ################################################################################
2 ##
3 ##  $Revision: 16 $
4 ##  $Author: mhx $
5 ##  $Date: 2009/01/18 14:10:55 +0100 $
6 ##
7 ################################################################################
8 ##
9 ##  Version 3.x, Copyright (C) 2004-2009, 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
24 MY_CXT_CLONE
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 /*
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
57 #ifndef START_MY_CXT
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 { VERSION < 5.004_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
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
114 #else /* single interpreter */
115
116 #ifndef START_MY_CXT
117
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
131 #endif /* START_MY_CXT */
132
133 #ifndef MY_CXT_CLONE
134 #define MY_CXT_CLONE    NOOP
135 #endif
136
137 #endif
138
139 =xsmisc
140
141 #define MY_CXT_KEY "Devel::PPPort::_guts" XS_VERSION
142
143 typedef struct {
144   /* Put Global Data in here */
145   int dummy;
146 } my_cxt_t;
147
148 START_MY_CXT
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
179 int
180 MY_CXT_CLONE()
181         CODE:
182                 MY_CXT_CLONE;
183                 RETVAL = 42;
184         OUTPUT:
185                 RETVAL
186
187 =tests plan => 3
188
189 ok(&Devel::PPPort::MY_CXT_1());
190 ok(&Devel::PPPort::MY_CXT_2());
191 ok(&Devel::PPPort::MY_CXT_CLONE());
192