Bjoern Hoehrmann <[EMAIL PROTECTED]> writes:
>Hi,
>
>  http://search.cpan.org/src/BJOERN/SGML-Parser-OpenSP-0.02/OpenSP.xs
>is a C++ XS extension. I am trying to figure out what is needed, if
>anything, to make it play nicely in the context of multiple threads.

The MOST important thing is to make sure your XS code and any library 
code it calls is ready for threads. That means no static variables
without MUTEX exclusion and all the usual thready things.

>Do I understand correctly from perlguts that nothing is actually needed?

as far as passing 'my_perl' about (which is what dTHX and co. do)
you can do _need_ to do anything. But of you do nothing the 
function to "find current perl for this thread" which would 
be called by dTHX is instead called every time it is needed
which may be several times in one sv.h macro!

>
>Then perlguts lists two other way of making this more efficient, the
>most efficient way is supposed to be using the pTHX_ macro, do I under-
>stand correctly that my extension generally cannot use it as most of the
>methods of the main object are actually callbacks called by external
>code which won't pass the required parameters?

Probably true, but any sane callback scheme will pass some 
"user data" pointer to the C function. You can put the interpreter
pointer in that if you want to go to extreams.


>
>Then, the middle way would be to define PERL_NO_GET_CONTEXT prior to
>including the Perl headers and then call dTHX from all functions and
>methods that use the Perl API, right? 

I usually put the PERL_NO_GET_CONTEXT at the top and then add
dTHX when compiler complains, but this usually means nearly 
all functions ;-)

>Then, are there any requirements
>for when dTHX should be called (other than before actually using the
>API) like, for example, before or after dSP? I guess dSP counts as
>using the API so dTHX would have to precede it.

Yes.

>
>Can I use the two more efficient way in combination? For example, there
>is the heavily used _cs2sv function which converts a custom string re-
>presentation to a proper UTF-8 SV*, and the sdata method which is called
>from external code, currently
>
>  void SgmlParserOpenSP::sdata(const SdataEvent& e)
>  {
>    if (!handler_can("sdata"))
>      return;
>  
>    updatePosition(e.pos);
>  
>    HV* hv = newHV();
>  
>    hv_store(hv, "EntityName", 10, _cs2sv(e.entityName), HvvEntityName);
>    hv_store(hv, "Text", 4, _cs2sv(e.text), HvvText);
>  
>    dispatchEvent("sdata", hv);
>  }
>
>Can I change this to
>
>  ...
>  SV* _cs2sv(pTHX_ const SGMLApplication::CharString s)
>  ...
>  void SgmlParserOpenSP::sdata(const SdataEvent& e)
>  {
>    dTHX;
>    ...
>    hv_store(hv, "EntityName", 10, _cs2sv(aTHX_ e.entityName), ...);
>    hv_store(hv, "Text", 4, _cs2sv(aTHX_ e.text), ...);
>    ...
>  }

Yes you can do that and mixing dTHX and pTHX/aTHX like that 
is good compromise.

>
>or are these methods mutually exclusive? 

Not at all. Both just serve to get a 

PerlInterpreter *my_perl;

Initialized and in scope for macros to use.


>Is there anything special to
>consider for C++ extensions as opposed to C extensions?

Not really.

For a threaded-perl C++ thing I would be tempted 
to have a "base class" (or mixin) which saved the iterpreter
pointer in the object. It really needs
a warpped mind to weave perls #define forest 
with C++. But I think something like 

class PerlBase {
...
private:
  PerlInterpreter *my_perl;
...
};

Would mean that all the methods of the class would have 
a 'my_perl' in scope via their 'this' pointer so would 
not need pTHX/aTHX. Only the constructor(s)
would need it - but they would need to be tricky to 
get a parameter called 'my_perl' assigned to a member called 'my_perl'

Perhaps a constructor like:

   PerlBase(pTHX) { this->my_perl = my_perl; }  

is all it needs ???


>
>Assuming nothing actually needs to be done to support such usage, are
>there any rules to estimate what could be gained from using one of the
>more efficient methods in my extension? 

Not really - it depends how your platfrom gets at thread local 
thingys. On some x86's there is a segment register pointing at 
the thread local pool so it is nearly free. On other 
systems where threads are an after-thought it can be a system call.
So dTHX may cost a cycle or two, or several milli-seconds
if system call counts as a yeild!


>perlguts only states it is more
>efficient but that could mean anything from totally insignificant to my
>extension would be unusable if not optimized in this regard. Are there
>rules to determine which functions would gain most from optimizations
>in this regard?

Any function which uses perl API a lot will benefit.
If it just unpacks a few things and the top then grinds away 
in C and returns a simple result then a "few" dTHX equivalents
are probably not too bad on systems where threads 
are usable. 

I recommend doing a 

make Whatever.i 

to get the C pre-processed version 
and then taking a look at the insanely 
complex function calls that happen without the dTHX-s

In my case some dumb compiler just gave up and dTHX
was only way to get Tk to compile.


>
>TIA.

Reply via email to