RAII and ScopeGuard

5,369 views

Published on

Published in: Technology, Education
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,369
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
35
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

RAII and ScopeGuard

  1. 1. “RESOURCE ACQUISITION IS INITIALIZATION” Andrey Dankevich April, 20131 4/18/2013
  2. 2. What is a resource? • Memory • Handles • Locks • Sockets • Threads • Temp files • …2 4/18/2013
  3. 3. What is a resource? “Resource” is anything that follows this pattern!3 4/18/2013
  4. 4. So what’s the problem? Real code might have different points at which the resource should be released:4 4/18/2013
  5. 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. 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. 7. RAII// use an object to represent a resourceclass 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. 8. Stack lifetime semanticsIn C++ the only code that can be guaranteed to beexecuted after an exception is thrown are the destructorsof objects residing on the stack.  Deterministic  Exception-safe void f() { A a; throw 42; } // ~A() is called8 4/18/2013
  9. 9. LIVE DEMO http://ideone.com/enqHPr9 4/18/2013
  10. 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. 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. 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. 13. .NET - ExamplesWorking with temp settings values: Check the implementation for AutoCAD settings http://www.theswamp.org/index.php?topic=31897.msg474083#msg474083Use this approach if you need to temporarily change the settings inapplication.13 4/18/2013
  14. 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_lock14 4/18/2013
  15. 15. SCOPE GUARD15 4/18/2013
  16. 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. 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. 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 destructor18 4/18/2013
  19. 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
  20. 20. http://j.mp/FridayTechTalks20 4/18/2013
  21. 21. Questions?21 4/18/2013

×