#ifndef SCOPEGUARD_H
#define SCOPEGUARD_H

#include <utility>

/** \brief Template class for executing code at scope exit.
 *
 * By default the object will be an active mode and execute the function
 * passed to the constructor when the object is destructed. You can however
 * cancel this action by calling dismiss().
 *
 * There is a clever macro that allows you to write something like
 * SCOPE_EXIT { foo(); };
 */
template<class Fun>
class ScopeGuard {
	Fun f_;
	bool active_;
public:
	ScopeGuard(Fun f)
		: f_(std::move(f))
		, active_(true) {
	}

	~ScopeGuard() { if(active_) f_(); }

	void dismiss() { active_=false; }

	ScopeGuard() = delete;
	ScopeGuard(const ScopeGuard&) =	delete;
	ScopeGuard&	operator=(const	ScopeGuard&) = delete;
	ScopeGuard(ScopeGuard&& rhs)
		: f_(std::move(rhs.f_))
		, active_(rhs.active_)
	{
		rhs.dismiss();
	}
};

template<class Fun>
ScopeGuard<Fun> scopeGuard(Fun f)
{
	return ScopeGuard<Fun>(std::move(f));
}

namespace ScopeGuard_detail {

	enum class ScopeGuardOnExit {};

	template<typename Fun>
	ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
		return ScopeGuard<Fun>(std::forward<Fun>(fn));
	}

}

#define CONCATENATE_IMPL(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(str) \
	CONCATENATE(str,__COUNTER__)
#else
#define ANONYMOUS_VARIABLE(str) \
	CONCATENATE(str,__LINE__)
#endif

#define SCOPE_EXIT \
	auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
		= ::ScopeGuard_detail::ScopeGuardOnExit() + [&]()

#endif // SCOPEGUARD_H
