2. What is a resource?
• Memory
• Handles
• Locks
• Sockets
• Threads
• Temp files
• …
2 4/18/2013
3. What is a resource?
“Resource” is anything that follows this pattern!
3 4/18/2013
4. So what’s the problem?
Real code might have different points at which
the resource should be released:
4 4/18/2013
5. Resources and errors
void f(const char* p)
{
FILE* f = fopen(p,"r"); // acquire
// use f
fclose(f); // release
}
5 4/18/2013
6. Resources and errors
// naïve fix:
void f(const char* p)
{ Is this code really
FILE* f = 0;
try {
safer?
f = fopen(p, "r");
// use f
}
catch (…) { // handle every exception
if (f) fclose(f);
throw;
}
if (f) fclose(f);
}
6 4/18/2013
7. RAII
// 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); }
};
7 4/18/2013
8. Stack lifetime semantics
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
8 4/18/2013
10. .NET
• 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.
using (Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
10 4/18/2013
11. .NET
• 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.
{
Font font1 = new Font("Arial", 10.0f);
try {
byte charset = font1.GdiCharSet;
}
finally {
if (font1 != null)
((IDisposable)font1).Dispose();
}
11 } 4/18/2013
12. .NET - Examples
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;
}
}
12 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.
13 4/18/2013
14. Back to C++
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
14 4/18/2013
16. SCOPE GUARD
• 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
17. SCOPE GUARD vs unique_ptr
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);
17 4/18/2013
18. SCOPE GUARD vs unique_ptr
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
18 4/18/2013
19. SCOPE GUARD vs unique_ptr
Using ScopeGuard:
ProReference fixed_surf_ref = nullptr;
status = ProSelectionToReference ( sels[0], &fixed_surf_ref );
SCOPE_EXIT { ProReferenceFree ( fixed_surf_ref ); };
I LOVE IT!!!
19 4/18/2013