/* Macros for general registry objects.

   Copyright (C) 2011-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 GDB_REGISTRY_H
#define GDB_REGISTRY_H

#include <type_traits>

template<typename T> class registry;

/* An accessor class that is used by registry_key.

   Normally, a container class has a registry<> field named
   "registry_fields".  In this case, the default accessor is used, as
   it simply returns the object.

   However, a container may sometimes need to store the registry
   elsewhere.  In this case, registry_accessor can be specialized to
   perform the needed indirection.  */

template<typename T>
struct registry_accessor
{
  /* Given a container of type T, return its registry.  */
  static registry<T> *get (T *obj)
  {
    return &obj->registry_fields;
  }
};

/* In gdb, sometimes there is a need for one module (e.g., the Python
   Type code) to attach some data to another object (e.g., an
   objfile); but it's also desirable that this be done such that the
   base object (the objfile in this example) not need to know anything
   about the attaching module (the Python code).

   This is handled using the registry system.

   A class needing to allow this sort registration can add a registry
   field.  For example, you would write:

   class some_container { registry<some_container> registry_fields; };

   The name of the field matters by default, see registry_accessor.

   A module wanting to attach data to instances of some_container uses
   the "key" class to register a key.  This key can then be passed to
   the "get" and "set" methods to handle this module's data.  */

template<typename T>
class registry
{
public:

  registry ()
    : m_fields (get_registrations ().size ())
  {
  }

  ~registry ()
  {
    clear_registry ();
  }

  DISABLE_COPY_AND_ASSIGN (registry);

  /* A type-safe registry key.

     The registry itself holds just a "void *".  This is not always
     convenient to manage, so this template class can be used instead,
     to provide a type-safe interface, that also helps manage the
     lifetime of the stored objects.

     When the container is destroyed, this key arranges to destroy the
     underlying data using Deleter.  This defaults to
     std::default_delete.  */

  template<typename DATA, typename Deleter = std::default_delete<DATA>>
  class key
  {
  public:

    key ()
      : m_key (registry<T>::new_key (cleanup))
    {
    }

    DISABLE_COPY_AND_ASSIGN (key);

    /* Fetch the data attached to OBJ that is associated with this key.
       If no such data has been attached, nullptr is returned.  */
    DATA *get (T *obj) const
    {
      registry<T> *reg_obj = registry_accessor<T>::get (obj);
      return (DATA *) reg_obj->get (m_key);
    }

    /* Attach DATA to OBJ, associated with this key.  Note that any
       previous data is simply dropped -- if destruction is needed,
       'clear' should be called.  */
    void set (T *obj, DATA *data) const
    {
      registry<T> *reg_obj = registry_accessor<T>::get (obj);
      reg_obj->set (m_key, (typename std::remove_const<DATA> *) data);
    }

    /* If this key uses the default deleter, then this method is
       available.  It emplaces a new instance of the associated data
       type and attaches it to OBJ using this key.  The arguments, if
       any, are forwarded to the constructor.  */
    template<typename Dummy = DATA *, typename... Args>
    typename std::enable_if<std::is_same<Deleter,
					 std::default_delete<DATA>>::value,
			    Dummy>::type
    emplace (T *obj, Args &&...args) const
    {
      DATA *result = new DATA (std::forward<Args> (args)...);
      set (obj, result);
      return result;
    }

    /* Clear the data attached to OBJ that is associated with this KEY.
       Any existing data is destroyed using the deleter, and the data is
       reset to nullptr.  */
    void clear (T *obj) const
    {
      DATA *datum = get (obj);
      if (datum != nullptr)
	{
	  cleanup (datum);
	  set (obj, nullptr);
	}
    }

  private:

    /* A helper function that is called by the registry to delete the
       contained object.  */
    static void cleanup (void *arg)
    {
      DATA *datum = (DATA *) arg;
      Deleter d;
      d (datum);
    }

    /* The underlying key.  */
    const unsigned m_key;
  };

  /* Clear all the data associated with this container.  This is
     dangerous and should not normally be done.  */
  void clear_registry ()
  {
    /* Call all the free functions.  */
    std::vector<registry_data_callback> &registrations
      = get_registrations ();
    unsigned last = registrations.size ();
    for (unsigned i = 0; i < last; ++i)
      {
	void *elt = m_fields[i];
	if (elt != nullptr)
	  {
	    registrations[i] (elt);
	    m_fields[i] = nullptr;
	  }
      }
  }

private:

  /* Registry callbacks have this type.  */
  typedef void (*registry_data_callback) (void *);

  /* Get a new key for this particular registry.  FREE is a callback.
     When the container object is destroyed, all FREE functions are
     called.  The data associated with the container object is passed
     to the callback.  */
  static unsigned new_key (registry_data_callback free)
  {
    std::vector<registry_data_callback> &registrations
      = get_registrations ();
    unsigned result = registrations.size ();
    registrations.push_back (free);
    return result;
  }

  /* Set the datum associated with KEY in this container.  */
  void set (unsigned key, void *datum)
  {
    m_fields[key] = datum;
  }

  /* Fetch the datum associated with KEY in this container.  If 'set'
     has not been called for this key, nullptr is returned.  */
  void *get (unsigned key)
  {
    return m_fields[key];
  }

  /* The data stored in this instance.  */
  std::vector<void *> m_fields;

  /* Return a reference to the vector of all the registrations that
     have been made.  */
  static std::vector<registry_data_callback> &get_registrations ()
  {
    static std::vector<registry_data_callback> registrations;
    return registrations;
  }
};

#endif /* GDB_REGISTRY_H */
