|
Packit |
7d6a7d |
################################################################################
|
|
Packit |
7d6a7d |
##
|
|
Packit |
7d6a7d |
## Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
|
|
Packit |
7d6a7d |
## Version 2.x, Copyright (C) 2001, Paul Marquess.
|
|
Packit |
7d6a7d |
## Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
|
|
Packit |
7d6a7d |
##
|
|
Packit |
7d6a7d |
## This program is free software; you can redistribute it and/or
|
|
Packit |
7d6a7d |
## modify it under the same terms as Perl itself.
|
|
Packit |
7d6a7d |
##
|
|
Packit |
7d6a7d |
################################################################################
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=provides
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
START_MY_CXT
|
|
Packit |
7d6a7d |
dMY_CXT_SV
|
|
Packit |
7d6a7d |
dMY_CXT
|
|
Packit |
7d6a7d |
MY_CXT_INIT
|
|
Packit |
7d6a7d |
MY_CXT_CLONE
|
|
Packit |
7d6a7d |
MY_CXT
|
|
Packit |
7d6a7d |
pMY_CXT
|
|
Packit |
7d6a7d |
pMY_CXT_
|
|
Packit |
7d6a7d |
_pMY_CXT
|
|
Packit |
7d6a7d |
aMY_CXT
|
|
Packit |
7d6a7d |
aMY_CXT_
|
|
Packit |
7d6a7d |
_aMY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=implementation
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/*
|
|
Packit |
7d6a7d |
* Boilerplate macros for initializing and accessing interpreter-local
|
|
Packit |
7d6a7d |
* data from C. All statics in extensions should be reworked to use
|
|
Packit |
7d6a7d |
* this, if you want to make the extension thread-safe. See ext/re/re.xs
|
|
Packit |
7d6a7d |
* for an example of the use of these macros.
|
|
Packit |
7d6a7d |
*
|
|
Packit |
7d6a7d |
* Code that uses these macros is responsible for the following:
|
|
Packit |
7d6a7d |
* 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
|
|
Packit |
7d6a7d |
* 2. Declare a typedef named my_cxt_t that is a structure that contains
|
|
Packit |
7d6a7d |
* all the data that needs to be interpreter-local.
|
|
Packit |
7d6a7d |
* 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
|
|
Packit |
7d6a7d |
* 4. Use the MY_CXT_INIT macro such that it is called exactly once
|
|
Packit |
7d6a7d |
* (typically put in the BOOT: section).
|
|
Packit |
7d6a7d |
* 5. Use the members of the my_cxt_t structure everywhere as
|
|
Packit |
7d6a7d |
* MY_CXT.member.
|
|
Packit |
7d6a7d |
* 6. Use the dMY_CXT macro (a declaration) in all the functions that
|
|
Packit |
7d6a7d |
* access MY_CXT.
|
|
Packit |
7d6a7d |
*/
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
|
|
Packit |
7d6a7d |
defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifndef START_MY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* This must appear in all extensions that define a my_cxt_t structure,
|
|
Packit |
7d6a7d |
* right after the definition (i.e. at file scope). The non-threads
|
|
Packit |
7d6a7d |
* case below uses it to declare the data as static. */
|
|
Packit |
7d6a7d |
#define START_MY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#if { VERSION < 5.004_68 }
|
|
Packit |
7d6a7d |
/* Fetches the SV that keeps the per-interpreter data. */
|
|
Packit |
7d6a7d |
#define dMY_CXT_SV \
|
|
Packit |
7d6a7d |
SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE)
|
|
Packit |
7d6a7d |
#else /* >= perl5.004_68 */
|
|
Packit |
7d6a7d |
#define dMY_CXT_SV \
|
|
Packit |
7d6a7d |
SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
|
|
Packit |
7d6a7d |
sizeof(MY_CXT_KEY)-1, TRUE)
|
|
Packit |
7d6a7d |
#endif /* < perl5.004_68 */
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* This declaration should be used within all functions that use the
|
|
Packit |
7d6a7d |
* interpreter-local data. */
|
|
Packit |
7d6a7d |
#define dMY_CXT \
|
|
Packit |
7d6a7d |
dMY_CXT_SV; \
|
|
Packit |
7d6a7d |
my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* Creates and zeroes the per-interpreter data.
|
|
Packit |
7d6a7d |
* (We allocate my_cxtp in a Perl SV so that it will be released when
|
|
Packit |
7d6a7d |
* the interpreter goes away.) */
|
|
Packit |
7d6a7d |
#define MY_CXT_INIT \
|
|
Packit |
7d6a7d |
dMY_CXT_SV; \
|
|
Packit |
7d6a7d |
/* newSV() allocates one more than needed */ \
|
|
Packit |
7d6a7d |
my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
|
|
Packit |
7d6a7d |
Zero(my_cxtp, 1, my_cxt_t); \
|
|
Packit |
7d6a7d |
sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* This macro must be used to access members of the my_cxt_t structure.
|
|
Packit |
7d6a7d |
* e.g. MYCXT.some_data */
|
|
Packit |
7d6a7d |
#define MY_CXT (*my_cxtp)
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
/* Judicious use of these macros can reduce the number of times dMY_CXT
|
|
Packit |
7d6a7d |
* is used. Use is similar to pTHX, aTHX etc. */
|
|
Packit |
7d6a7d |
#define pMY_CXT my_cxt_t *my_cxtp
|
|
Packit |
7d6a7d |
#define pMY_CXT_ pMY_CXT,
|
|
Packit |
7d6a7d |
#define _pMY_CXT ,pMY_CXT
|
|
Packit |
7d6a7d |
#define aMY_CXT my_cxtp
|
|
Packit |
7d6a7d |
#define aMY_CXT_ aMY_CXT,
|
|
Packit |
7d6a7d |
#define _aMY_CXT ,aMY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#endif /* START_MY_CXT */
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifndef MY_CXT_CLONE
|
|
Packit |
7d6a7d |
/* Clones the per-interpreter data. */
|
|
Packit |
7d6a7d |
#define MY_CXT_CLONE \
|
|
Packit |
7d6a7d |
dMY_CXT_SV; \
|
|
Packit |
7d6a7d |
my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
|
|
Packit |
7d6a7d |
Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\
|
|
Packit |
7d6a7d |
sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#else /* single interpreter */
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifndef START_MY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#define START_MY_CXT static my_cxt_t my_cxt;
|
|
Packit |
7d6a7d |
#define dMY_CXT_SV dNOOP
|
|
Packit |
7d6a7d |
#define dMY_CXT dNOOP
|
|
Packit |
7d6a7d |
#define MY_CXT_INIT NOOP
|
|
Packit |
7d6a7d |
#define MY_CXT my_cxt
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#define pMY_CXT void
|
|
Packit |
7d6a7d |
#define pMY_CXT_
|
|
Packit |
7d6a7d |
#define _pMY_CXT
|
|
Packit |
7d6a7d |
#define aMY_CXT
|
|
Packit |
7d6a7d |
#define aMY_CXT_
|
|
Packit |
7d6a7d |
#define _aMY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#endif /* START_MY_CXT */
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#ifndef MY_CXT_CLONE
|
|
Packit |
7d6a7d |
#define MY_CXT_CLONE NOOP
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#endif
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=xsmisc
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
#define MY_CXT_KEY "Devel::PPPort::_guts" XS_VERSION
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
typedef struct {
|
|
Packit |
7d6a7d |
/* Put Global Data in here */
|
|
Packit |
7d6a7d |
int dummy;
|
|
Packit |
7d6a7d |
} my_cxt_t;
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
START_MY_CXT
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=xsboot
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
{
|
|
Packit |
7d6a7d |
MY_CXT_INIT;
|
|
Packit |
7d6a7d |
/* If any of the fields in the my_cxt_t struct need
|
|
Packit |
7d6a7d |
* to be initialised, do it here.
|
|
Packit |
7d6a7d |
*/
|
|
Packit |
7d6a7d |
MY_CXT.dummy = 42;
|
|
Packit |
7d6a7d |
}
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=xsubs
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
int
|
|
Packit |
7d6a7d |
MY_CXT_1()
|
|
Packit |
7d6a7d |
CODE:
|
|
Packit |
7d6a7d |
dMY_CXT;
|
|
Packit |
7d6a7d |
RETVAL = MY_CXT.dummy == 42;
|
|
Packit |
7d6a7d |
++MY_CXT.dummy;
|
|
Packit |
7d6a7d |
OUTPUT:
|
|
Packit |
7d6a7d |
RETVAL
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
int
|
|
Packit |
7d6a7d |
MY_CXT_2()
|
|
Packit |
7d6a7d |
CODE:
|
|
Packit |
7d6a7d |
dMY_CXT;
|
|
Packit |
7d6a7d |
RETVAL = MY_CXT.dummy == 43;
|
|
Packit |
7d6a7d |
OUTPUT:
|
|
Packit |
7d6a7d |
RETVAL
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
int
|
|
Packit |
7d6a7d |
MY_CXT_CLONE()
|
|
Packit |
7d6a7d |
CODE:
|
|
Packit |
7d6a7d |
MY_CXT_CLONE;
|
|
Packit |
7d6a7d |
RETVAL = 42;
|
|
Packit |
7d6a7d |
OUTPUT:
|
|
Packit |
7d6a7d |
RETVAL
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
=tests plan => 3
|
|
Packit |
7d6a7d |
|
|
Packit |
7d6a7d |
ok(&Devel::PPPort::MY_CXT_1());
|
|
Packit |
7d6a7d |
ok(&Devel::PPPort::MY_CXT_2());
|
|
Packit |
7d6a7d |
ok(&Devel::PPPort::MY_CXT_CLONE());
|