syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I have an object whose Devel::Peek::Dump() is as follows:
SV = RV(0xa88ae8) at 0xa88adc REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0xa889bc SV = PVMG(0x253aedc) at 0xa889bc REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,OVERLOAD,pIOK) IV = 41565372 NV = 0 PV = 0 STASH = 0x97dea4 "Math::MPFR"
Within XS code, how do I establish that the TEMP flag is there ? I had thought that SvTEMP(sv) would return the numeric value of the TEMP flag, but it returns zero. I also checked SvTEMP(SvRV(sv)) - which returned 0 (as I expected).

UPDATE: I now believe that what I was testing for the presence of the TEMP flag did, in fact *not* have the TEMP flag set at all - and that everything worked as it should have.

As a second question, what does the presence of that TEMP flag mean? Looking at the XSub that creates the object, I don't really see a reason for the TEMP flag to be there. That XSub is:
SV * Rmpc_realref(mpc_t *op) { mpfr_t * mpfr_t_obj; SV * obj_ref, * obj; New(42, mpfr_t_obj, 1, mpfr_t); if(mpfr_t_obj == NULL) croak("Failed to allocate memory in Rmpc_r +ealref function"); obj_ref = newSV(0); obj = newSVrv(obj_ref, "Math::MPFR"); mpfr_t_obj = mpc_realref(*op); sv_setiv(obj, INT2PTR(IV,mpfr_t_obj)); SvREADONLY_on(obj); return obj_ref; }
where mpc_realref() is an mpc library function that returns a pointer to an mpfr library structure (mpfr_t).

UPDATE: The TEMP flag was *not* being set by the XSub - it was only being set because the XSub's return value was not being asigned to a variable.

I have other similar objects (where the only difference I can see is that the TEMP flag is absent). These other objects require a slightly different DESTROY() procedure - so I'm thinking that the solution is to have:
void DESTROY(mpfr_t * op) { if(the TEMP flag is present) {do one thing} else {do the other thing} }
Hence my interest in being able to detect the presence of the TEMP flag.

Cheers,
Rob

Replies are listed 'Best First'.
Re: [XS] How to detect the TEMP flag
by BrowserUk (Patriarch) on Nov 20, 2008 at 06:39 UTC

    This is a case of the blind leading the blind, so watch my step. Which I guess translates to "Listen carefully, because I shall say this only once--and probably wrong".

    The effect you are describing seems to be associated with the mysteries and magic of TARGs. Those temporary stack items that are created at compile time and reused by different subs/ops and even recursive re-invocations of the same sub. They are related to the well-known optimisation that means that some sub variables don't get cleaned up when they return, but rather persist to be reused next time.

    There is some scant mention of them in the sections: "Putting a C value on Perl stack", "Scratchpads" & "Scratchpads and recursion" of Perlguts, but it is less than clear. At least to me when I encountered this a couple of years ago.

    I found that if you ensure that subroutine return values are explicitly set sv_2mortal(), many of the traps "went away", but I fear that I may have been creating SVs that would never get cleaned up?

    Hopefully, someone who knows what they are talking about will set the record straight, but maybe this mention will trigger understanding in your brain. I've personally got half a dozen ideas for modules that need XS but on whihc I can make no progress for my failure to understand this mechanism (amongst others:().


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I found that if you ensure that subroutine return values are explicitly set sv_2mortal(), many of the traps "went away", but I fear that I may have been creating SVs that would never get cleaned up?

      I think that's the main difference. I'm creating persistent objects that ought to be cleaned up - but only when they go out of scope. I don't think I can make use of 'sv_2mortal' for this particular exercise. (I could be wrong about that ... I'll have to give it some more thought.)

      Hopefully, my reply to ikegami's reply makes things a little clearer. (My original post suffers from having been written 10 minutes too early. I hate it when that happens.)
      I do know that if I don't bless the object into any package, then everything works fine. The only problems then are that:
      1) we'll get memory leaks if:
          a) the user doesn't manually call the clean-up function;
          b) the Rmpc_realref return value is not assigned to a variable;
      2) the Rmpc_realref return value can't be used with the overloaded Math::MPFR operators.

      Cheers,
      Rob
Re: [XS] How to detect the TEMP flag
by syphilis (Archbishop) on Nov 20, 2008 at 05:52 UTC
    Within XS code, how do I establish that the TEMP flag is there ?

    Bah!! ... the TEMP flag doesn't always get set - and it certainly doesn't get set by the XSub. Whether it gets set or not depends upon whether I assign the return of Rmpc_realref() to a variable or not. I rewrote the perl section of my test script, assigning the return value to a variable, and the TEMP flag disappeared altogether.

    It looks like I'm unable to bless this object into package Math::MPFR - if I do, I invariably get a segfault when DESTROY() is called. I can't see any way of enabling DESTROY() to distinguish between the 2 "types" of objects.

    Cheers,
    Rob

      I can't see any way of enabling DESTROY() to distinguish between the 2 "types" of objects.

      What two kinds? This TEMP flag business is an XY Problem.

        What two kinds?

        For the usual Math::MPFR objects, destruction is conducted as follows:
        void DESTROY(mpfr_t * p) { mpfr_clear(*p); Safefree(p); }
        For this slightly different "kind" that I was hoping to introduce, it needs to be:
        void DESTROY(mpfr_t * p) { Safefree(p); }
        This is because, with the latter "kind", there's no dynamically allocated space for mpfr_clear() to clean up - and attempting to do so, simply causes a segfault.

        My main difficulty is that, for both "kinds", the Devel::Peek::Dump() is essentially the same - which leads me to now think that blessing both "kinds" into the same package is a no-go. Initially, I thought I could make use of the TEMP flag - but that's a blind alley that grew out of a poorly designed test script (rather than an XY problem :-)
        If I had realised sooner just what the TEMP flag implied, I would have understood that it had nothing to offer me and my post would have been quite different ... possibly would not have come to fruition.

        Basically, DESTROY() needs to be able to determine whether or not to invoke the mpfr_clear() call - and my problem is that I don't see how it can make that decision, simply because the means to distinguish one "kind" from the other doesn't exist.

        The idea is probably headed for the scrap heap .... the value of what I was thinking of doing has only *limited* value in a perl context, anyway.

        Cheers,
        Rob
Re: [XS] How to detect the TEMP flag
by jand (Friar) on Nov 20, 2008 at 19:42 UTC
    The TEMP flag is turned on by sv_2mortal(). It indicates that the value stored in the SV is going to be freed by the next FREETMPS boundary anyways, so if you are assigning its value to another SV (via sv_setsv() and its friends), then you can simply steal the data (e.g. PV) from the mortal SV instead of allocating new memory and copying it.

    There is normally no reason to worry about this in correctly written XS code, so the fact that you have to deal with this flag might indicate a problem in your code elsewhere.

    Generally you should not keep references to mortal SVs beyond the next FREETMPS, which I think you may be doing here.