// -*- mode: c++ -*-
#ifndef __IMP_GUARD__26964644
#define __IMP_GUARD__26964644

namespace imp {
  /**
   * \brief A generic RAII guard
   *
   * \tparam Deleter A Callable type that will be called in {\ref Guard::~Guard}
   *
   * A generic RAII guard that calls the deleter on the Guard going out of scope
   */
  template <class Deleter>
  class Guard {
      bool mExecuted = false;
      Deleter mDeleter;

  public:
      Guard(Deleter&& deleter):
          mDeleter(std::move_if_noexcept(deleter)) {}

      ~Guard()
      {
          if (!mExecuted)
              mDeleter();
      }

       /*!
       * Execute the deleter deliberately prior to the Guard object going out of scope
       */
      void execute()
      {
          if (!mExecuted) {
              mDeleter();
              mExecuted = true;
          }
      }

      /*!
       * Prevent deleter being executed on destruction
       */
      void release()
      { mExecuted = true; }
  };

  template <class Deleter>
  inline Guard<Deleter> make_guard(Deleter&& deleter)
  { return { std::forward<Deleter>(deleter) }; }
}

#endif //__IMP_GUARD__26964644
