From: Jarkko Hietaniemi Date: Thu, 15 Nov 2001 23:18:19 +0000 (+0000) Subject: Document the MY_CXT business; from Paul Marquess. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=662a0f8c5d8b6f39576444a5a7208fca2f67099e;p=p5sagit%2Fp5-mst-13.2.git Document the MY_CXT business; from Paul Marquess. p4raw-id: //depot/perl@13031 --- diff --git a/pod/perlxs.pod b/pod/perlxs.pod index cee8e16..5146a1e 100644 --- a/pod/perlxs.pod +++ b/pod/perlxs.pod @@ -1702,6 +1702,133 @@ The INPUT and OUTPUT sections substitute underscores for double-colons on the fly, giving the desired effect. This example demonstrates some of the power and versatility of the typemap facility. +=head2 Safely Storing Static Data in XS + +Starting with Perl 5.8, a macro framework has been defined to allow +static data to be safely stored in XS modules that will be accessed from +a multi-threaded Perl. + +Although primarily designed for use with multi-threaded Perl, the macros +have been designed so that they will work with non-threaded Perl as well. + +It is therefore strongly recommended that these macros be used by all +XS modules that make use of static data. + +The easiest way to get a template set of macros to use is by specifiying +the C<-g> (C<--global>) option with h2xs (see L). + +Below is an example module that makes use of the macros. + + #include "EXTERN.h" + #include "perl.h" + #include "XSUB.h" + + /* Global Data */ + + #define MY_CXT_KEY "BlindMice::_guts" XS_VERSION + + typedef struct { + int count; + char name[3][100]; + } my_cxt_t; + + START_MY_CXT + + MODULE = BlindMice PACKAGE = BlindMice + + BOOT: + { + MY_CXT_INIT; + MY_CXT.count = 0; + strcpy(MY_CXT.name[0], "None"); + strcpy(MY_CXT.name[1], "None"); + strcpy(MY_CXT.name[2], "None"); + } + + int + newMouse(char * name) + char * name; + PREINIT: + dMY_CXT; + CODE: + if (MY_CXT.count >= 3) { + warn("Already have 3 blind mice") ; + RETVAL = 0; + } + else { + RETVAL = ++ MY_CXT.count; + strcpy(MY_CXT.name[MY_CXT.count - 1], name); + } + + char * + get_mouse_name(index) + int index + CODE: + dMY_CXT; + RETVAL = MY_CXT.lives ++; + if (index > MY_CXT.count) + croak("There are only 3 blind mice."); + else + RETVAL = newSVpv(MY_CXT.name[index - 1]); + + +B + +=over 5 + +=item MY_CXT_KEY + +This macro is used to define a unique key to refer to the static data +for an XS module. The suggested naming scheme, as used by h2xs, is to +use a string that consists of the module name, the string "::_guts" +and the module version number. + + #define MY_CXT_KEY "MyModule::_guts" XS_VERSION + +=item typedef my_cxt_t + +This struct typedef I always be called C -- the other +C macros assume the existence of the C typedef name. + +Declare a typedef named C that is a structure that contains +all the data that needs to be interpreter-local. + + typedef struct { + int some_value; + } my_cxt_t; + +=item START_MY_CXT + +Always place the START_MY_CXT macro directly after the declaration +of C. + +=item MY_CXT_INIT + +The MY_CXT_INIT macro initialises storage for the C struct. + +It I be called exactly once -- typically in a BOOT: section. + +=item dMY_CXT + +Use the dMY_CXT macro (a declaration) in all the functions that access +MY_CXT. + +=item MY_CXT + +Use the MY_CXT macro to access members of the C struct. For +example, if C is + + typedef struct { + int index; + } my_cxt_t; + +then use this to access the C member + + dMY_CXT; + MY_CXT.index = 2; + +=back + =head1 EXAMPLES File C: Interface to some ONC+ RPC bind library functions.