/* Copyright (C) 2019 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 COMMON_SCOPE_EXIT_H
#define COMMON_SCOPE_EXIT_H

#include <functional>
#include <type_traits>
#include "common/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 ();
      }
  }

  /* This is needed for make_scope_exit because copy elision isn't
     guaranteed until C++17.  An optimizing compiler will usually skip
     calling this, but it must exist.  */
  scope_exit_base (const scope_exit_base &other)
    : m_released (other.m_released)
  {
    other.m_released = true;
  }

  void operator= (const scope_exit_base &) = delete;

  /* 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 ();
    }

  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 ();
  }

  /* This is needed for make_scope_exit because copy elision isn't
     guaranteed until C++17.  An optimizing compiler will usually skip
     calling this, but it must exist.  */
  scope_exit (const scope_exit &other)
    : scope_exit_base<scope_exit<EF>> (other),
      m_exit_function (other.m_exit_function)
  {
  }

  void operator= (const scope_exit &) = delete;
  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 /* COMMON_SCOPE_EXIT_H */
