From: Joao Abecasis (jpabecasis_at_[hidden])
Date: 2005-09-08 18:48:45


Anthony Williams wrote:
> Alexander Terekhov <terekhov_at_[hidden]> writes:
>
>
>>Anthony Williams wrote:
>>
>>>However, our once_flag can store a result of a user-defined type, which may
>>>therefore require proper destruction, so that it can notify other processes,
>>>send network packets, write to a file, or whatever; this therefore needs
>>>dealing with somehow before process termination.
>>
>>User would then call _destroy() or _reset() (the later is likely
>>to be called multiple times). I won't tell you "how". Trade secret.
>
>
> Don't be such a tease!
>
> class X
> {
> public
> X()
> {
> acquire_resource();
> }
> void do_something();
> ~X()
> {
> release_resource();
> }
> };
>
> X get_X();
>
> void f()
> {
> static once_flag once;
> call_once(get_X,once).do_something();
> // how do we clean up the X associated with "once", and release it's
> // resource?
> // We can't sensibly call once_destroy() here.
> }

I have written a static_<...> template class that uses boost::call_once
to (I suppose) offer thread-safe initialization of what amounts to
static data. Use case:

void f()
{
     static_<X> x;
}

This seems equal in purpose to what you're now seeking to offer with the
new call_once.

Here's the abbreviated implementation of static_,

     template < ... >
     struct static_
     {
         static_()
         {
             struct constructor
             {
                 static void construct()
                 {
                     new (get_address()) value_type();

                     // Schedule the object for destruction
                     static destructor d;
                 }
             };

             // Ensure constructor is called only once
             boost::call_once(&constructor::construct,
                 constructed_);
         }

     private:
         static pointer get_address()
         {
             return static_cast<pointer>(data_.address());
         }

         struct destructor
         {
             ~destructor()
             {
                 get_address()->~value_type();
             }
         };

         // static storage for object and flag
         static boost::aligned_storage< ... > data_;
         static boost::once_flag constructed_;
     };

I'd like to hear your views on the flaws and shortcomings with this
approach.

Regards,

João