This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to Devel::PPPort 3.00_03.
[perl5.git] / ext / Devel / PPPort / parts / inc / MY_CXT
CommitLineData
adfe19db
MHM
1################################################################################
2##
3## $Revision: 7 $
4## $Author: mhx $
5## $Date: 2004/08/13 12:45:55 +0200 $
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
20START_MY_CXT
21dMY_CXT_SV
22dMY_CXT
23MY_CXT_INIT
24MY_CXT
25pMY_CXT
26pMY_CXT_
27_pMY_CXT
28aMY_CXT
29aMY_CXT_
30_aMY_CXT
31
32=implementation
33
34#ifndef START_MY_CXT
35
36/*
37 * Boilerplate macros for initializing and accessing interpreter-local
38 * data from C. All statics in extensions should be reworked to use
39 * this, if you want to make the extension thread-safe. See ext/re/re.xs
40 * for an example of the use of these macros.
41 *
42 * Code that uses these macros is responsible for the following:
43 * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
44 * 2. Declare a typedef named my_cxt_t that is a structure that contains
45 * all the data that needs to be interpreter-local.
46 * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
47 * 4. Use the MY_CXT_INIT macro such that it is called exactly once
48 * (typically put in the BOOT: section).
49 * 5. Use the members of the my_cxt_t structure everywhere as
50 * MY_CXT.member.
51 * 6. Use the dMY_CXT macro (a declaration) in all the functions that
52 * access MY_CXT.
53 */
54
55#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
56 defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
57
58/* This must appear in all extensions that define a my_cxt_t structure,
59 * right after the definition (i.e. at file scope). The non-threads
60 * case below uses it to declare the data as static. */
61#define START_MY_CXT
62
63#if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
64/* Fetches the SV that keeps the per-interpreter data. */
65#define dMY_CXT_SV \
66 SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE)
67#else /* >= perl5.004_68 */
68#define dMY_CXT_SV \
69 SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
70 sizeof(MY_CXT_KEY)-1, TRUE)
71#endif /* < perl5.004_68 */
72
73/* This declaration should be used within all functions that use the
74 * interpreter-local data. */
75#define dMY_CXT \
76 dMY_CXT_SV; \
77 my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
78
79/* Creates and zeroes the per-interpreter data.
80 * (We allocate my_cxtp in a Perl SV so that it will be released when
81 * the interpreter goes away.) */
82#define MY_CXT_INIT \
83 dMY_CXT_SV; \
84 /* newSV() allocates one more than needed */ \
85 my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
86 Zero(my_cxtp, 1, my_cxt_t); \
87 sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
88
89/* This macro must be used to access members of the my_cxt_t structure.
90 * e.g. MYCXT.some_data */
91#define MY_CXT (*my_cxtp)
92
93/* Judicious use of these macros can reduce the number of times dMY_CXT
94 * is used. Use is similar to pTHX, aTHX etc. */
95#define pMY_CXT my_cxt_t *my_cxtp
96#define pMY_CXT_ pMY_CXT,
97#define _pMY_CXT ,pMY_CXT
98#define aMY_CXT my_cxtp
99#define aMY_CXT_ aMY_CXT,
100#define _aMY_CXT ,aMY_CXT
101
102#else /* single interpreter */
103
104#define START_MY_CXT static my_cxt_t my_cxt;
105#define dMY_CXT_SV dNOOP
106#define dMY_CXT dNOOP
107#define MY_CXT_INIT NOOP
108#define MY_CXT my_cxt
109
110#define pMY_CXT void
111#define pMY_CXT_
112#define _pMY_CXT
113#define aMY_CXT
114#define aMY_CXT_
115#define _aMY_CXT
116
117#endif
118
119#endif /* START_MY_CXT */
120
121=xsmisc
122
123#define MY_CXT_KEY "Devel::PPPort::_guts" XS_VERSION
124
125typedef struct {
126 /* Put Global Data in here */
127 int dummy;
128} my_cxt_t;
129
130START_MY_CXT
131
132=xsboot
133
134{
135 MY_CXT_INIT;
136 /* If any of the fields in the my_cxt_t struct need
137 * to be initialised, do it here.
138 */
139 MY_CXT.dummy = 42;
140}
141
142=xsubs
143
144int
145MY_CXT_1()
146 CODE:
147 dMY_CXT;
148 RETVAL = MY_CXT.dummy == 42;
149 ++MY_CXT.dummy;
150 OUTPUT:
151 RETVAL
152
153int
154MY_CXT_2()
155 CODE:
156 dMY_CXT;
157 RETVAL = MY_CXT.dummy == 43;
158 OUTPUT:
159 RETVAL
160
161=tests plan => 2
162
163ok(&Devel::PPPort::MY_CXT_1());
164ok(&Devel::PPPort::MY_CXT_2());
165