Transactional Values
Any C++ class can be made transactional. The atomic::value class template holds a single value that can be rolled back to any previous value.
atomic::value<std::string> name = "bill"; { atomic::transaction t1; name = "tom"; assert(*name == "tom"); { atomic::transaction t2; name = "fred"; assert(*name == "fred"); t2.commit(); } assert(*name == "fred"); // Committed by t2 } assert(*name == "bill"); // Rolled back by t1
The stored object is const, so that it cannot be accidentally modified in a way that cannot be rolled back by a transaction. Previous values are not destroyed until the end of the transaction, in case they need to be reincarnated.
Transactional Pointers
The Atomic Library provides shared pointers and weak pointers that are similar to the TR1 smart pointers (www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf). These pointers keep a counter of the number of pointers to the object. When the count reaches zero, the object can be deleted.
These pointers do not destroy the pointee object until the end of the transaction in case the pointer needs to be rolled back, but the reference count (q.expired(), for example) behaves as if the object is destroyed. For instance:
atomic::shared_ptr<int> p(new int(1)); atomic::weak_ptr<int> q(p); { atomic::transaction tr; p.reset(new int(2)); assert(q.expired()); assert(*p == 2); } assert(*p == 1); // Rolled back by tr assert(!q.expired()); // Rolled back by tr
If compatibility with std::tr1::shared_ptr is required, then a suitable approach would be atomic::value<std::tr1::shared_ptr<> >.