template<class T, class Relinquish, class FlagType = bool, FlagType InvalidVal = std::is_lvalue_reference<T>::value, class = typename std::enable_if< !std::is_same<FlagType, bool>::value && (std::is_same<FlagType, bool>::value || std::is_same<FlagType, T>::value) && std::is_trivially_default_constructible<Relinquish>::value >::type>
class taco::ResourceGuard< T, Relinquish, FlagType, InvalidVal, class >
ResourceGuard is used for automatically relinquishes some resource when it goes out of scope.
It is similar to std::unique_ptr for dynamic allocated memory, but it allows one to enable RAII idiom on other resources such as buffer frames.
The resource is denoted as a T typed value, (usually an integral or a pointer), and it may be reclaimed by calling the Relinquish::operator(). Some constraints apply: 1) T may not be a boolean value; 2) Relinquish must be trivially constrictible. The relinquish functor is not called if the stored value is an invalid value (see below).
The third type parameter FlagType and the fourth value parameter InvalidVal are used for denoting an invalid value. FlagType must be one of the following:
FlagType: there is a special sentinel value that serves as the invalid value
bool with InvalidVal == false: we store an additional boolean flag (default for non-lvalue-refence T)
bool with InvalidVal == true: the value is always (default for lvalue-reference T). (It is a bit confusing to reuse FlagType == bool for this specialization, but we can't set it to void as we need to use a conditional type as the type of InvalidVal which is N/A until C++20).
There is an implicit conversion from \t ResourceGuard<T, ...> to \t T so that it may be used in place of \t T in many places. Caution: be careful with double "free" if you directly call the relinquish function instead of ResourceGuard::reset() before it goes out of scope, unless the relinquish function specifically consider for that (e.g., BufferManager::UnpinPage()).
Another useful function is ResourceGuard::Release(), which does not relinquish the resource. Rather it transfers the resource back to the caller by setting ResourceGuard to an invalid value and will not invoke the relinquish functor upon destruction. This is useful when the caller wants to transfer the ownership of the underlying resource beyond the scope where the ResourceGuard is defined (e.g., passing a buffer id stored in ScopedBufferId into a function that will unpin it from inside).
Note: always prefer existing C++ standard library guard or type alias in specific components. E.g., use std::unique_ptr for memory resource; use taco::MutexGuard for std::mutex; use taco::ScopedBufferId in stoarge/BufferManager.h.
The main template implements the class when FlagType is T.