Skip to content

Instantly share code, notes, and snippets.

@SeanCline
Last active June 10, 2016 12:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SeanCline/de2669b320743f42bed192b16ee14ba9 to your computer and use it in GitHub Desktop.
Save SeanCline/de2669b320743f42bed192b16ee14ba9 to your computer and use it in GitHub Desktop.
transacted<T> - Stores a copy of a type and writes the result back to the original unless an exception is thrown.
#include "transacted.h"
#include <iostream>
#include <stdexcept>
using namespace std;
int x = 1;
long y = 2;
float z = 3;
void doSomething()
{
TRANSACTED(x, y, z);
++x; ++y; ++z;
}
void doSomethingButThrow()
{
TRANSACTED(x, y, z);
++x; ++y; ++z;
throw runtime_error("Transaction not applied!");
}
int main()
{
cout << x << y << z << "\n";
doSomething();
cout << x << y << z << "\n";
try {
doSomethingButThrow();
} catch (const exception& ex) {
cout << ex.what() << "\n";
}
cout << x << y << z << "\n";
}
#pragma once
#include <exception>
template <typename T>
class transacted {
public:
explicit transacted(T& t)
: copy_(t), original_(t), uncaughtExceptions_(std::uncaught_exceptions())
{}
~transacted()
{
if (uncaughtExceptions_ == std::uncaught_exceptions())
commit();
}
void commit() const
{
original_ = copy_;
}
operator T&() { return copy_; }
operator const T&() const { return copy_; }
T& get() { return copy_; }
const T& get() const { return copy_; }
private:
T copy_;
T& original_;
int uncaughtExceptions_;
};
#define TRANSACTED1(VAR1) auto& transacted_ref_ ## VAR1 = VAR1; transacted<decltype(VAR1)> VAR1{transacted_ref_ ## VAR1};
#define TRANSACTED2(VAR1, VAR2) TRANSACTED1(VAR1) TRANSACTED1(VAR2)
#define TRANSACTED3(VAR1, VAR2, VAR3) TRANSACTED2(VAR1, VAR2) TRANSACTED1(VAR3)
#define TRANSACTED4(VAR1, VAR2, VAR3, VAR4) TRANSACTED2(VAR1, VAR2) TRANSACTED2(VAR3, VAR4)
#define TRANSACTED5(VAR1, VAR2, VAR3, VAR4, VAR5) TRANSACTED4(VAR1, VAR2, VAR3, VAR4) TRANSACTED1(VAR5)
#define EXPAND(x) x
#define GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define VA_NUM_ARGS(...) EXPAND(GET_NTH_ARG(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
#define CONCATENATE(_1, _2) CONCATENATE_IMPL(_1, _2)
#define CONCATENATE_IMPL(_1, _2) _1##_2
#define TRANSACTEDN(N, ...) CONCATENATE(TRANSACTED, N)(__VA_ARGS__)
#define TRANSACTED(...) TRANSACTEDN(VA_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment