Blame parts/inc/MY_CXT

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());