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