$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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"