/* Observers

   Copyright (C) 2016-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_OBSERVABLE_H
#define GDBSUPPORT_OBSERVABLE_H

#include <algorithm>
#include <functional>
#include <vector>

/* Print an "observer" debug statement.  */

#define observer_debug_printf(fmt, ...) \
  debug_prefixed_printf_cond (observer_debug, "observer", fmt, ##__VA_ARGS__)

/* Print "observer" start/end debug statements.  */

#define OBSERVER_SCOPED_DEBUG_START_END(fmt, ...) \
  scoped_debug_start_end (observer_debug, "observer", fmt, ##__VA_ARGS__)

namespace gdb
{

namespace observers
{

extern bool observer_debug;

/* An observer is an entity which is interested in being notified
   when GDB reaches certain states, or certain events occur in GDB.
   The entity being observed is called the observable.  To receive
   notifications, the observer attaches a callback to the observable.
   One observable can have several observers.

   The observer implementation is also currently not reentrant.  In
   particular, it is therefore not possible to call the attach or
   detach routines during a notification.  */

/* The type of a key that can be passed to attach, which can be passed
   to detach to remove associated observers.  Tokens have address
   identity, and are thus usually const globals.  */
struct token
{
  token () = default;

  DISABLE_COPY_AND_ASSIGN (token);
};

namespace detail
{
  /* Types that don't depend on any template parameter.  This saves a
     bit of code and debug info size, compared to putting them inside
     class observable.  */

  /* Use for sorting algorithm, to indicate which observer we have
     visited.  */
  enum class visit_state
  {
    NOT_VISITED,
    VISITING,
    VISITED,
  };
}

template<typename... T>
class observable
{
public:
  typedef std::function<void (T...)> func_type;

private:
  struct observer
  {
    observer (const struct token *token, func_type func, const char *name,
	      const std::vector<const struct token *> &dependencies)
      : token (token), func (func), name (name), dependencies (dependencies)
    {}

    const struct token *token;
    func_type func;
    const char *name;
    std::vector<const struct token *> dependencies;
  };

public:
  explicit observable (const char *name)
    : m_name (name)
  {
  }

  DISABLE_COPY_AND_ASSIGN (observable);

  /* Attach F as an observer to this observable.  F cannot be detached or
     specified as a dependency.

     DEPENDENCIES is a list of tokens of observers to be notified before this
     one.

     NAME is the name of the observer, used for debug output purposes.  Its
     lifetime must be at least as long as the observer is attached.  */
  void attach (const func_type &f, const char *name,
	       const std::vector<const struct token *> &dependencies = {})
  {
    attach (f, nullptr, name, dependencies);
  }

  /* Attach F as an observer to this observable.

     T is a reference to a token that can be used to later remove F or specify F
     as a dependency of another observer.

     DEPENDENCIES is a list of tokens of observers to be notified before this
     one.

     NAME is the name of the observer, used for debug output purposes.  Its
     lifetime must be at least as long as the observer is attached.  */
  void attach (const func_type &f, const token &t, const char *name,
	       const std::vector<const struct token *> &dependencies = {})
  {
    attach (f, &t, name, dependencies);
  }

  /* Remove observers associated with T from this observable.  T is
     the token that was previously passed to any number of "attach"
     calls.  */
  void detach (const token &t)
  {
    auto iter = std::remove_if (m_observers.begin (),
				m_observers.end (),
				[&] (const observer &o)
				{
				  return o.token == &t;
				});

    observer_debug_printf ("Detaching observable %s from observer %s",
			   iter->name, m_name);

    m_observers.erase (iter, m_observers.end ());
  }

  /* Notify all observers that are attached to this observable.  */
  void notify (T... args) const
  {
    OBSERVER_SCOPED_DEBUG_START_END ("observable %s notify() called", m_name);

    for (auto &&e : m_observers)
      {
	OBSERVER_SCOPED_DEBUG_START_END ("calling observer %s of observable %s",
					 e.name, m_name);
	e.func (args...);
      }
  }

private:

  std::vector<observer> m_observers;
  const char *m_name;

  /* Helper method for topological sort using depth-first search algorithm.

     Visit all dependencies of observer at INDEX in M_OBSERVERS (later referred
     to as "the observer").  Then append the observer to SORTED_OBSERVERS.

     If the observer is already visited, do nothing.  */
  void visit_for_sorting (std::vector<observer> &sorted_observers,
			  std::vector<detail::visit_state> &visit_states,
			  int index)
  {
    if (visit_states[index] == detail::visit_state::VISITED)
      return;

    /* If we are already visiting this observer, it means there's a cycle.  */
    gdb_assert (visit_states[index] != detail::visit_state::VISITING);

    visit_states[index] = detail::visit_state::VISITING;

    /* For each dependency of this observer...  */
    for (const token *dep : m_observers[index].dependencies)
      {
	/* ... find the observer that has token DEP.  If found, visit it.  */
	auto it_dep
	  = std::find_if (m_observers.begin (), m_observers.end (),
			    [&] (observer o) { return o.token == dep; });
	if (it_dep != m_observers.end ())
	{
	  int i = std::distance (m_observers.begin (), it_dep);
	  visit_for_sorting (sorted_observers, visit_states, i);
	}
      }

    visit_states[index] = detail::visit_state::VISITED;
    sorted_observers.push_back (m_observers[index]);
  }

  /* Sort the observers, so that dependencies come before observers
     depending on them.

     Uses depth-first search algorithm for topological sorting, see
     https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search .  */
  void sort_observers ()
  {
    std::vector<observer> sorted_observers;
    std::vector<detail::visit_state> visit_states
      (m_observers.size (), detail::visit_state::NOT_VISITED);

    for (size_t i = 0; i < m_observers.size (); i++)
      visit_for_sorting (sorted_observers, visit_states, i);

    m_observers = std::move (sorted_observers);
  }

  void attach (const func_type &f, const token *t, const char *name,
	       const std::vector<const struct token *> &dependencies)
  {

    observer_debug_printf ("Attaching observable %s to observer %s",
			   name, m_name);

    m_observers.emplace_back (t, f, name, dependencies);

    /* The observer has been inserted at the end of the vector, so it will be
       after any of its potential dependencies attached earlier.  If the
       observer has a token, it means that other observers can specify it as
       a dependency, so sorting is necessary to ensure those will be after the
       newly inserted observer afterwards.  */
    if (t != nullptr)
      sort_observers ();
  };
};

} /* namespace observers */

} /* namespace gdb */

#endif /* GDBSUPPORT_OBSERVABLE_H */
