/* Copyright (C) 2019-2025 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef GDBSUPPORT_SCOPE_EXIT_H
#define GDBSUPPORT_SCOPE_EXIT_H

#include <functional>
#include <type_traits>
#include "gdbsupport/preprocessor.h"

/* scope_exit is a general-purpose scope guard that calls its exit
   function at the end of the current scope.  A scope_exit may be
   canceled by calling the "release" method.  The API is modeled on
   P0052R5 - Generic Scope Guard and RAII Wrapper for the Standard
   Library, which is itself based on Andrej Alexandrescu's
   ScopeGuard/SCOPE_EXIT.

   There are two forms available:

   - The "make_scope_exit" form allows canceling the scope guard.  Use
     it like this:

     auto cleanup = make_scope_exit ( <function, function object, lambda> );
     ...
     cleanup.release (); // cancel

   - If you don't need to cancel the guard, you can use the SCOPE_EXIT
     macro, like this:

     SCOPE_EXIT
       {
	 // any code you like here.
       }

   See also forward_scope_exit.
*/

/* CRTP base class for cancelable scope_exit-like classes.  Implements
   the common call-custom-function-from-dtor functionality.  Classes
   that inherit this implement the on_exit() method, which is called
   from scope_exit_base's dtor.  */

template <typename CRTP>
class scope_exit_base
{
public:
  scope_exit_base () = default;

  ~scope_exit_base ()
  {
    if (!m_released)
      {
	auto *self = static_cast<CRTP *> (this);
	self->on_exit ();
      }
  }

  DISABLE_COPY_AND_ASSIGN (scope_exit_base);

  /* If this is called, then the wrapped function will not be called
     on destruction.  */
  void release () noexcept
  {
    m_released = true;
  }

private:

  /* True if released.  Mutable because of the copy ctor hack
     above.  */
  mutable bool m_released = false;
};

/* The scope_exit class.  */

template<typename EF>
class scope_exit : public scope_exit_base<scope_exit<EF>>
{
  /* For access to on_exit().  */
  friend scope_exit_base<scope_exit<EF>>;

public:

  template<typename EFP,
	   typename = gdb::Requires<std::is_constructible<EF, EFP>>>
  scope_exit (EFP &&f)
    try : m_exit_function ((!std::is_lvalue_reference<EFP>::value
			    && std::is_nothrow_constructible<EF, EFP>::value)
			   ? std::move (f)
			   : f)
  {
  }
  catch (...)
    {
      /* "If the initialization of exit_function throws an exception,
	 calls f()."  */
      f ();
      /* "throws: Nothing, unless the initialization of exit_function
	 throws."  */
      throw;
    }

  template<typename EFP,
	   typename = gdb::Requires<std::is_constructible<EF, EFP>>>
  scope_exit (scope_exit &&rhs)
    noexcept (std::is_nothrow_move_constructible<EF>::value
	      || std::is_nothrow_copy_constructible<EF>::value)
    : m_exit_function (std::is_nothrow_constructible<EFP>::value
		       ? std::move (rhs)
		       : rhs)
  {
    rhs.release ();
  }

  DISABLE_COPY_AND_ASSIGN (scope_exit);
  void operator= (scope_exit &&) = delete;

private:
  void on_exit ()
  {
    m_exit_function ();
  }

  /* The function to call on scope exit.  */
  EF m_exit_function;
};

template <typename EF>
scope_exit<typename std::decay<EF>::type>
make_scope_exit (EF &&f)
{
  return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (f));
}

namespace detail
{

enum class scope_exit_lhs {};

template<typename EF>
scope_exit<typename std::decay<EF>::type>
operator+ (scope_exit_lhs, EF &&rhs)
{
  return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (rhs));
}

}

/* Register a block of code to run on scope exit.  Note that the local
   context is captured by reference, which means you should be careful
   to avoid inadvertently changing a captured local's value before the
   scope exit runs.  */

#define SCOPE_EXIT \
  auto CONCAT(scope_exit_, __LINE__) = ::detail::scope_exit_lhs () + [&] ()

#endif /* GDBSUPPORT_SCOPE_EXIT_H */
