July 2015 Developer's Poll

Use this forum for polls.

How frequently do you use RAII in the code that you write?

You may select 1 option

 
 
View results

July 2015 Developer's Poll

Postby Damon » Fri Aug 07, 2015 11:04 am

Thanks in advance for your votes!

Cheers,
Damon Chandler
Editor-in-Chief
C++Builder Developer's Journal
http://bcbjournal.com
User avatar
Damon
BCBJ Editor and Admin
BCBJ Editor and Admin
 
Posts: 285
Joined: Wed May 26, 2004 11:25 pm
Location: Stillwater, OK, USA

Re: July 2015 Developer's Poll

Postby djones » Fri Aug 07, 2015 12:01 pm

I use RAII any time it is even remotely possible. If I don't have a ready-made RAII mechanism for something, I will often write one. Over the years, I have built a pretty decent library of predicates for use with boost::shared_ptr<>, and I make extensive use of a modified version of Andrei Alexandrescu's ScopeGuard template classes.

Here's an example of how I use predicates with boost::shared_ptr<>:

class FindCloser
{
public:
void operator()(HANDLE *handle) const
{ if ( *handle != NULL ) { FindClose( *handle ); *handle = NULL; } }
};

// provide exception safety for the Find resource without resorting to try...finally
boost::shared_ptr<HANDLE> shared_find( &hFindFile, FindCloser() );


Here's a ScopeGuard example:

// make sure pSubcategory is deleted at the end of scope, if guard is not dismissed
ScopeGuard guard = MakeGuard( DeleteSubcategoryPtr, pSubcategory );


And while I do most of my work in C# these days, I find ScopeGuard extremely useful in C# too, not so much for memory resources (thanks to garbage collection), but definitely for certain kinds of resources and especially for reciprocal operations. I ported the ScopeGuard class to C# and use it all the time, like this:

using (var transactionGuard = ScopeGuardFactory.MakeGuard(targetDbSqlTransaction.Rollback))
{
// do some work on the DB that might throw an exception

// commit DB changes
targetDbSqlTransaction.Commit();

// dismiss the transaction guard (prevents unintended Rollback)
transactionGuard.Dismiss();
}

Some of my colleagues have noticed my use of ScopeGuard in C# and have asked about it because they have never seen anything like it before, and when I explain it to them, they like it a lot.

Dennis
djones
 
Posts: 6
Joined: Sun Dec 07, 2008 2:35 pm

Re: July 2015 Developer's Poll

Postby Damon » Thu Sep 10, 2015 10:35 am

Great techniques Dennis! Hope you were able to convince some colleagues to adopt the technique or more RAII in general.

Cheers,
Damon Chandler
Editor-in-Chief
C++Builder Developer's Journal
http://bcbjournal.com
User avatar
Damon
BCBJ Editor and Admin
BCBJ Editor and Admin
 
Posts: 285
Joined: Wed May 26, 2004 11:25 pm
Location: Stillwater, OK, USA

Re: July 2015 Developer's Poll

Postby rlebeau » Thu Sep 10, 2015 10:34 pm

djones wrote:Here's an example of how I use predicates with boost::shared_ptr<>


You don't really need a separate FindCloser class with shared_ptr, you can use FindClose() directly as the deleter. And the only thing that the FindCloser class is offering to shared_ptr is automatic assignment of the source variable to NULL. Which, honestly, I wouldn't really bother with in this situation:

Code: Select all
HANDLE hFindFile = FindFirstFile(...);
boost::shared_ptr<void> shared_find( hFindFile, &::FindClose ); // <-- not &hFindFile


Or:

Code: Select all
boost::shared_ptr<void> hFindFile( FindFirstFile(...), &::FindClose );


Consider that the benefit of shared_ptr over unique_ptr (which you would need FindCloser for) is reference-counting across multiple shared_ptr instances (hence its name). Think of what happens if the source variable goes out of scope before all of the shared_ptr instances go out of scope. An invalid variable would be closed and assigned to NULL. Giving the shared_ptr its own copy of the HANDLE is safer.

If you intend to use the HANDLE locally and not pass it around, you should actually be using unique_ptr instead:

Code: Select all
class FindCloser
{
public:
    typedef HANDLE pointer; // <-- add this
    void operator()(HANDLE handle) const // <-- not HANDLE*
    { if ( handle != INVALID_HANDLE_VALUE ) { FindClose( handle ); } }
};


Code: Select all
HANDLE hFindFile = FindFirstFile(...);
boost::unique_ptr<HANDLE, FindCloser> shared_find( hFindFile ); // <-- not &hFindFile


Or:

Code: Select all
boost::unique_ptr<HANDLE, FindCloser> hFindFile( FindFirstFile(...) );
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1544
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Polls

Who is online

Users browsing this forum: No registered users and 1 guest

cron