diff --git a/ortools/base/cleanup.h b/ortools/base/cleanup.h index f7919b0571..df0680184a 100644 --- a/ortools/base/cleanup.h +++ b/ortools/base/cleanup.h @@ -16,22 +16,109 @@ #include +#include "absl/base/macros.h" + namespace absl { -template -class Cleanup { +namespace cleanup_internal { + +template +class Storage { + using InvokeT = absl::base_internal::InvokeT; + static_assert(std::is_same::value, ""); + static_assert(!std::is_reference::value, ""); + public: - template - explicit Cleanup(G&& f) : f_(std::forward(f)) {} - ~Cleanup() { f_(); } + Storage() : contains_callback_(false), callback_() {} + + Storage(Storage&& other_storage) + : contains_callback_(other_storage.ContainsCallback()), + callback_(other_storage.ReleaseCallback()) {} + + template + explicit Storage(TheCallback&& the_callback) + : contains_callback_(true), + callback_(std::forward(the_callback)) {} + + template + Storage(Storage&& other_storage) // NOLINT + : contains_callback_(other_storage.ContainsCallback()), + callback_(other_storage.ReleaseCallback()) {} + + Storage& operator=(Storage&& other_storage) { + if (ContainsCallback()) std::move(callback_)(); + contains_callback_ = other_storage.ContainsCallback(); + callback_ = other_storage.ReleaseCallback(); + return *this; + } + + bool ContainsCallback() const { return contains_callback_; } + + Callback ReleaseCallback() { + contains_callback_ = false; + return std::move(callback_); + } + + void CancelCallback() { contains_callback_ = false; } + + void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS { + CancelCallback(); + + std::move(callback_)(); + } private: - F f_; + bool contains_callback_; + Callback callback_; }; -template -Cleanup MakeCleanup(F&& f) { - return Cleanup(std::forward(f)); +struct AccessStorage { + template