On 18/10/2011 20:18, My Th wrote:
> O , 2011-10-18 17:54 +0100, Chris Morley rakstīja:
>> On 12/10/2011 00:15, My Th wrote:
>>> Sv, 2011-10-09 23:48 +0300, My Th rakstīja:
>>>> S , 2011-10-08 21:13 +0100, Chris Morley rakstīja:
>>>>> On 08/10/2011 20:02, My Th wrote:
>>>>>> It might be that the changes could be implemented in other place which
>>>>>> would shrink the patch size, but I don't know the OB code that well, so
>>>>>> I went for the most straightforward solution.
>>>>>
>>>>> Could a single line
>>>>>      static int n = LoadAllPlugins();
>>>>> in the function OBPlugin::PluginMap() replace all the other calls?
>>>>> The local static variable n would be initialized once on first use, but
>>>>> not subsequently used.
>>>>>
>>>>> I'm impressed that you took the trouble to understand the OBPlugin code.
>>>>> In the hybrid systems Cygwin and Mingw32 the plugins were originally not
>>>>> being loaded. Tim Vandermeersch made some changes which fixed this, but
>>>>> it would be helpful, if you are interested, in explaining how they work.
>>>>> (The OBPlugin code is a bit obscure; I can understand why macros are
>>>>> considered evil, http://www.parashift.com/c++-faq-lite )
>>>>
>>>> The biggest problem with the macros in this case is that the code in
>>>> them is so badly formatted that reading it makes head hurt. And on top
>>>> of that one has to follow the subclassing of OBPlugin ->   plugin types ->
>>>> plugin sub-types.
>>>>
>>>> OBPlugin::PluginMap() is the key point here. It has to be fully
>>>> populated before any lookup in that is done.
>>>>
>>>> Plugin map is a two level construct:
>>>> - First is a list of plugin types
>>>> - Second is a list of sub-types for each plugin type
>>>>
>>>> As I understand, the plugin map is populated by making instances of
>>>> specific plugin sub-types. Loading plugins makes also all the instances
>>>> of those plugin sub-types ->   plugin type map gets populated. So the
>>>> function OBPlugin::LoadAllPlugins() has to be called before the lookup
>>>> in plugin map is done.
>>>>
>>>> Besides loading the dynamic libraries, OBPlugin::LoadAllPlugins() also
>>>> have a hook for making instances of plugin classes using information in
>>>> a text file plugindefines.txt.
>>>>
>>>> The problem with putting OBPlugin::LoadAllPlugins() inside of
>>>> OBPlugin::PluginMap() is that OBDefine class, which makes instances of
>>>> plugin classes given in the text file, itself is a plugin and it fails
>>>> to make those instances if plugin loading is put there.
>>>>
>>>> It is required to make an instance of OBDefine after all the plugins
>>>> have been loaded to ensure that it can make instances of all the classes
>>>> the data file is referring to. OB knows about all available plugins only
>>>> after all those instances are made.
>>>>
>>>> The code in my patch ensures that all of the plugins are properly loaded
>>>> and it doesn't touch platform specific code for loading dynamic
>>>> libraries (that is done by DLHandler). It also doesn't change any
>>>> exposed interface, so ABI should be fine AFAIK.
>>>>
>>>> Only issue is that I can't see a single entry point where to put
>>>> OBPlugin::LoadAllPlugins(), at least not for the current OB plugin
>>>> system. Maybe the solution is to make wrapper function for
>>>> OBPlugin::PluginMap() and OBPlugin::LoadAllPlugins(), and make other
>>>> functions call the wrapper, letting only sub-class constructors to call
>>>> OBPlugin::PluginMap() directly. Does it sound reasonable? I can make
>>>> such version of the patch if needed.
>>
>> The attached patch (against the current trunk) is a modification of your
>> proposal, with LoadAllPlugins() called only during the initialization of
>> a local static variable in OBPlugin::PluginMap(). This saves several
>> other calls and a boolean. The initialization occurs at the first use of
>> any plugin. OBDefine seems to work ok (see revised test program) but the
>> global variable OBLocale was being called before it was initialized (the
>> well-known static initialization problem). This was fixed by replacing
>> the global variable by a local one in the OBDefine constructor, which I
>> think should not affect its operation.
>>
>> This works with Visual Studio 8 on Windows 7 (all I have), but it would
>> be nice to know know it worked on some other systems before committing it.
>>
>> Chris
>
> Hi!
>
> I have problems with your version of the patch. I'm using Gentoo Linux
> with gcc 4.6.1.
>
> Running the test program I get this:
> Try finding a forcefield in blank state..
> terminate called after throwing an instance of
> '__gnu_cxx::recursive_init_error'
>    what():  std::exception
> Aborted
>
It seems Visual C++ and gcc treat this differently, presumably Visual 
C++ has set the internal 'initialized' flag on the variable n before 
LoadAllPlugins() has returned, while gcc does it afterwards.
PluginMap() is called when there is any use of any plugin and I see the 
first use is when OpGenAlias in the API code is made. The recursive 
passes I suspect are all the other plugins being made when 
LoadAllPlugins() runs.

> I think the reason for this exception is the same as I mention for why
> LoadAllPlugins() can't be called from PluginMap() - the hook to
> OBDefine.
>
> Also there is no point making the function LoadAllPlugins() to return
> int if its not used. As it is now LoadAllPlugins() is called every time
> the PluginMap() is accessed. In my version I had an if statement to
> ensure that it is called only once and the status AllPluginsLoaded was
> updated inside the function just before the hook for OBDefine (which
> also accesses PluginMap()).
In the line
   static int n = LoadAllPlugins();
in PluginMap(), LoadAllPlugins should be called only once when the local 
static variable n is initialized on the first pass. This certainly 
happens for me (using the debugger); does it not for you?

>
> I can't comment right now on the issue with OBLocale since the patch in
> this form is clearly not working for me. I'm surprised it works on Win.
>
> I think the move of LoadAllPlugins() to private status is very
> appropriate, so I'm changing that also in my version.
>
> Another question I have is how to handle openbabel/dlhandler.h include?
> Is it really necessary to have it in both places - plugin.h and
> plugin.cpp? I think one of them is enough. Probably tough it should go
> in plugin.cpp since there is the definition of LoadAllPlugins() which
> uses it. Am I correct?
Yes, I meant to move it, but instead copied it. On second thoughts, I 
think it is better in plugin.h otherwise it needs to be included in a 
few other places in OB. Better to leave pluhin.h as the top level 
inclusive header for this area.
>
> In my test program I also add a check for plugin iterators. Attached
> updated versions of the patch and test program.
>

With gcc not playing ball, I've committed your patch, which seems to 
work fine for me, to trunk.

Chris

> Reinis

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
OpenBabel-Devel mailing list
OpenBabel-Devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbabel-devel

Reply via email to