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
.