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.