21
“RESOURCE ACQUISITION IS INITIALIZATIONAndrey Dankevich April, 2013 4/18/2013 1

RAII and ScopeGuard

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: RAII and ScopeGuard

“RESOURCE ACQUISITION IS INITIALIZATION”

Andrey Dankevich April, 2013

4/18/2013 1

Page 2: RAII and ScopeGuard

• Memory • Handles • Locks • Sockets • Threads • Temp files • …

4/18/2013 2

What is a resource?

Page 3: RAII and ScopeGuard

4/18/2013 3

What is a resource?

“Resource” is anything that follows this pattern!

Page 4: RAII and ScopeGuard

4/18/2013 4

So what’s the problem?

Real code might have different points at which the resource should be released:

Page 5: RAII and ScopeGuard

void f(const char* p) { FILE* f = fopen(p,"r"); // acquire // use f fclose(f); // release }

4/18/2013 5

Resources and errors

Page 6: RAII and ScopeGuard

// naïve fix: void f(const char* p) {

FILE* f = 0; try {

f = fopen(p, "r"); // use f

} catch (…) { // handle every exception

if (f) fclose(f); throw;

} if (f) fclose(f);

}

4/18/2013 6

Resources and errors

Is this code really safer?

Page 7: RAII and ScopeGuard

// use an object to represent a resource

class File_handle { // belongs in some support library FILE* p; public:

File_handle(const char* pp, const char* r) { p = fopen(pp,r); if (p==0) throw File_error(pp,r); } File_handle(const string& s, const char* r) { p = fopen(s.c_str(),r); if (p==0) throw File_error(s,r); } ~File_handle() { fclose(p); }

}; 4/18/2013 7

RAII

Page 8: RAII and ScopeGuard

In C++ the only code that can be guaranteed to be executed after an exception is thrown are the destructors of objects residing on the stack.

Deterministic Exception-safe

void f() {

A a; throw 42;

} // ~A() is called

4/18/2013 8

Stack lifetime semantics

Page 9: RAII and ScopeGuard

LIVE DEMO

http://ideone.com/enqHPr

4/18/2013 9

Page 10: RAII and ScopeGuard

• Java, C# and Python, support various forms of the dispose pattern to simplify cleanup of resources.

• Custom classes in C# and Java have to explicitly implement the Dispose method.

4/18/2013 10

.NET

using (Font font1 = new Font("Arial", 10.0f)) { byte charset = font1.GdiCharSet; }

Page 11: RAII and ScopeGuard

• Java, C# and Python, support various forms of the dispose pattern to simplify cleanup of resources.

• Custom classes in C# and Java have to explicitly implement the Dispose method.

4/18/2013 11

.NET

{ Font font1 = new Font("Arial", 10.0f); try { byte charset = font1.GdiCharSet; } finally { if (font1 != null) ((IDisposable)font1).Dispose(); } }

Page 12: RAII and ScopeGuard

Working with temp files:

class TempFile : IDisposable { public TempFile(string filePath) { if (String.IsNullOrWhiteSpace(filePath)) throw new ArgumentNullException(); this.Path = filePath; } public string Path { get; private set; } public void Dispose() { if (!String.IsNullOrWhiteSpace(this.Path)) { try { System.IO.File.Delete(this.Path); } catch { } this.Path = null; } } } 4/18/2013 12

.NET - Examples

Page 13: RAII and ScopeGuard

4/18/2013 13

.NET - Examples

Working with temp settings values: Check the implementation for AutoCAD settings

http://www.theswamp.org/index.php?topic=31897.msg474083#msg474083

Use this approach if you need to temporarily change the settings in application.

Page 14: RAII and ScopeGuard

Many STL classes use RAII: • std::basic_ifstream, std::basic_ofstream and

std::basic_fstream will close the file stream on

destruction if close() hasn’t yet been called.

• smart pointer classes std::unique_ptr for single-owned

objects and std::shared_ptr for objects with shared

ownership.

• Memory: std::string, std::vector…

• Locks: std::unique_lock

4/18/2013 14

Back to C++

Page 15: RAII and ScopeGuard

SCOPE GUARD

4/18/2013 15

Page 16: RAII and ScopeGuard

• Original article: http://drdobbs.com/184403758

• Improved implementation: http://www.zete.org/people/jlehrer/scopeguard.html

• C++ and Beyond 2012: Andrei Alexandrescu - Systematic

Error Handling in C++:

video (from 01:05:11) - http://j.mp/XAbBWe

slides ( from slide #31) - http://sdrv.ms/RXjNPR

• C++11 implementation: https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h

4/18/2013

SCOPE GUARD

Page 17: RAII and ScopeGuard

Real-world example with PTC Creo API:

• Resource type: ProReference In fact it’s mere a typedef void* ProReference;

• Resource acquire: // Gets and allocates a ProReference containing a // representation for this selection. ProError ProSelectionToReference (ProSelection selection, ProReference* reference);

• Resource release: ProError ProReferenceFree (ProReference reference);

4/18/2013 17

SCOPE GUARD vs unique_ptr

Page 18: RAII and ScopeGuard

Using std::unique_ptr<>: auto ref_allocator = []( const ProSelection selection ) -> ProReference { ProReference reference; ProError status = ProSelectionToReference(selection, &reference); return reference; }; auto ref_deleter = [](ProReference& ref) { ProReferenceFree (ref); }; std::unique_ptr <std::remove_pointer<ProReference>::type, decltype(ref_deleter)> fixed_surf_ref ( ref_allocator(sels[0]), ref_deleter ); // ref_deleter is guaranteed to be called in destructor

4/18/2013 18

SCOPE GUARD vs unique_ptr

Page 19: RAII and ScopeGuard

Using ScopeGuard: ProReference fixed_surf_ref = nullptr; status = ProSelectionToReference ( sels[0], &fixed_surf_ref ); SCOPE_EXIT { ProReferenceFree ( fixed_surf_ref ); };

4/18/2013 19

SCOPE GUARD vs unique_ptr

I LOVE IT!!!

Page 20: RAII and ScopeGuard

http://j.mp/FridayTechTalks

4/18/2013 20

Page 21: RAII and ScopeGuard

Questions?

4/18/2013 21