Paavo Helde
11/19/2008 9:58:00 PM
Christof Warlich <cwarlich@gmx.de> kirjutas:
> Victor Bazarov schrieb:
>>> To avoid this, I replaced the above with the following code, now
>>> having everything defined in a header file:
>>>
>>> // init.h
>>> #include <stdio.h>
>>> inline int init() {
>>> // whatever needs to be initialized goes here
>>> printf("initializing\n");
>>> return 0;
>>> }
>>> // ensure that init is called exactly once
>>> inline int initialize(void) {
>>> static int dummy = init();
>>> return 0;
>>> }
>>> static int dummy = initialize();
>>>
>>> This works as desired: With the two sample application files one.cc
>>> and two.cc:
>>>
>>> // one.cc
>>> #include "init.h"
>>> int main(void) {
>>> return 0;
>>> }
>>>
>>> // two.cc
>>> #include "init.h"
>>>
>>> and compilation:
>>>
>>> $ g++ -I. one.cc two.cc
>>>
>>> the init() function is only called once:
>>>
>>> $ ./a.out
>>> initializing
>>>
>>> The only concern is that a new global dummy variable will be created
>>> for every application file that includes init.h. Any ideas to avoid
>>> this?
>>
>> No offence, but you're trying to avoid using object modules in your
>> library and still want to have a feature that is only possible to
>> have *if* your library has at least one object module.
>
> Please have a closer look at the code example above: It shows that it
> _is_ possible to execute initialization code exactly once before main()
> _without_ the need of a dedicated library object module. The files
> one.cc and two.cc are examples for application code that is _using_ the
> library, hence including the library's interface definition, i.e.
init.h
> in the example above. Sorry that I haven't made that clear enough.
>
> So why did I post, you may ask. Generally, I'm quite happy with this
> solution, but it comes at the cost of needing the space of an integer
> per application object file that uses the library (due to the global
> dummy variable). Thus, I'm asking for ideas if this could be avoided or
> at least be minimized. All I could think of so far was to make dummy a
> char instead of an int to reduce the amount of memory being occupied.
>
You have several choices, and you have to make some compromises:
1) put a call to initialize() in the beginning of each public function.
If the functions are mostly longer than 3 lines, the cost is probably
negligible.
2) make all functions a singleton methods, provide a function for
returning a reference to the singleton, which performs init in ctor. This
is essentially a more glorified variant of 1).
3) provide a real library, with a static global inside it taking care
about initialization. This suffers from the order-of-static-
initialization problem, meaning that your library may not be portably
called before main().
4) requiring the client to call Init() explicitly. This creates an easy
opportunity for a client-side error, which might be hard to detect
(unless you also do 1), in which case there is no point to do 4)).
5) your current approach, making a static per each TU. The cost is
probably negligible unless the client project has thousands of nearly
empty source files.
I think I would pick 1) myself. But 5) is also quite attractive. It has
the nice feature of circumventing the statics initialization order
problem in different TU-s, inherent to 3).
hth
Paavo