Boost.Flyweight Documentation - Tutorial - Technical issues

# Boost.Flyweight Tutorial: Technical issues

Extending Boost.Flyweight
Boost.Flyweight tutorial
Annex: MPL lambda expressions

## Contents

- Static data initialization

## Static data initialization

For any given `T`, the type `flyweight<T>` maintains some class-wide or static data that needs to be properly initialized before the class can be used. The internal machinery of Boost.Flyweight guarantees that static data initialization takes place automatically before the first use of the particular `flyweight<T>` instantiation in the program, and in any case always during the so-called dynamic initialization phase of the program startup sequence. Although this is not strictly required by the C++ standard, in current practice dynamic initialization is completed before `main()` begins.

So, for all practical purposes, static data initialization is performed before `main()` or before the first pre-`main()` usage of the class, for instance if we declare a global `static flyweight<T>` object. This covers the vast majority of usage cases in a transparent manner, but there are some scenarios where the automatic static data initialization policy of Boost.Flyweight can fail:

>     // global thread pool

>     class thread_pool
>     {
>     public:
>       thread_pool()
>       {
>         for(int i=0;i<100;++i)p[i]=shared_ptr<thread>(new thread(thread_fun));
>       }

>     private:
>       static void thread_fun()
>       {
>         // uses flyweight<std::string>
>       }
>       array<shared_ptr<thread>,100> p;
>     };

>     static thread_pool thpool;

>     int main()
>     {
>       ...

The global pool of the example launches several threads, each of which internally uses `flyweight<std::string>`. Static data initialization can potentially be executed twice concurrently if two threads happen to collide on the first usage of `flyweight<std::string>`: Boost.Flyweight initialization does not consider thread safety. So, we need to explicitly take care of static data initialization in a thread safe context before launching the threads:

>     class thread_pool
>     {
>     public:
>       thread_pool()
>       {
>         flyweight<std::string>::init();
>         for(int i=0;i<100;++i)p[i]=shared_ptr<thread>(new thread(thread_fun));
>       }
>       ...

The static member function `init` is not thread safe, either: in our particular example it just happens to be called in a single threaded environment. When concurrency can happen, `flyweight<T>::init` must be properly synchronized by the programmer by using some mutual exclusion mechanisms of her own.

The following is another example where the default static initialization provided by Boost.Flyweight can fail:

>     static std::vector<flyweight<std::string> > v;

>     int main()
>     {
>       // use v
>     }

In some environments, the program above fails when exiting. For instance, if run from Microsoft Visual C++ environment in debug mode, a breakpoint is triggered at termination time and the debug output window shows a message along the following:

>     HEAP[test.exe]: HEAP: Free Heap block 3a6488 modified at 3a6650 after it was
>     freed
>     Windows has triggered a breakpoint in test.exe.
>     This may be due to a corruption of the heap, and indicates a bug in test.exe
>     or any of the DLLs it has loaded.
>     The output window may have more diagnostic information

What is the problem? Although the type of `v` involves `flyweight<std::string>`, constructing `v` as an empty vector need not create any flyweight object proper; so, it is perfectly possible that the static initialization of `flyweight<std::string>` happens after the construction of `v`; when this is the case, the static destruction of the associated factory will occur before `v`'s destruction, leaving the vector with dangling flyweights. Again, the solution consists in explicitly forcing the static instantiation of `flyweight<std::string>` before `v` is created. Here, calling the function `flyweight<std::string>::init` is a little cumbersome, so we can resort to the utility type `flyweight<std::string>::initializer` to do that job for us:

>     // equivalent to calling flyweight<std::string>::init()
>     static flyweight<std::string>::initializer  fwinit;
>     static std::vector<flyweight<std::string> > v;

>     int main()
>     {
>       // use v; no dangling flyweights at termination now
>     }

Extending Boost.Flyweight
Boost.Flyweight tutorial
Annex: MPL lambda expressions

Revised Octber 16th 2010

© Copyright 2006-2010 Joaquín M López Muñoz. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)