Boost logo

Boost Users :

From: bill_kempf (williamkempf_at_[hidden])
Date: 2002-03-21 11:10:07


--- In Boost-Users_at_y..., "Philip Ashmore" <philip_ashmore_at_h...> wrote:
> Oops! I didn't know I had to join the group!

It's not a have to kinda thing. I was only suggesting that your
questions/comments could be useful to the community and so would
be "better" in this forum then just in private e-mail. You do have
the choice, and I will respond to personal e-mails :).

>
> Regards,
> Philip Ashmore
> ----- Original Message -----
> From: "Philip Ashmore" <philip_ashmore_at_h...>
> To: "William Kempf" <williamkempf_at_h...>
> Cc: <Boost-Users_at_y...>
> Sent: Wednesday, March 20, 2002 12:29 PM
> Subject: Re: Boost.Threads thread_specific_ptr and more
>
>
> > Hi there.
> >
> > Rather than respond to your points directly, I've written a
document
> > outlining my ideas on how static data could be managed more
clearly. This
> > obviously relates to thread_specific_ptr as instances are global,
hence
> > static, but is quite general and therefore hopefully more useful.

Just for other peoples knowledge the attached document can now be
found in the files section at http://groups.yahoo.com/group/Boost-
Users/files/staticData.doc.

I'm not sure that you fully understand the problem your trying to
solve by the document's text, so just let me make sure we're on the
same page. Your initial example that's supposed to illustrate
something that doesn't work, actually does work in some cases.
Here's some complete code from your example that will compile, link
and run, even using MSVC++ 6 SP 5.

#include <iostream>

class A
{
public:
  A() : val(0) { }
  int val;
};

class B
{
public:
  static A g_a;
};

A B::g_a;

static B g_b;

int main(int argc, char* argv)
{
  std::cout << B::g_a.val << std::endl;
  std::cout << g_b.g_a.val << std::endl;
  return 0;
}

The problem you allude to when you say "the order of construction of
non-trivial static objects is seemingly arbitrary" actually only
applies when the "statics" are defined in different translation units
(which you do mention later in the article, so maybe you do
understand the issue... I just need to make sure we're on the same
page). Section 3.6.2 in the standard defines all of this. This is a
well known "problem" for which there isn't any single solution...
though there is one solution that's often preferred. Your complex
template approach *almost* uses this solution, but not quite.

Your templates define smart pointers that lazily create the object on
the heap the first time they are needed, and delete the object when
the template goes out of scope. There are two problems I see with
this. First, using the heap isn't always a good solution. Second,
this approach doesn't address the issue with the order of destruction
of the objects, which is the inverse problem with the order of
construction.

The more traditional solution doesn't use the heap and should also
address the issue of the order of destruction. All that's needed is
to replace the data with a function!

A& g_a()
{
   static A instance;
   return instance;
}

This takes advantage of the rules for initialization order of local
statics. In fact, the recommended way to use call_once() for globals
makes use of this technique:

A* a = 0;
boost::once_flag once_a = BOOST_ONCE_INIT;
void init_a()
{
   static A instance;
   a = &instance;
}
A& get_a()
{
   boost::call_once(&init_a, once_a);
   return *a;
}

Bill Kempf


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net