“RESOURCE ACQUISITION
       IS INITIALIZATION”

                      Andrey Dankevich
                      April, 2013


1                            4/18/2013
What is a resource?

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



2                                          4/18/2013
What is a resource?




    “Resource” is anything that follows this pattern!

3                                             4/18/2013
So what’s the problem?
    Real code might have different points at which
    the resource should be released:




4                                           4/18/2013
Resources and errors


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




5                                         4/18/2013
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
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
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
LIVE DEMO

    http://ideone.com/enqHPr



9                              4/18/2013
.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
.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
.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
      }
.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
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
SCOPE GUARD



15                 4/18/2013
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
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
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
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
http://j.mp/FridayTechTalks



20                           4/18/2013
Questions?




21                4/18/2013

RAII and ScopeGuard

  • 1.
    “RESOURCE ACQUISITION IS INITIALIZATION” Andrey Dankevich April, 2013 1 4/18/2013
  • 2.
    What is aresource? • Memory • Handles • Locks • Sockets • Threads • Temp files • … 2 4/18/2013
  • 3.
    What is aresource? “Resource” is anything that follows this pattern! 3 4/18/2013
  • 4.
    So what’s theproblem? 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 anobject 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 InC++ 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
  • 9.
    LIVE DEMO http://ideone.com/enqHPr 9 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 Workingwith 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++ ManySTL 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
  • 15.
    SCOPE GUARD 15 4/18/2013
  • 16.
    SCOPE GUARD • Originalarticle: 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 vsunique_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 vsunique_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 vsunique_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.
  • 21.
    Questions? 21 4/18/2013