Dirk Reiners wrote:
The basic problem is that the linker is too smart. We use static C++
objects quite a bit that register themselves with a factory when they
are instantiated. But a smart linker can see that none of the symbols
from that object file are used anywhere else in the program, and
conclude that the object file is not needed. The workaround is to
manually touch a symbol from the object file, which will force the
object file to be linked, which will in turn create the static object,
which can then register itself with the factory.
There is a technique called 'nifty-counter' which adresses this issue.
It is described in John Lakos' great book "Large scale c++ software
engineering". Basically, you do something like this:
foo.h:
class foo : public FactoryProduct { ... };
class fooInit { fooInit(); ~fooInit(); };
static fooInit s_initFoo;
foo.cpp:
int count = 0;
fooIinit() { if (count++ == 0) regWithFactory<Foo>(); }
~fooInit() { if(--count == 0) unregWithFactory<Foo>(); }
user_foo.cpp
#include <foo.h>
user_foo.cpp will have a reference to foo.cpp, so it will be accessible.
Naturally, this is a general technique to assure that any class-global
data is initialized before using the class itself. What we've done is to
wrap the xxxInit declaration and implementation in some useful macros,
and use layers of niftycounters. (If you have a macro
DECLARE_NIFTYCOUNTER(fooInit) and IMPLEMENT_NIFTYCOUNTER then you do
something like the following:)
foomodule.h:
DECLARE_NIFTYCOUNTER(fooModuleInit)
foomodule.cpp
DECLARE_NIFTYCOUNTER(foo)
DECLARE_NIFTYCOUNTER(bar)
IMPLEMENT_NIFTYCOUNTER(fooModuleInit)
.. and so on and so forth. This is quite useful since you don't have to
include the entire header of foo, just have it's niftycounter class and
a local instance of that class. Of course you can layer this, and have
one header refering to foomodule.h-equivalents and thus having only one
header to include in order to get all these dynamic objects from
several modules referenced (or perhaps only some, depending on your
application). Or in case of OpenSG, that could be included by
osgInit()'s .cpp file.
The drawback of this is that if the work done in niftycounter-init is
heavy, you may have delays before entering main(). But just registering
classes in factories and similar things have not been a problem for us.
Somewhat related to this is that if there are many singletons (such as
the factory in the given example) in your application, you need to be
careful about the order of construction/destruction, but doing that is
not especially difficult.
Regards,
/Marcus
-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users