1
0
Fork 0
arangodb/lib/Basics/ScopeGuard.h

105 lines
3.2 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_BASICS_SCOPE_GUARD_H
#define ARANGODB_BASICS_SCOPE_GUARD_H 1
// must not be included from somewhere except from Common.h
// we will fix this later
#ifndef TRI_WITHIN_COMMON
#error use <Basics/Common.h>
#endif
#include <type_traits>
#define SCOPE_GUARD_TOKEN_PASTE_WRAPPED(x, y) x##y
#define SCOPE_GUARD_TOKEN_PASTE(x, y) SCOPE_GUARD_TOKEN_PASTE_WRAPPED(x, y)
// helper macros for creating a ScopeGuard using a user-defined lambda or functor
#define TRI_DEFER_FUNC_INTERNAL(func, objname) auto objname = arangodb::scopeGuard(func);
#define TRI_DEFER_FUNC(func) TRI_DEFER_FUNC_INTERNAL(func, SCOPE_GUARD_TOKEN_PASTE(autoScopeGuardObj, __LINE__))
// helper macros for creating a capture-all ScopeGuard
#define TRI_DEFER_BLOCK_INTERNAL(func, objname) auto objname = arangodb::scopeGuard([&] { func; });
#define TRI_DEFER_BLOCK(func) TRI_DEFER_BLOCK_INTERNAL(func, SCOPE_GUARD_TOKEN_PASTE(autoScopeGuardObj, __LINE__))
// TRI_DEFER currently just maps to TRI_DEFER_BLOCK
// we will fix this later
#define TRI_DEFER(func) TRI_DEFER_BLOCK(func)
namespace arangodb {
template<class T>
class ScopeGuard {
public:
// prevent empty construction
ScopeGuard() = delete;
// prevent copying
ScopeGuard(ScopeGuard const&) = delete;
ScopeGuard& operator=(ScopeGuard const&) = delete;
ScopeGuard(T&& func) noexcept
: _func(std::move(func)),
_active(true) {}
ScopeGuard(ScopeGuard&& other) noexcept(std::is_nothrow_move_constructible<T>::value)
: _func(std::move_if_noexcept(other._func)),
_active(other._active) {
other.cancel();
}
// the actual work is done in the ScopeGuard's destructor
~ScopeGuard() noexcept {
if (active()) {
try {
// call the scope exit function
_func();
} catch (...) {
// we must not throw in destructors
}
}
}
// make the guard not trigger the function at scope exit
void cancel() noexcept { _active = false; }
// whether or not the guard will trigger the function at scope exit
bool active() const noexcept { return _active; }
private:
// the function to be executed at scope exit
T _func;
// whether or not the guard will trigger the function at scope exit
bool _active;
};
template<class T> ScopeGuard<T> scopeGuard(T&& f) {
return ScopeGuard<T>(std::move(f));
}
} // namespace
#endif