Atomic: A C++ Library for Transactional Programming

By Calum Grant

Overview

Transactional programming is about defining units of work called transactions that either succeed completely, or can be rolled back (undone) completely.

The purpose of transactions is to make it easy to recover from errors. If an exception is thrown, the transaction is rolled back. Transactions make error-recovery trivial since the programmer does not need to worry about leaving the program in an inconsistent state.

The Atomic library declares transactions using RAII. For example:

atomic::vector<std::string> list1, list2;

void f(std::string const & x)
{
    atomic::transaction tr;
    list1.push_back(x);
    list2.push_back(x);
    tr.commit();
}

If an exception is thrown, the transaction rolls back list1 and list2, and the function has no side-effects.

Transactions can be nested, so even if an inner transaction succeeds, an outer transaction can roll it back.

The Atomic library implements a variety of classes that can be rolled back to any point in their past. These are: value, list, vector, map, multimap, set, multiset, shared_ptr and weak_ptr. The atomic containers are approximately 10% slower than the std containers.

Transactions give a strong guarantee of exception-safety, without needing to analyse a program in minute detail for exceptions.

For further reading see GotW #61: ACID Programming.