Boost logo

Boost :

Subject: Re: [boost] very simple implementation of Andrei Alexandrescu's ScopeGuard idiom
From: Sergey Radionov (rsatom_at_[hidden])
Date: 2012-09-03 22:56:24


2012/9/4 Lorenzo Caminiti <lorcaminiti_at_[hidden]>:
> On Mon, Sep 3, 2012 at 6:37 PM, Sergey Radionov <rsatom_at_[hidden]> wrote:
>> 2012/9/4 Lorenzo Caminiti <lorcaminiti_at_[hidden]>:
>>> On Mon, Sep 3, 2012 at 10:28 AM, Stewart, Robert <Robert.Stewart_at_[hidden]> wrote:
>>>> Sergey Radionov wrote:
>>>>>
>>>>> https://github.com/RSATom/finally_execute/blob/master/finally
>>>>> _execute.h
>>>>>
>>>>> based on http://www.drdobbs.com/cpp/generic-change-the-way-
>>>>> you-write-excepti/184403758?pgno=2
>>>>>
>>>>> I know about http://sourceforge.net/projects/loki-lib/ but
>>>>> with boost::bind this can be much simpler:
>>>>> https://github.com/RSATom/finally_execute/blob/master/README
>>>>>
>>>>> I've used this in many of my projects, and found it very
>>>>> usefull....
>>>>>
>>>>> don't understand, why this simple solution does not
>>>>> contributed already to Boost by someone else... :)
>>>>
>>>> I created a version, too, but the usage is much simpler.
>>>>
>>>> Given the following:
>>>>
>>>> FILE * const file(fopen("test", "r"));
>>>> if (file)
>>>> {
>>>> // A
>>>> }
>>>>
>>>> Your usage, at A, is:
>>>>
>>>> finally_execute _(make_fin_exec(boost::bind(fclose, file)));
>>>>
>>>> Mine is:
>>>>
>>>> scope_guard _(fclose, file);
>>>>
>>>> As you can see, a little more complication in the component makes
>>>> usage much simpler.
>>>
>>> Boost.ScopeExit allows you to "execute *arbitrary* code when the
>>> enclosing scope exits". I don't see how you execute arbitrary code
>>> with the above.
>> Yep, but in 90% of cases I just need call one function on scope exit,
>
> OK if that's what you need but that's not the problem that ScopeExit
> is trying to solve to "call a function on scope exit".
>
>> and in this case ScopeExit will be too cumbersome.
>> little example:
>>
>> void foo()
>> {
>> FILE* f1 = fopen( "file1.bin", "rb");
>> if( !f1 ) return;
>> finally_execute close_file1 = make_fin_exec( boost::bind(fclose, f1) );
>>
>> FILE* f2 = fopen( "file2.bin", "rb");
>> if( !f2 ) return;
>> finally_execute close_file1 = make_fin_exec( boost::bind(fclose, f4) );
>>
>> FILE* f3 = fopen( "file3.bin", "rb");
>> if( !f3 ) return;
>> finally_execute close_file1 = make_fin_exec( boost::bind(fclose, f4) );
>>
>> FILE* f4 = fopen( "file4.bin", "rb");
>> if( !f4 ) return;
>> finally_execute close_file1 = make_fin_exec( boost::bind(fclose, f4) );
>> }
>>
>> how it will look with ScopeExit?
>
> If you are willing to use macros (as ScopeExit does), maybe something like this:
>
> #define EXIT_CLOSE(f) \
> BOOST_SCOPE_EXIT(&f) { \
> fclose(f); \
> } BOOST_SCOPE_EXIT_END
>
> void foo()
> {
> FILE* f1 = fopen( "file1.bin", "rb");
> if( !f1 ) return;
> EXIT_CLOSE(f1)
>
> FILE* f2 = fopen( "file2.bin", "rb");
> if( !f2 ) return;
> EXIT_CLOSE(f2)
>
> FILE* f3 = fopen( "file3.bin", "rb");
> if( !f3 ) return;
> EXIT_CLOSE(f3)
>
> FILE* f4 = fopen( "file4.bin", "rb");
> if( !f4 ) return;
> EXIT_CLOSE(f4)
> }
>
>> what will be more clear?
>
> That depends on your application domain, maybe your developer's tema,
> etc so it's your call.
ok, let's use example more closer to real life:

bool MoveFile(const char* from, const char* to)
{

   FILE* f1 = fopen( from, "rb");
   if( !f1 ) return false;
   finally_execute close_file1 = make_fin_exec( boost::bind(fclose, f1) );

   FILE* f2 = fopen( to, "wb");
   if( !f2 ) return false;
   finally_execute close_file2 = make_fin_exec( boost::bind(fclose, f2) );

   finally_execute remove_file1 = make_fin_exec( boost::bind(remove, from) );
   finally_execute remove_file2 = make_fin_exec( boost::bind(remove, to) );

   /*do real move*/

   if( was_error ) {
      remove_file1.dismiss();
      return false;
   }
   else {
      remove_file2.dismiss();
      return true;
   }

}


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