Boost logo

Boost :

From: Pete Becker (petebecker_at_[hidden])
Date: 2002-08-06 08:13:26


At 05:00 PM 8/6/2002 +1000, Andrew J Bromage wrote:
>Is there any interest in something like this?
>
> void call_once(function0<void>& func, once_flag&);

To paraphrase my recollection of Butenhof's discussion: back in the olden
days, before POSIX had static initializers for mutexes, once functions were
essential, so that you could guarantee that a mutex had been initialized
before you used it. That was their primary reason for existing. Once static
initialion of mutexes was added this problem went away, and with it, the
primary need for once functions.

Further, a once function won't ever be more efficient than user-written
code that uses a mutex and a flag, and will often be less efficient. So as
long as you can statically initialize a mutex, once functions are "merely"
a convenience.

Now back to my own opinion, based on the above.

In C++ we have automatic initialization of static objects, so there is even
less need for once functions. Making them more powerful doesn't seem
productive, since they will rarely be needed in well-designed code.

The one place where they seem useful is in lazy initialization. But rather
than thinking in C terms and prolonging the life of the inside-out
interface to once functions, think C++ and design a more suitable solution:

class lazy_initializer
{
public:
         lazy_initializer();
         ~lazy_initializer();
         void init_once();
private:
         virtual void do_init() = 0;
};

A derived class can contain whatever data it needs, suitably initialized in
its constructor. Lazy initialization of the expensive parts of the derived
class is done in the override of do_init. Code that needs this
initialization should first call init_once, which calls do_init the first
time it's called.

I haven't shown the implementation because it's more important at the
moment to focus on the concept, without getting bogged down in
implementation details.

class buffer : public lazy_initializer
{
public:
         buffer(size_t s);
         ~buffer();
         char *get();
private:
         char *buf;
         size_t sz;
         void do_init();
};

buffer::buffer(size_t s) : sz(s), buf(0)
         {
         }

buffer::~buffer()
         {
         delete [] buf;
         }

char *buffer::get()
         {
         init_once();
         return buf;
         }

void buffer::do_init()
         {
         buf = new char[sz];
         }

        -- Pete

Dinkumware, Ltd.
"Genuine Software"


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk