Resource Acquisition Is
  Initialization (RAII)
{
    int device;

    if( . . . ) // Some selection criteria
    {
        device = open(. . .);
    } else {
        device = socket(. . .);
        . . .
    }

    close(device);
}
{
    int device;

    if( . . . ) // Some selection criteria
    {
        device = open(. . .);
    } else {
        device = socket(. . .);
        . . .
    }
    // If you return, or throw exception, here then device
    // remains open:

    // if ( . . . ) // close(device) was accidentally forgotten
    //    return;
    close(device);
}
struct DeviceCloser      {

     DeviceCloser()      // Initialization
        : m_device(NULL)
     {}

     ~DeviceCloser()    // Destruction
     {
       close(m_device); // Close the device handle
     }

     int m_device;
};
{
    DeviceCloser dc;
    int &device = dc.m_file;

    if( . . . ) // Some selection criteria
    {
        device = open(. . .);
    } else {
        device = socket(. . .);
        . . .
    }

    // … Whatever happens here, the device will be closed

} // Device closed here
struct DeviceCloser            {

     DeviceCloser(string device_name)               // Initialization
       //: m_device(NULL)
     {
         if( . . . ) // Some selection criteria
         {
             m_device = open(device_name, . . .);
         } else {
             m_device = socket(. . .);
             . . .
         }
     }

     ~DeviceCloser()    // Destruction
     {
       close(m_device); // Close the device handle
     }
     int m_device;
};
{
    string device_name(“Large Hadron Collider”);

    DeviceCloser dc(device_name);

    dc.start();

    // … Whatever happens here, the device will be closed
    // and the world will be saved

} // Device closed here
Object lifecycle




Construction       Acquire


                             Resource




 Destruction       Release
// in the the C language, see."cleanup" variable attribute”
#define RAII_VARIABLE(vartype,varname,initval,dtor) 
    void _dtor_ ## varname (vartype * v) { dtor(*v); } 
    vartype varname __attribute__((cleanup(_dtor_ ##
varname))) = (initval)

// This macro can then be used as follows:

void example_usage() {
  RAII_VARIABLE(FILE*, logfile, fopen("logfile.txt", "w+"),
fclose);
  fputs("hello logfile!", logfile);
}
Typical Uses

• Synchronization primitives
  (Mutex Lock/Unlock)
• File Open/Close
• Memory allocation/deallocation
Things to Remember

• To prevent resource leaks, use RAII objects
  that acquire resources in their constructors
  and release them in their destructors.
• Commonly useful RAII classes are
  shared_ptr,auto_ptr, etc[code] (another
  seminar)
List of references:
• Scott Meyers, Effective C++: 55 Specific Ways
  to Improve Your Programs and Designs
• Stephen C. Dewhurst, C++ Common
  Knowledge: Essential Intermediate
  Programming
• Matthew Wilson, Imperfect C++: Practical
  Solutions for Real-Life Programming

Raii

  • 1.
    Resource Acquisition Is Initialization (RAII)
  • 2.
    { int device; if( . . . ) // Some selection criteria { device = open(. . .); } else { device = socket(. . .); . . . } close(device); }
  • 3.
    { int device; if( . . . ) // Some selection criteria { device = open(. . .); } else { device = socket(. . .); . . . } // If you return, or throw exception, here then device // remains open: // if ( . . . ) // close(device) was accidentally forgotten // return; close(device); }
  • 4.
    struct DeviceCloser { DeviceCloser() // Initialization : m_device(NULL) {} ~DeviceCloser() // Destruction { close(m_device); // Close the device handle } int m_device; };
  • 5.
    { DeviceCloser dc; int &device = dc.m_file; if( . . . ) // Some selection criteria { device = open(. . .); } else { device = socket(. . .); . . . } // … Whatever happens here, the device will be closed } // Device closed here
  • 6.
    struct DeviceCloser { DeviceCloser(string device_name) // Initialization //: m_device(NULL) { if( . . . ) // Some selection criteria { m_device = open(device_name, . . .); } else { m_device = socket(. . .); . . . } } ~DeviceCloser() // Destruction { close(m_device); // Close the device handle } int m_device; };
  • 7.
    { string device_name(“Large Hadron Collider”); DeviceCloser dc(device_name); dc.start(); // … Whatever happens here, the device will be closed // and the world will be saved } // Device closed here
  • 8.
    Object lifecycle Construction Acquire Resource Destruction Release
  • 9.
    // in thethe C language, see."cleanup" variable attribute” #define RAII_VARIABLE(vartype,varname,initval,dtor) void _dtor_ ## varname (vartype * v) { dtor(*v); } vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval) // This macro can then be used as follows: void example_usage() { RAII_VARIABLE(FILE*, logfile, fopen("logfile.txt", "w+"), fclose); fputs("hello logfile!", logfile); }
  • 10.
    Typical Uses • Synchronizationprimitives (Mutex Lock/Unlock) • File Open/Close • Memory allocation/deallocation
  • 11.
    Things to Remember •To prevent resource leaks, use RAII objects that acquire resources in their constructors and release them in their destructors. • Commonly useful RAII classes are shared_ptr,auto_ptr, etc[code] (another seminar)
  • 12.
    List of references: •Scott Meyers, Effective C++: 55 Specific Ways to Improve Your Programs and Designs • Stephen C. Dewhurst, C++ Common Knowledge: Essential Intermediate Programming • Matthew Wilson, Imperfect C++: Practical Solutions for Real-Life Programming