[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

init code in header-only library

Christof Warlich

11/18/2008 5:38:00 PM

Hi,

I'm working on a (template) library that is up to now entirely
implemented in header-files. This makes the library quite convenient to
use as no extra object code needs to be linked when using the library.
But now, the library needs to run some initialization code at system
startup. Usually, this initialization code would be called from a .cc
file once at system startup, e.g. by assigning the init function to a
global variable:

// init.cc
#include <stdio.h>
inline int init() {
// whatever needs to be initialized goes here
printf("initializing\n");
return 0;
}
static int dummy = init();

With this simple approach, calling init() cannot be done from a header
file, as it will be called as often as it will be included by .cc files.
Thus, it is required to link the application with the object derived
from init.cc now.

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?

Christof
4 Answers

Victor Bazarov

11/19/2008 2:45:00 AM

0

Christof Warlich wrote:
> Hi,
>
> I'm working on a (template) library that is up to now entirely
> implemented in header-files. This makes the library quite convenient
> to use as no extra object code needs to be linked when using the
> library. But now, the library needs to run some initialization code
> at system startup. Usually, this initialization code would be called
> from a .cc file once at system startup, e.g. by assigning the init
> function to a global variable:
>
> // init.cc
> #include <stdio.h>
> inline int init() {
> // whatever needs to be initialized goes here
> printf("initializing\n");
> return 0;
> }
> static int dummy = init();
>
> With this simple approach, calling init() cannot be done from a header
> file, as it will be called as often as it will be included by .cc
> files. Thus, it is required to link the application with the object
> derived from init.cc now.
>
> 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. It's like
you want to have your cake and eat it too (although I don't really
like that expression).

You can, if you want, just *document* that your library needs to
be initialised by calling your initialisation function. If the user
needs to use your library before 'main' is called, they would need
to define a single static variable somewhere in their code, and use
that variable's initialisation to call your function. If they don't
care about initialising your library before 'main', they could just
call your initialisation function at the beginning of 'main'. No
problem. Let the user decide.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


Christof Warlich

11/19/2008 9:38:00 AM

0

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.

Paavo Helde

11/19/2008 9:58:00 PM

0

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

Christof Warlich

11/19/2008 10:55:00 PM

0

Paavo Helde schrieb:
> 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.
......
> 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
>
Thanks for summing up the options, in particular for 1) , which I have
not considered so far. Getting someone else's view is always good to
avoid stupid design decisions. Anyway, I will stick to 5), as some of my
library functions will be very short, i.e. one-liners. And you are
absolutely right that the memory cost will be neglectable for almost all
real world applications using the library.