5c2258b203
Summary: Auto scope doxygen fix Test Plan: manual Reviewers: dtomicevic Subscribers: buda Differential Revision: https://memgraph.phacility.com/D26
66 lines
1.6 KiB
C++
66 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include <utility>
|
|
|
|
/**
|
|
* @brief Calls a cleanup function on scope exit
|
|
*
|
|
* consider this example:
|
|
*
|
|
* void hard_worker()
|
|
* {
|
|
* resource.enable();
|
|
* do_stuff(); // throws exception
|
|
* resource.disable();
|
|
* }
|
|
*
|
|
* if do_stuff throws an exception, resource.disable is never called
|
|
* and the app is left in an inconsistent state. ideally, you would like
|
|
* to call resource.disable regardles of the exception being thrown.
|
|
* OnScopeExit makes this possible and very convenient via a 'Auto' macro
|
|
*
|
|
* void hard_worker()
|
|
* {
|
|
* resource.enable();
|
|
* Auto(resource.disable());
|
|
* do_stuff(); // throws exception
|
|
* }
|
|
*
|
|
* now, resource.disable will be called every time it goes out of scope
|
|
* regardless of the exception
|
|
*
|
|
* @tparam F Lambda which holds a wrapper function around the cleanup code
|
|
*/
|
|
template <class F>
|
|
class OnScopeExit
|
|
{
|
|
public:
|
|
OnScopeExit(F& f) : f(f) {}
|
|
|
|
~OnScopeExit()
|
|
{
|
|
// calls the cleanup function
|
|
f();
|
|
}
|
|
|
|
private:
|
|
F& f;
|
|
};
|
|
|
|
#define TOKEN_PASTEx(x, y) x##y
|
|
#define TOKEN_PASTE(x, y) TOKEN_PASTEx(x, y)
|
|
|
|
#define Auto_INTERNAL(Destructor, counter) \
|
|
auto TOKEN_PASTE(auto_func_, counter) = [&]() { Destructor; }; \
|
|
OnScopeExit<decltype(TOKEN_PASTE(auto_func_, counter))> \
|
|
TOKEN_PASTE(auto_, counter)(TOKEN_PASTE(auto_func_, counter));
|
|
|
|
#define Auto(Destructor) Auto_INTERNAL(Destructor, __COUNTER__)
|
|
|
|
// -- example:
|
|
// Auto(f());
|
|
// -- is expended to:
|
|
// auto auto_func_1 = [&]() { f(); };
|
|
// OnScopeExit<decltype(auto_func_1)> auto_1(auto_func_1);
|
|
// -- f() is called at the end of a scope
|