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