From 28db151d56899d79c694f9da49e1bec15dfe7820 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Fri, 2 Aug 2024 21:52:59 +0000 Subject: [PATCH] perlguts.pod - mention SV_THINKFIRST* macros, move blocks around This commit: * Adds some initial description of the SV_THINKFIRST* macros to perlguts * Places that new content, along with Read-only and Copy-on-write sections closer to the sections which describe how to modify string contents. This commit is far from perfect. Reworking the the "Working with SVs" part of perlguts, such that there is a more obviously dedicated section for discussing string handling, seems like it would be definite future improvement. --- pod/perlguts.pod | 138 ++++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 48 deletions(-) diff --git a/pod/perlguts.pod b/pod/perlguts.pod index d08cff6a5d73..f04cb5fc180f 100644 --- a/pod/perlguts.pod +++ b/pod/perlguts.pod @@ -521,6 +521,96 @@ IV with loss, SvIOKp, SvNOKp and SvNOK will be set, while SvIOK wont be. In general, though, it's best to use the C macros. +=head2 Read-Only Values + +In Perl 5.16 and earlier, copy-on-write (see the next section) shared a +flag bit with read-only scalars. So the only way to test whether +C, etc., will raise a "Modification of a read-only value" error +in those versions is: + + SvREADONLY(sv) && !SvIsCOW(sv) + +Under Perl 5.18 and later, SvREADONLY only applies to read-only variables, +and, under 5.20, copy-on-write scalars can also be read-only, so the above +check is incorrect. You just want: + + SvREADONLY(sv) + +If you need to do this check often, define your own macro like this: + + #if PERL_VERSION >= 18 + # define SvTRULYREADONLY(sv) SvREADONLY(sv) + #else + # define SvTRULYREADONLY(sv) (SvREADONLY(sv) && !SvIsCOW(sv)) + #endif + +Or better yet, read about THINKFIRST macros below. + +=head2 Copy on Write + +Perl implements a copy-on-write (COW) mechanism for scalars, in which +string copies are not immediately made when requested, but are deferred +until made necessary by one or the other scalar changing. This is mostly +transparent, but one must take care not to modify string buffers that are +shared by multiple SVs. + +You can test whether an SV is using copy-on-write with C. + +You can force an SV to make its own copy of its string buffer by calling +C or SvPV_force_nolen(sv). + +If you want to make the SV drop its string buffer, use +C or simply +C. + +All of these functions will croak on read-only scalars (see the previous +section for more on those). + +To test that your code is behaving correctly and not modifying COW buffers, +on systems that support L (e.g. Unix, Linux, BSDs, macOS) you can +configure perl with C<-Accflags=-DPERL_DEBUG_READONLY_COW> and it will turn +buffer violations into crashes. You will find it to be marvellously slow, +so you may want to skip perl's own tests. + +=head2 THINKFIRST before writing to a string buffer + +You are more likely to (and usually I) see the C +macro used to check whether an SV is ready to be written to, as this is a +combined single check to see if the SV: + +=over 4 + +=item * +Points to a COW buffer + +=item * +Is READONLY + +=item * +Contains a reference + +=item * +Has some relevant magic assigned + +=back + +Two related macros can be used to perform those checks and, if required, +also perform some action: + +=over 4 + +=item * +C calls C to copy the +string buffer, turning it into a mutable string. + +=item * +C calls C +which drops any string buffer pointed to by C. This is usually +used to avoid copying any COW string to a new buffer, prior to +writing some completely new string to C. + +=back + =head2 Working with AVs There are two main, longstanding ways to create and load an AV. The first @@ -1326,54 +1416,6 @@ following code: If the order of C and C had been reversed, then the macro C would need to be called instead of C. -=head2 Read-Only Values - -In Perl 5.16 and earlier, copy-on-write (see the next section) shared a -flag bit with read-only scalars. So the only way to test whether -C, etc., will raise a "Modification of a read-only value" error -in those versions is: - - SvREADONLY(sv) && !SvIsCOW(sv) - -Under Perl 5.18 and later, SvREADONLY only applies to read-only variables, -and, under 5.20, copy-on-write scalars can also be read-only, so the above -check is incorrect. You just want: - - SvREADONLY(sv) - -If you need to do this check often, define your own macro like this: - - #if PERL_VERSION >= 18 - # define SvTRULYREADONLY(sv) SvREADONLY(sv) - #else - # define SvTRULYREADONLY(sv) (SvREADONLY(sv) && !SvIsCOW(sv)) - #endif - -=head2 Copy on Write - -Perl implements a copy-on-write (COW) mechanism for scalars, in which -string copies are not immediately made when requested, but are deferred -until made necessary by one or the other scalar changing. This is mostly -transparent, but one must take care not to modify string buffers that are -shared by multiple SVs. - -You can test whether an SV is using copy-on-write with C. - -You can force an SV to make its own copy of its string buffer by calling C or SvPV_force_nolen(sv). - -If you want to make the SV drop its string buffer, use -C or simply -C. - -All of these functions will croak on read-only scalars (see the previous -section for more on those). - -To test that your code is behaving correctly and not modifying COW buffers, -on systems that support L (i.e., Unix) you can configure perl with -C<-Accflags=-DPERL_DEBUG_READONLY_COW> and it will turn buffer violations -into crashes. You will find it to be marvellously slow, so you may want to -skip perl's own tests. - =head2 Magic Variables [This section still under construction. Ignore everything here. Post no