Thread: Initialising data when application initialises?

  1. #1
    Code Monkey Davros's Avatar
    Join Date
    Jun 2002
    Posts
    812

    Initialising data when application initialises?

    What's the best way to initialise [static] data when the main thread of an application initialises?

    Here's what I mean: Let's suppose I am writing an api function which needs to work with some static data. Ideally this needs initialising only once. An example would be some check sum routine--here's some psuedo code to demonstrate:

    Code:
    unsigned int calc_crc32(void* buf, size_t buf_sz)
    {
      int rslt = 0;
    
      // Static table
      static unsigned char s_table[255];
      static bool s_init = false;
    
      // Initialise static table
      if (s_init == false)
      {
        ...
        s_init = true;
      }
    
      // Calc result
      if (buf != 0)
      {
         ...
         rslt = some_rslt;
      }
    
      return rslt;
    }
    What I want to happen is for this function to be called automatically on initialisation, so as to initialise the static data. This is only an example--I also want (in general) to initialise heap data, so I really do want to know how to call initialisation functions when the main thread starts so as to avoid thread race conditions in the initialisation of data. Another example of use would be the initialisation of singletons.

    Now I know I can put a dummy variable in a cpp file and initialise it from the function, like so:

    Code:
    // Some cpp file
    static int s_dummy = calc_crc32(0, 0);
    But this forces me to use a dummy value in order to call c_calc_crc32() at start-up.

    Is there some way I can ensure calc_crc32 (or a function in general) is called in the main thread when it starts up, without having to use dummy data? And without having to call the function from main--assume I writing api.

    Any other suggestions?

    Thanks
    OS: Windows XP
    Compilers: MinGW (Code::Blocks), BCB 5

    BigAngryDog.com

  2. #2
    Registered User
    Join Date
    Feb 2006
    Posts
    312
    If I understand you correctly, is this the sort of thing you're after..?
    Code:
    char* table_initialiser()
    {
        static char s_table[255];
        //some code to initialise s_table
    
        return s_table;
    }
    
    void some_function()
    {
        static char * const s_table(table_initialiser());
    }

  3. #3
    Code Monkey Davros's Avatar
    Join Date
    Jun 2002
    Posts
    812
    Thanks for the reply. No--not really. (* See note at bottom)

    What I'm asking is a very general question. Really, it is this:

    How do cause some function to be called on main thread initialisation?

    I can call it through the use of a dummy variable initialisation, like so:

    int dummy = some_func();

    But is there a better way? I.e. without having dummy variables every where?

    I'm struggling to explain myself without specific examples. So here's another one -- a singleton:

    Code:
    SomeClass& SomeClass::singleton()
    {
      static SomeClass sc;
      return sc;
    }
    Now this is OK--except in a multiple threaded application where the singleton() method may be called for the first time by two threads simultaneously, resulting in a race condition during the creation of the static "sc" variable.

    I can overcome this by ensuring the singleton() method is initially called in the application's main thread by:

    SomeClass& dummy = SomeClass::singleton();

    in the cpp file.

    However, do I really need to declare a dummy variable in order to get the function to be called on initialisation?

    Is there some way in C++ I can get SomeClass::singleton() to be called on start-up without the use of dummy data?

    * PS

    Thanks for the example Bench82 -- I see what your code is doing now. However, the answer is still no--it's not what I want. I still want a function called on main thread start-up because I need to ensure it is called for the first time in the main thread an not in any other thread. Also, remember, I am writing an api so it is not applicable to call functions in the main() C function.
    Last edited by Davros; 01-01-2007 at 08:48 PM.
    OS: Windows XP
    Compilers: MinGW (Code::Blocks), BCB 5

    BigAngryDog.com

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    If you're doing things with multiple threads of execution, you're outside the scope of the C++ standard, and fall back on implementation specific means to ensure objects shared between threads are accessed correctly.

    Even leaving out the question of multi-threading, there is still no portable means of ensuring that static data is initialised unless you specifically ensure that it is. That means main(), which is formally the first point at which the programmer is guaranteed to have control, or some function called by main() must take some action to ensure the data is initialised.

    One way which often works is to have a static object instantiated in the same source file as main(). For example;
    Code:
    class Initialiser
    {
       public:
        Initialiser()
        {
              // initialise static data
        };
        ~Initialiser()
        {
               // clean up static data
        };
    };
    
    Initialiser doit;
    
    int main()
    {
         // assume doit's constructor has been invoked so static data is initialised
    }
    The main problem with this, at least from your perspective, is that it requires modification of the source file that contains the main() function. Another problem with this approach is that compilers are not formally required to instantiate the object named doit before calling main(). And, in fact, some aggressive compilers and their optimisers will recognise that nothing is being done with it, and therefore not instantiate it at all -- which means that your global data will not be instantiated at (presumably) the point where you need it to be. Those compilers can often be fooled, somewhat, by these simple changes;
    Code:
    class Initialiser
    {
       public:
        Initialiser()
        {
              // initialise static data
        };
        ~Initialiser()
        {
               // clean up static data
        };
    
        void PingObject() {};
    };
    
    Initialiser doit;
    
    int main()
    {
         doit.PingObject();
         // assume doit's constructor has been invoked so static data is initialised
    }
    This works as doit is a static object, and is therefore guaranteed to be initialised at some time before invoking a non-static member on it (which is what the call of doit.PingObject() does). The catch is that it is still up to the compiler to decide when, or if, to instantiate the object. That may happen before main() is called, it may happen immediately before the the call of doit.PingObject(). However, it breaks your constraint of leaving main() unmodified.

    One alternative approach, which works with some compilers but not others, is to place a static object in some other source file and link in the corresponding compiled object file when building the application. The main problem with this is that it doesn't work with some compilers and linkers: just linking in a compiled object file is insufficient to ensure that any objects within it are instantiated (i.e. their constructors are called to initialise your static data). It also very rarely works with an object library, as linkers tend to avoid extracting code from libraries unless that code is overtly called by the program. Which means you still need to take some action to ensure that your static data is initialised.

    Other than that, you are usually left to rely on compiler specific techniques. For example, some compilers support a pragma that allow the programmer to queue functions for calling, before and after main() is called.

    IMHO, it is a good thing that this is the way it is. I would generally be unappreciative if I received a library, and it quietly did work that I didn't know about. If, OTOH, I receive a library with documentation that says "you must do <action> to ensure the library is properly initialised", then I can make a deliberate decision --- as designer and implementer of code which uses that library --- as to how I ensure the library is properly initialised before I use it.

  5. #5
    Code Monkey Davros's Avatar
    Join Date
    Jun 2002
    Posts
    812
    Thanks Grumpy for taking the time to respond.

    I guess that answers my question. Thank you.
    OS: Windows XP
    Compilers: MinGW (Code::Blocks), BCB 5

    BigAngryDog.com

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. xor linked list
    By adramalech in forum C Programming
    Replies: 23
    Last Post: 10-14-2008, 10:13 AM
  2. Where's the EPIPE signal?
    By marc.andrysco in forum Networking/Device Communication
    Replies: 0
    Last Post: 12-23-2006, 08:04 PM
  3. Intercepting Data Bound for Local Application from Remote Server
    By maththeorylvr in forum Networking/Device Communication
    Replies: 2
    Last Post: 11-29-2005, 01:57 AM
  4. Dynamic data members?
    By confusalot in forum C++ Programming
    Replies: 4
    Last Post: 02-27-2005, 11:15 AM
  5. C Programming Question
    By TK in forum A Brief History of Cprogramming.com
    Replies: 13
    Last Post: 07-04-2002, 07:11 PM