Category Archives: C++ - Page 2

C++ - Resource Acquisition Is Initialization

Resource Acquisition Is Initialization

In the previous article we presented a simple timer class that initializes its internal clock in the constructor and computes the elapsed time in the destructor.

In fact, initializing a resource in a constructor and discarding it in a destructor is a common idiom in C++ called Resource Acquisition Is Initialization (RAII).
This is a great technique when dealing with exception handling: for example let's say at the beginning of a function you allocate 10 blocks of memory, open 2 files and acquire a lock. Of course you are really tidy so you properly free the allocated memory, close the files and release the lock at the end of the function.

However if an exception is raised in the middle of your code, you are in deep trouble: your program leaks memory, file descriptors are still opened and the lock is not released...
When leaving a block (even when an exception is raised), all variables allocated on the stack (i.e. local variables) are destroyed, this process is called stack unwinding.

Even if you are not concerned with exceptions, by using the RAII idiom you can write simpler code and there is no risk you accidentally forget to release a lock !
For example, using RAII with a lock:

// Before critical section
{ // Critical section !
  Lock lock(mutex); // Construct Lock object and acquire mutex.
  // Do some super critical stuff
  ...
  // End of scope: variable lock is destroyed and the mutex is released automatically.
}
// After critical section

auto_ptr

You can also use RAII to handle files or you can use it with raw pointers using the C++ std::auto_ptr class. When the variable reaches end of scope, the destructor automatically calls delete on the pointer. Using operator * we can manipulate an auto_ptr just like a pointer of the underlying type:

{                                                                                                                                                                                                                
  std::auto_ptr<int> p(new int);                                                                                                                                                                                 
  *p = 42;                                                                                                                                                                                                       
  std::cout << *p << std::endl;
  // Allocated memory is released.                                                                                                                                                                             
}

RAII in C

Using gcc variable attributes you can use the RAII idiom in C!
We use the cleanup attribute:

cleanup (cleanup_function)
The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.

Wikipedia presents an example on how to automatically call fclose() on a file descriptor using the cleanup attribute:

#define RAII_VARIABLE(vartype,varname,initval,dtor) \
    void _dtor_ ## varname (vartype * v) { dtor(*v); } \
    vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
 
void example_usage() {
  RAII_VARIABLE(FILE*, logfile, fopen("logfile.txt", "w+"), fclose);
  fputs("hello logfile!", logfile);
}

C++ - Timer Class

Timer Class

In C++ we often need to measure execution time of a small block or function call.
There are several ways to do this in C++, and it is a real pain to come up with both a portable and accurate version.
Using standard C++ only we can write a simple timer class in a few lines only using std::clock(). This function returns the number of clock ticks elapsed since the program was launched. Unfortunately, on some systems the precision of this function is terrible.

class Timer
{
public:
  Timer(const std::string& name)
    : name_ (name),
      start_ (std::clock())
    {
    }
  ~Timer()
    {
      double elapsed = (double(std::clock() - start_) / double(CLOCKS_PER_SEC));
      std::cout << name_ << ": " << int(elapsed * 1000) << "ms" << std::endl;
    }
private:
  std::string name_;
  std::clock_t start_;
};                                                                                                                                                                                                               
 
#define TIMER(name) Timer timer__(name);

An instance of the Timer class is created by providing a name. The constructor initializes the timer by using std::clock(). When the object is destroyed we compute the elapsed time and print it on standard output. We also define a macro TIMER(name) for convenience.

Usage

As the timer is initialized in the constructor and terminated in the destructor, we need to isolate the part of the code we want to measure in a block. When the end of the block is reached, we exit the scope of the timer variable and the destructor is called.
For example:

  int i = ...;
  for (...)
    ...
 
  {
    TIMER("Huge Loop"); // initialize timer
    for (...)
      ...
    // timer variable is destroyed: print elapsed time.
  }

The output can be something like this: Huge Loop: 352ms

User time VS Wall time

Good to know: by using std::clock() (instead of date-based methods) we measure user time, that is to say time actually spent by the CPU for the execution of the current program. If the process is put to sleep for a long time, we won't notice any change. For example the following code:

{
  TIMER("sleep");
  sleep(2); // go to sleep for 2s
}

should print this: sleep: 0ms.
If wall clock time was measured we would have approximately 2000ms here.