Rewrite registry.h
authorTom Tromey <tom@tromey.com>
Sun, 18 Oct 2020 17:38:10 +0000 (11:38 -0600)
committerTom Tromey <tom@tromey.com>
Thu, 28 Jul 2022 20:16:50 +0000 (14:16 -0600)
This rewrites registry.h, removing all the macros and replacing it
with relatively ordinary template classes.  The result is less code
than the previous setup.  It replaces large macros with a relatively
straightforward C++ class, and now manages its own cleanup.

The existing type-safe "key" class is replaced with the equivalent
template class.  This approach ended up requiring relatively few
changes to the users of the registry code in gdb -- code using the key
system just required a small change to the key's declaration.

All existing users of the old C-like API are now converted to use the
type-safe API.  This mostly involved changing explicit deletion
functions to be an operator() in a deleter class.

The old "save/free" two-phase process is removed, and replaced with a
single "free" phase.  No existing code used both phases.

The old "free" callbacks took a parameter for the enclosing container
object.  However, this wasn't truly needed and is removed here as
well.

64 files changed:
gdb/Makefile.in
gdb/ada-lang.c
gdb/ada-tasks.c
gdb/arm-tdep.c
gdb/auto-load.c
gdb/auxv.c
gdb/break-catch-syscall.c
gdb/breakpoint.c
gdb/coffread.c
gdb/ctfread.c
gdb/dbxread.c
gdb/dwarf2/frame.c
gdb/dwarf2/read.c
gdb/elfread.c
gdb/fbsd-tdep.c
gdb/gdb-stabs.h
gdb/gdb_bfd.c
gdb/gdb_bfd.h
gdb/gdbtypes.c
gdb/guile/guile-internal.h
gdb/guile/scm-block.c
gdb/guile/scm-frame.c
gdb/guile/scm-objfile.c
gdb/guile/scm-progspace.c
gdb/guile/scm-symbol.c
gdb/guile/scm-symtab.c
gdb/guile/scm-type.c
gdb/hppa-tdep.c
gdb/inferior.c
gdb/inferior.h
gdb/inflow.c
gdb/linux-tdep.c
gdb/mdebugread.c
gdb/minidebug.c
gdb/nto-tdep.c
gdb/objc-lang.c
gdb/objfiles.c
gdb/objfiles.h
gdb/progspace.c
gdb/progspace.h
gdb/python/py-block.c
gdb/python/py-inferior.c
gdb/python/py-objfile.c
gdb/python/py-progspace.c
gdb/python/py-symbol.c
gdb/python/py-symtab.c
gdb/python/py-type.c
gdb/registry.c [deleted file]
gdb/registry.h
gdb/remote-sim.c
gdb/remote.c
gdb/rs6000-tdep.c
gdb/solib-aix.c
gdb/solib-darwin.c
gdb/solib-dsbt.c
gdb/solib-svr4.c
gdb/solib.c
gdb/source.c
gdb/stabsread.c
gdb/symfile-debug.c
gdb/symfile.c
gdb/symtab.c
gdb/target-dcache.c
gdb/xcoffread.c

index aebb7dc5ea3171bf0b9cb0d5481d0f7c0deae496..2598b81d2054d073d56f0edb5778fc5917712180 100644 (file)
@@ -1152,7 +1152,6 @@ COMMON_SFILES = \
        regcache.c \
        regcache-dump.c \
        reggroups.c \
-       registry.c \
        remote.c \
        remote-fileio.c \
        remote-notif.c \
index 650408134bb5af3af72824cecef86c8168189db0..d49baf99005910553c93ca49f497a9ba6e9c85af 100644 (file)
@@ -334,7 +334,7 @@ struct ada_inferior_data
 };
 
 /* Our key to this module's inferior data.  */
-static const struct inferior_key<ada_inferior_data> ada_inferior_data;
+static const registry<inferior>::key<ada_inferior_data> ada_inferior_data;
 
 /* Return our inferior data for the given inferior (INF).
 
@@ -376,7 +376,8 @@ struct ada_pspace_data
 };
 
 /* Key to our per-program-space data.  */
-static const struct program_space_key<ada_pspace_data> ada_pspace_data_handle;
+static const registry<program_space>::key<ada_pspace_data>
+  ada_pspace_data_handle;
 
 /* Return this module's data for the given program space (PSPACE).
    If not is found, add a zero'ed one now.
index 0043f2999d9d8a9e62f83b46f628d30ae90e4b52..fda49557a4f8a8426637d9025dd1246b9a3b8f4f 100644 (file)
@@ -166,7 +166,7 @@ struct ada_tasks_pspace_data
 };
 
 /* Key to our per-program-space data.  */
-static const struct program_space_key<ada_tasks_pspace_data>
+static const registry<program_space>::key<ada_tasks_pspace_data>
   ada_tasks_pspace_data_handle;
 
 /* The kind of data structure used by the runtime to store the list
@@ -242,7 +242,7 @@ struct ada_tasks_inferior_data
 };
 
 /* Key to our per-inferior data.  */
-static const struct inferior_key<ada_tasks_inferior_data>
+static const registry<inferior>::key<ada_tasks_inferior_data>
   ada_tasks_inferior_data_handle;
 
 /* Return a string with TASKNO followed by the task name if TASK_INFO
index 7d8d040f8f12200d0cc0a5e7be2be3c67ab842ba..d4c5beb5e06c915aca72a3c57e59c8bbc1e3c87d 100644 (file)
@@ -123,7 +123,7 @@ struct arm_per_bfd
 };
 
 /* Per-bfd data used for mapping symbols.  */
-static bfd_key<arm_per_bfd> arm_bfd_data_key;
+static const registry<bfd>::key<arm_per_bfd> arm_bfd_data_key;
 
 /* The list of available "set arm ..." and "show arm ..." commands.  */
 static struct cmd_list_element *setarmcmdlist = NULL;
@@ -2407,7 +2407,7 @@ struct arm_exidx_data
 };
 
 /* Per-BFD key to store exception handling information.  */
-static const struct bfd_key<arm_exidx_data> arm_exidx_data_key;
+static const registry<bfd>::key<arm_exidx_data> arm_exidx_data_key;
 
 static struct obj_section *
 arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
index b6056f5d60a957b0c19ae87e79d8cc866eb742c8..54ed73d1bf3a68c3d9710230bad96d7915610d95 100644 (file)
@@ -536,8 +536,8 @@ struct loaded_script
 };
 
 /* Per-program-space data key.  */
-static const struct program_space_key<struct auto_load_pspace_info>
-  auto_load_pspace_data;
+static const registry<program_space>::key<auto_load_pspace_info>
+     auto_load_pspace_data;
 
 /* Get the current autoload data.  If none is found yet, add it now.  This
    function always returns a valid object.  */
index 8e175138f5da4f97c5e342358cb88f6dfdd489d7..6154988f6ddd944577b68510d071487fa554c73c 100644 (file)
@@ -332,7 +332,7 @@ struct auxv_info
 };
 
 /* Per-inferior data key for auxv.  */
-static const struct inferior_key<auxv_info> auxv_inferior_data;
+static const registry<inferior>::key<auxv_info> auxv_inferior_data;
 
 /* Invalidate INF's auxv cache.  */
 
index 06d48466de7466b38b0d7076167f4a38256ab91d..805bb86cee6ff8eead85197943be22b575fd691b 100644 (file)
@@ -79,7 +79,7 @@ struct catch_syscall_inferior_data
   int total_syscalls_count;
 };
 
-static const struct inferior_key<struct catch_syscall_inferior_data>
+static const registry<inferior>::key<catch_syscall_inferior_data>
   catch_syscall_inferior_data;
 
 static struct catch_syscall_inferior_data *
index 39a8eaa8a341ec542f5c86eba9bf603ad165e2c4..dae96d205be474fd017f22fbff013926a9512598 100644 (file)
@@ -3327,7 +3327,7 @@ struct breakpoint_objfile_data
   std::vector<probe *> exception_probes;
 };
 
-static const struct objfile_key<breakpoint_objfile_data>
+static const registry<objfile>::key<breakpoint_objfile_data>
   breakpoint_objfile_key;
 
 /* Minimal symbol not found sentinel.  */
index 474a1aa02f570acf6fc7605e0c7cbc7dce9c0634..f7f5bb007caf3d7940ebf243f7580aa4c9efbd50 100644 (file)
@@ -61,7 +61,7 @@ struct coff_symfile_info
 
 /* Key for COFF-associated data.  */
 
-static const struct objfile_key<coff_symfile_info> coff_objfile_data_key;
+static const registry<objfile>::key<coff_symfile_info> coff_objfile_data_key;
 
 /* Translate an external name string into a user-visible name.  */
 #define        EXTERNAL_NAME(string, abfd) \
index 828f300d29d515cc24c8bc4db6e458ef302ceae5..0da4f0d0720de2a4ca3c6ee4e7dc19053e51cebc 100644 (file)
@@ -87,7 +87,7 @@
 #include "ctf.h"
 #include "ctf-api.h"
 
-static const struct objfile_key<htab, htab_deleter> ctf_tid_key;
+static const registry<objfile>::key<htab, htab_deleter> ctf_tid_key;
 
 struct ctf_fp_info
 {
@@ -107,7 +107,7 @@ ctf_fp_info::~ctf_fp_info ()
   ctf_close (arc);
 }
 
-static const objfile_key<ctf_fp_info> ctf_dict_key;
+static const registry<objfile>::key<ctf_fp_info> ctf_dict_key;
 
 /* A CTF context consists of a file pointer and an objfile pointer.  */
 
@@ -243,7 +243,7 @@ set_tid_type (struct objfile *of, ctf_id_t tid, struct type *typ)
 {
   htab_t htab;
 
-  htab = (htab_t) ctf_tid_key.get (of);
+  htab = ctf_tid_key.get (of);
   if (htab == NULL)
     {
       htab = htab_create_alloc (1, tid_and_type_hash,
@@ -271,7 +271,7 @@ get_tid_type (struct objfile *of, ctf_id_t tid)
   struct ctf_tid_and_type *slot, ids;
   htab_t htab;
 
-  htab = (htab_t) ctf_tid_key.get (of);
+  htab = ctf_tid_key.get (of);
   if (htab == NULL)
     return nullptr;
 
index bcf519000bceefd52cacceeed7c844f9896acaa3..e1bf9a01e3060357f450451b071e71b4a2612edc 100644 (file)
@@ -57,7 +57,7 @@
 
 /* Key for dbx-associated data.  */
 
-objfile_key<dbx_symfile_info> dbx_objfile_data_key;
+const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
 
 /* We put a pointer to this structure in the read_symtab_private field
    of the psymtab.  */
index 5878d72f922d54d8f8d47b138b6914500e7ed7ba..d7a06395acb863b0b422f65b98d5f449ebb25f94 100644 (file)
@@ -1370,12 +1370,12 @@ dwarf2_frame_cfa (struct frame_info *this_frame)
 \f
 /* We store the frame data on the BFD.  This is only done if it is
    independent of the address space and so can be shared.  */
-static const struct bfd_key<comp_unit> dwarf2_frame_bfd_data;
+static const registry<bfd>::key<comp_unit> dwarf2_frame_bfd_data;
 
 /* If any BFD sections require relocations (note; really should be if
    any debug info requires relocations), then we store the frame data
    on the objfile instead, and do not share it.  */
-const struct objfile_key<comp_unit> dwarf2_frame_objfile_data;
+static const registry<objfile>::key<comp_unit> dwarf2_frame_objfile_data;
 \f
 
 /* Pointer encoding helper functions.  */
index f7e55af3e86b41b2dc36a13c84d83b34bede27d9..70419da13e42b312d67dc9f6892e856e61b423ed 100644 (file)
@@ -124,7 +124,8 @@ static bool check_physname = false;
 static bool use_deprecated_index_sections = false;
 
 /* This is used to store the data that is always per objfile.  */
-static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
+static const registry<objfile>::key<dwarf2_per_objfile>
+     dwarf2_objfile_data_key;
 
 /* These are used to store the dwarf2_per_bfd objects.
 
@@ -134,8 +135,9 @@ static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
    Other objfiles are not going to share a dwarf2_per_bfd with any other
    objfiles, so they'll have their own version kept in the _objfile_data_key
    version.  */
-static const struct bfd_key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
-static const struct objfile_key<dwarf2_per_bfd> dwarf2_per_bfd_objfile_data_key;
+static const registry<bfd>::key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
+static const registry<objfile>::key<dwarf2_per_bfd>
+  dwarf2_per_bfd_objfile_data_key;
 
 /* The "aclass" indices for various kinds of computed DWARF symbols.  */
 
index 8ff62a1fed59532282d0177f91105d26b3a88824..deed34c35c7d3258f0f515f0e4baf43cf52ea693 100644 (file)
@@ -69,7 +69,7 @@ typedef std::vector<std::unique_ptr<probe>> elfread_data;
 
 /* Per-BFD data for probe info.  */
 
-static const struct bfd_key<elfread_data> probe_key;
+static const registry<bfd>::key<elfread_data> probe_key;
 
 /* Minimal symbols located at the GOT entries for .plt - that is the real
    pointer where the given entry will jump to.  It gets updated by the real
@@ -646,7 +646,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
 
 /* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked.  */
 
-static const struct objfile_key<htab, htab_deleter>
+static const registry<objfile>::key<htab, htab_deleter>
   elf_objfile_gnu_ifunc_cache_data;
 
 /* Map function names to CORE_ADDR in elf_objfile_gnu_ifunc_cache_data.  */
index b241e855bd6f716b36c16703ff764b1aff470599..f2f961b5486ac790b5778f20fe42bd31be4e6a2d 100644 (file)
@@ -520,7 +520,7 @@ struct fbsd_pspace_data
 };
 
 /* Per-program-space data for FreeBSD architectures.  */
-static const struct program_space_key<fbsd_pspace_data>
+static const registry<program_space>::key<fbsd_pspace_data>
   fbsd_pspace_data_handle;
 
 static struct fbsd_pspace_data *
index fef988524f217e660da613b4237008142f58a698..5c697906caba3d38b4f3f8c8a054937578c0c126 100644 (file)
@@ -60,7 +60,7 @@ struct dbx_symfile_info
 
 /* The tag used to find the DBX info attached to an objfile.  This is
    global because it is referenced by several modules.  */
-extern objfile_key<dbx_symfile_info> dbx_objfile_data_key;
+extern const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
 
 #define DBX_SYMFILE_INFO(o)    (dbx_objfile_data_key.get (o))
 #define DBX_TEXT_ADDR(o)       (DBX_SYMFILE_INFO(o)->text_addr)
index 22828482d5b39d85b678f3342cbe605d7aaff60f..6c03ae5ef0535389e2ccd2be3bcde679fb87f009 100644 (file)
@@ -112,13 +112,15 @@ struct gdb_bfd_data
   std::vector<gdb_bfd_ref_ptr> included_bfds;
 
   /* The registry.  */
-  REGISTRY_FIELDS = {};
+  registry<bfd> registry_fields;
 };
 
-#define GDB_BFD_DATA_ACCESSOR(ABFD) \
-  ((struct gdb_bfd_data *) bfd_usrdata (ABFD))
-
-DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR)
+registry<bfd> *
+registry_accessor<bfd>::get (bfd *abfd)
+{
+  struct gdb_bfd_data *gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
+  return &gdata->registry_fields;
+}
 
 /* A hash table storing all the BFDs maintained in the cache.  */
 
@@ -498,7 +500,6 @@ gdb_bfd_init_data (struct bfd *abfd, struct stat *st)
 
   gdata = new gdb_bfd_data (abfd, st);
   bfd_set_usrdata (abfd, gdata);
-  bfd_alloc_data (abfd);
 
   /* This is the first we've seen it, so add it to the hash table.  */
   slot = htab_find_slot (all_bfds, abfd, INSERT);
@@ -725,7 +726,6 @@ gdb_bfd_unref (struct bfd *abfd)
        htab_clear_slot (gdb_bfd_cache, slot);
     }
 
-  bfd_free_data (abfd);
   delete gdata;
   bfd_set_usrdata (abfd, NULL);  /* Paranoia.  */
 
index 6845d6ccef561c95cdec8137ab86170cfae45e0f..86f7be85f2090afc57e4c7a66c3ad039be33f4e6 100644 (file)
 #include "gdbsupport/iterator-range.h"
 #include "gdbsupport/next-iterator.h"
 
-DECLARE_REGISTRY (bfd);
+/* A registry adaptor for BFD.  This arranges to store the registry in
+   gdb's per-BFD data, which is stored as the bfd_usrdata.  */
+template<>
+struct registry_accessor<bfd>
+{
+  static registry<bfd> *get (bfd *abfd);
+};
 
 /* If supplied a path starting with this sequence, gdb_bfd_open will
    open BFDs using target fileio operations.  */
index 34da6d80e924e36d3c5952bc81b69cf7f6c2e5bc..8ab0a898ba66bc40440499aaf4cfb07dffaf16ce 100644 (file)
@@ -6078,7 +6078,7 @@ typedef std::vector<std::unique_ptr<fixed_point_type_info>>
     fixed_point_type_storage;
 
 /* Key used for managing the storage of fixed-point type info.  */
-static const struct objfile_key<fixed_point_type_storage>
+static const struct registry<objfile>::key<fixed_point_type_storage>
     fixed_point_objfile_key;
 
 /* See gdbtypes.h.  */
@@ -6305,8 +6305,8 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
 /* This set of objfile-based types is intended to be used by symbol
    readers as basic types.  */
 
-static const struct objfile_key<struct objfile_type,
-                               gdb::noop_deleter<struct objfile_type>>
+static const registry<objfile>::key<struct objfile_type,
+                                   gdb::noop_deleter<struct objfile_type>>
   objfile_type_data;
 
 const struct objfile_type *
index 4cdb7e355d7fd880b6ddee0148618180f4158e30..30cc5c307ae2e1366a2848a91aa905adfd415024 100644 (file)
@@ -28,6 +28,7 @@
 #include "extension-priv.h"
 #include "symtab.h"
 #include "libguile.h"
+#include "objfiles.h"
 
 struct block;
 struct frame_info;
@@ -272,7 +273,6 @@ struct eqable_gdb_smob
 #undef GDB_SMOB_HEAD
 
 struct objfile;
-struct objfile_data;
 
 /* A predicate that returns non-zero if an object is a particular kind
    of gsmob.  */
index 41954c70519535681a7b58faf2bd3caf68e1bb1e..a29c2db58f10ab240fcfa57359e7ebec1e7fe78e 100644 (file)
@@ -76,7 +76,37 @@ static scm_t_bits block_syms_progress_smob_tag;
 /* The "next!" block syms iterator method.  */
 static SCM bkscm_next_symbol_x_proc;
 
-static const struct objfile_data *bkscm_objfile_data_key;
+/* This is called when an objfile is about to be freed.
+   Invalidate the block as further actions on the block would result
+   in bad data.  All access to b_smob->block should be gated by
+   checks to ensure the block is (still) valid.  */
+struct bkscm_deleter
+{
+  /* Helper function for bkscm_del_objfile_blocks to mark the block
+     as invalid.  */
+
+  static int
+  bkscm_mark_block_invalid (void **slot, void *info)
+  {
+    block_smob *b_smob = (block_smob *) *slot;
+
+    b_smob->block = NULL;
+    b_smob->objfile = NULL;
+    return 1;
+  }
+
+  void operator() (htab_t htab)
+  {
+    if (htab != NULL)
+      {
+       htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL);
+       htab_delete (htab);
+      }
+  }
+};
+
+static const registry<objfile>::key<htab, bkscm_deleter>
+     bkscm_objfile_data_key;
 \f
 /* Administrivia for block smobs.  */
 
@@ -108,13 +138,13 @@ bkscm_eq_block_smob (const void *ap, const void *bp)
 static htab_t
 bkscm_objfile_block_map (struct objfile *objfile)
 {
-  htab_t htab = (htab_t) objfile_data (objfile, bkscm_objfile_data_key);
+  htab_t htab = bkscm_objfile_data_key.get (objfile);
 
   if (htab == NULL)
     {
       htab = gdbscm_create_eqable_gsmob_ptr_map (bkscm_hash_block_smob,
                                                 bkscm_eq_block_smob);
-      set_objfile_data (objfile, bkscm_objfile_data_key, htab);
+      bkscm_objfile_data_key.set (objfile, htab);
     }
 
   return htab;
@@ -326,35 +356,6 @@ bkscm_scm_to_block (SCM block_scm, int arg_pos, const char *func_name,
   return NULL;
 }
 
-/* Helper function for bkscm_del_objfile_blocks to mark the block
-   as invalid.  */
-
-static int
-bkscm_mark_block_invalid (void **slot, void *info)
-{
-  block_smob *b_smob = (block_smob *) *slot;
-
-  b_smob->block = NULL;
-  b_smob->objfile = NULL;
-  return 1;
-}
-
-/* This function is called when an objfile is about to be freed.
-   Invalidate the block as further actions on the block would result
-   in bad data.  All access to b_smob->block should be gated by
-   checks to ensure the block is (still) valid.  */
-
-static void
-bkscm_del_objfile_blocks (struct objfile *objfile, void *datum)
-{
-  htab_t htab = (htab_t) datum;
-
-  if (htab != NULL)
-    {
-      htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL);
-      htab_delete (htab);
-    }
-}
 \f
 /* Block methods.  */
 
@@ -800,13 +801,3 @@ gdbscm_initialize_blocks (void)
                                gdbscm_scm_from_c_string ("\
 Internal function to assist the block symbols iterator."));
 }
-
-void _initialize_scm_block ();
-void
-_initialize_scm_block ()
-{
-  /* Register an objfile "free" callback so we can properly
-     invalidate blocks when an object file is about to be deleted.  */
-  bkscm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, bkscm_del_objfile_blocks);
-}
index 6bbb6f81d685bb8771e7bbf1588e473775031d4a..4132bb246d8f5897e5f8b2253b7786470ebbddfd 100644 (file)
@@ -74,7 +74,37 @@ static scm_t_bits frame_smob_tag;
 /* Keywords used in argument passing.  */
 static SCM block_keyword;
 
-static const struct inferior_data *frscm_inferior_data_key;
+/* This is called when an inferior is about to be freed.
+   Invalidate the frame as further actions on the frame could result
+   in bad data.  All access to the frame should be gated by
+   frscm_get_frame_smob_arg_unsafe which will raise an exception on
+   invalid frames.  */
+struct frscm_deleter
+{
+  /* Helper function for frscm_del_inferior_frames to mark the frame
+     as invalid.  */
+
+  static int
+  frscm_mark_frame_invalid (void **slot, void *info)
+  {
+    frame_smob *f_smob = (frame_smob *) *slot;
+
+    f_smob->inferior = NULL;
+    return 1;
+  }
+
+  void operator() (htab_t htab)
+  {
+    if (htab != NULL)
+      {
+       htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL);
+       htab_delete (htab);
+      }
+  }
+};
+
+static const registry<inferior>::key<htab, frscm_deleter>
+    frscm_inferior_data_key;
 \f
 /* Administrivia for frame smobs.  */
 
@@ -117,13 +147,13 @@ frscm_eq_frame_smob (const void *ap, const void *bp)
 static htab_t
 frscm_inferior_frame_map (struct inferior *inferior)
 {
-  htab_t htab = (htab_t) inferior_data (inferior, frscm_inferior_data_key);
+  htab_t htab = frscm_inferior_data_key.get (inferior);
 
   if (htab == NULL)
     {
       htab = gdbscm_create_eqable_gsmob_ptr_map (frscm_hash_frame_smob,
                                                 frscm_eq_frame_smob);
-      set_inferior_data (inferior, frscm_inferior_data_key, htab);
+      frscm_inferior_data_key.set (inferior, htab);
     }
 
   return htab;
@@ -346,35 +376,6 @@ frscm_frame_smob_to_frame (frame_smob *f_smob)
   return frame;
 }
 
-/* Helper function for frscm_del_inferior_frames to mark the frame
-   as invalid.  */
-
-static int
-frscm_mark_frame_invalid (void **slot, void *info)
-{
-  frame_smob *f_smob = (frame_smob *) *slot;
-
-  f_smob->inferior = NULL;
-  return 1;
-}
-
-/* This function is called when an inferior is about to be freed.
-   Invalidate the frame as further actions on the frame could result
-   in bad data.  All access to the frame should be gated by
-   frscm_get_frame_smob_arg_unsafe which will raise an exception on
-   invalid frames.  */
-
-static void
-frscm_del_inferior_frames (struct inferior *inferior, void *datum)
-{
-  htab_t htab = (htab_t) datum;
-
-  if (htab != NULL)
-    {
-      htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL);
-      htab_delete (htab);
-    }
-}
 \f
 /* Frame methods.  */
 
@@ -1170,13 +1171,3 @@ gdbscm_initialize_frames (void)
 
   block_keyword = scm_from_latin1_keyword ("block");
 }
-
-void _initialize_scm_frame ();
-void
-_initialize_scm_frame ()
-{
-  /* Register an inferior "free" callback so we can properly
-     invalidate frames when an inferior file is about to be deleted.  */
-  frscm_inferior_data_key
-    = register_inferior_data_with_cleanup (NULL, frscm_del_inferior_frames);
-}
index 760d5aa1f4b12b9a372eef1015d1591034dbf5f8..1a87dcf74fab1155a244ebd7dad05c1053330f43 100644 (file)
@@ -49,7 +49,18 @@ static const char objfile_smob_name[] = "gdb:objfile";
 /* The tag Guile knows the objfile smob by.  */
 static scm_t_bits objfile_smob_tag;
 
-static const struct objfile_data *ofscm_objfile_data_key;
+/* Objfile registry cleanup handler for when an objfile is deleted.  */
+struct ofscm_deleter
+{
+  void operator() (objfile_smob *o_smob)
+  {
+    o_smob->objfile = NULL;
+    scm_gc_unprotect_object (o_smob->containing_scm);
+  }
+};
+
+static const registry<objfile>::key<objfile_smob, ofscm_deleter>
+     ofscm_objfile_data_key;
 
 /* Return the list of pretty-printers registered with O_SMOB.  */
 
@@ -101,27 +112,6 @@ ofscm_make_objfile_smob (void)
   return o_scm;
 }
 
-/* Clear the OBJFILE pointer in O_SMOB and unprotect the object from GC.  */
-
-static void
-ofscm_release_objfile (objfile_smob *o_smob)
-{
-  o_smob->objfile = NULL;
-  scm_gc_unprotect_object (o_smob->containing_scm);
-}
-
-/* Objfile registry cleanup handler for when an objfile is deleted.  */
-
-static void
-ofscm_handle_objfile_deleted (struct objfile *objfile, void *datum)
-{
-  objfile_smob *o_smob = (objfile_smob *) datum;
-
-  gdb_assert (o_smob->objfile == objfile);
-
-  ofscm_release_objfile (o_smob);
-}
-
 /* Return non-zero if SCM is a <gdb:objfile> object.  */
 
 static int
@@ -147,7 +137,7 @@ ofscm_objfile_smob_from_objfile (struct objfile *objfile)
 {
   objfile_smob *o_smob;
 
-  o_smob = (objfile_smob *) objfile_data (objfile, ofscm_objfile_data_key);
+  o_smob = ofscm_objfile_data_key.get (objfile);
   if (o_smob == NULL)
     {
       SCM o_scm = ofscm_make_objfile_smob ();
@@ -155,7 +145,7 @@ ofscm_objfile_smob_from_objfile (struct objfile *objfile)
       o_smob = (objfile_smob *) SCM_SMOB_DATA (o_scm);
       o_smob->objfile = objfile;
 
-      set_objfile_data (objfile, ofscm_objfile_data_key, o_smob);
+      ofscm_objfile_data_key.set (objfile, o_smob);
       scm_gc_protect_object (o_smob->containing_scm);
     }
 
@@ -424,11 +414,3 @@ gdbscm_initialize_objfiles (void)
 
   gdbscm_define_functions (objfile_functions, 1);
 }
-
-void _initialize_scm_objfile ();
-void
-_initialize_scm_objfile ()
-{
-  ofscm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, ofscm_handle_objfile_deleted);
-}
index c48da761945265133f7f76b62ab6c08fe95ff240..7a197d76543faef7a7b0b287efea0d6a7b8f1882 100644 (file)
@@ -52,7 +52,18 @@ static const char pspace_smob_name[] = "gdb:progspace";
 /* The tag Guile knows the pspace smob by.  */
 static scm_t_bits pspace_smob_tag;
 
-static const struct program_space_data *psscm_pspace_data_key;
+/* Progspace registry cleanup handler for when a progspace is deleted.  */
+struct psscm_deleter
+{
+  void operator() (pspace_smob *p_smob)
+  {
+    p_smob->pspace = NULL;
+    scm_gc_unprotect_object (p_smob->containing_scm);
+  }
+};
+
+static const registry<program_space>::key<pspace_smob, psscm_deleter>
+     psscm_pspace_data_key;
 
 /* Return the list of pretty-printers registered with P_SMOB.  */
 
@@ -111,27 +122,6 @@ psscm_make_pspace_smob (void)
   return p_scm;
 }
 
-/* Clear the progspace pointer in P_SMOB and unprotect the object from GC.  */
-
-static void
-psscm_release_pspace (pspace_smob *p_smob)
-{
-  p_smob->pspace = NULL;
-  scm_gc_unprotect_object (p_smob->containing_scm);
-}
-
-/* Progspace registry cleanup handler for when a progspace is deleted.  */
-
-static void
-psscm_handle_pspace_deleted (struct program_space *pspace, void *datum)
-{
-  pspace_smob *p_smob = (pspace_smob *) datum;
-
-  gdb_assert (p_smob->pspace == pspace);
-
-  psscm_release_pspace (p_smob);
-}
-
 /* Return non-zero if SCM is a <gdb:progspace> object.  */
 
 static int
@@ -157,7 +147,7 @@ psscm_pspace_smob_from_pspace (struct program_space *pspace)
 {
   pspace_smob *p_smob;
 
-  p_smob = (pspace_smob *) program_space_data (pspace, psscm_pspace_data_key);
+  p_smob = psscm_pspace_data_key.get (pspace);
   if (p_smob == NULL)
     {
       SCM p_scm = psscm_make_pspace_smob ();
@@ -165,7 +155,7 @@ psscm_pspace_smob_from_pspace (struct program_space *pspace)
       p_smob = (pspace_smob *) SCM_SMOB_DATA (p_scm);
       p_smob->pspace = pspace;
 
-      set_program_space_data (pspace, psscm_pspace_data_key, p_smob);
+      psscm_pspace_data_key.set (pspace, p_smob);
       scm_gc_protect_object (p_smob->containing_scm);
     }
 
@@ -418,12 +408,3 @@ gdbscm_initialize_pspaces (void)
 
   gdbscm_define_functions (pspace_functions, 1);
 }
-
-void _initialize_scm_progspace ();
-void
-_initialize_scm_progspace ()
-{
-  psscm_pspace_data_key
-    = register_program_space_data_with_cleanup (NULL,
-                                               psscm_handle_pspace_deleted);
-}
index 55eac3cfff69dbdbcbb539d16f96bf2af776fea2..0b96e5a02c15eb479cb19098fd1cfa8ce9bc52f4 100644 (file)
@@ -49,7 +49,37 @@ static SCM block_keyword;
 static SCM domain_keyword;
 static SCM frame_keyword;
 
-static const struct objfile_data *syscm_objfile_data_key;
+/* This is called when an objfile is about to be freed.
+   Invalidate the symbol as further actions on the symbol would result
+   in bad data.  All access to s_smob->symbol should be gated by
+   syscm_get_valid_symbol_smob_arg_unsafe which will raise an exception on
+   invalid symbols.  */
+struct syscm_deleter
+{
+  /* Helper function for syscm_del_objfile_symbols to mark the symbol
+     as invalid.  */
+
+  static int
+  syscm_mark_symbol_invalid (void **slot, void *info)
+  {
+    symbol_smob *s_smob = (symbol_smob *) *slot;
+
+    s_smob->symbol = NULL;
+    return 1;
+  }
+
+  void operator() (htab_t htab)
+  {
+    if (htab != NULL)
+      {
+       htab_traverse_noresize (htab, syscm_mark_symbol_invalid, NULL);
+       htab_delete (htab);
+      }
+  }
+};
+
+static const registry<objfile>::key<htab, syscm_deleter>
+     syscm_objfile_data_key;
 static struct gdbarch_data *syscm_gdbarch_data_key;
 
 struct syscm_gdbarch_data
@@ -105,12 +135,12 @@ syscm_get_symbol_map (struct symbol *symbol)
     {
       struct objfile *objfile = symbol->objfile ();
 
-      htab = (htab_t) objfile_data (objfile, syscm_objfile_data_key);
+      htab = syscm_objfile_data_key.get (objfile);
       if (htab == NULL)
        {
          htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
                                                     syscm_eq_symbol_smob);
-         set_objfile_data (objfile, syscm_objfile_data_key, htab);
+         syscm_objfile_data_key.set (objfile, htab);
        }
     }
   else
@@ -291,35 +321,6 @@ syscm_get_valid_symbol_arg_unsafe (SCM self, int arg_pos,
   return s_smob->symbol;
 }
 
-/* Helper function for syscm_del_objfile_symbols to mark the symbol
-   as invalid.  */
-
-static int
-syscm_mark_symbol_invalid (void **slot, void *info)
-{
-  symbol_smob *s_smob = (symbol_smob *) *slot;
-
-  s_smob->symbol = NULL;
-  return 1;
-}
-
-/* This function is called when an objfile is about to be freed.
-   Invalidate the symbol as further actions on the symbol would result
-   in bad data.  All access to s_smob->symbol should be gated by
-   syscm_get_valid_symbol_smob_arg_unsafe which will raise an exception on
-   invalid symbols.  */
-
-static void
-syscm_del_objfile_symbols (struct objfile *objfile, void *datum)
-{
-  htab_t htab = (htab_t) datum;
-
-  if (htab != NULL)
-    {
-      htab_traverse_noresize (htab, syscm_mark_symbol_invalid, NULL);
-      htab_delete (htab);
-    }
-}
 \f
 /* Symbol methods.  */
 
@@ -823,11 +824,6 @@ void _initialize_scm_symbol ();
 void
 _initialize_scm_symbol ()
 {
-  /* Register an objfile "free" callback so we can properly
-     invalidate symbols when an object file is about to be deleted.  */
-  syscm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, syscm_del_objfile_symbols);
-
   /* Arch-specific symbol data.  */
   syscm_gdbarch_data_key
     = gdbarch_data_register_post_init (syscm_init_arch_symbols);
index 518ceeaa15dc687e6b7578ec4e6ec9db8cea1caa..940823147bf2e5f449994f65cd2dc3b98e4c9376 100644 (file)
@@ -77,7 +77,37 @@ static const char sal_smob_name[] = "gdb:sal";
 static scm_t_bits symtab_smob_tag;
 static scm_t_bits sal_smob_tag;
 
-static const struct objfile_data *stscm_objfile_data_key;
+/* This is called when an objfile is about to be freed.
+   Invalidate the symbol table as further actions on the symbol table
+   would result in bad data.  All access to st_smob->symtab should be
+   gated by stscm_get_valid_symtab_smob_arg_unsafe which will raise an
+   exception on invalid symbol tables.  */
+struct stscm_deleter
+{
+  /* Helper function for stscm_del_objfile_symtabs to mark the symtab
+     as invalid.  */
+
+  static int
+  stscm_mark_symtab_invalid (void **slot, void *info)
+  {
+    symtab_smob *st_smob = (symtab_smob *) *slot;
+
+    st_smob->symtab = NULL;
+    return 1;
+  }
+
+  void operator() (htab_t htab)
+  {
+    if (htab != NULL)
+      {
+       htab_traverse_noresize (htab, stscm_mark_symtab_invalid, NULL);
+       htab_delete (htab);
+      }
+  }
+};
+
+static const registry<objfile>::key<htab, stscm_deleter>
+     stscm_objfile_data_key;
 \f
 /* Administrivia for symtab smobs.  */
 
@@ -110,13 +140,13 @@ static htab_t
 stscm_objfile_symtab_map (struct symtab *symtab)
 {
   struct objfile *objfile = symtab->compunit ()->objfile ();
-  htab_t htab = (htab_t) objfile_data (objfile, stscm_objfile_data_key);
+  htab_t htab = stscm_objfile_data_key.get (objfile);
 
   if (htab == NULL)
     {
       htab = gdbscm_create_eqable_gsmob_ptr_map (stscm_hash_symtab_smob,
                                                 stscm_eq_symtab_smob);
-      set_objfile_data (objfile, stscm_objfile_data_key, htab);
+      stscm_objfile_data_key.set (objfile, htab);
     }
 
   return htab;
@@ -271,35 +301,6 @@ stscm_get_valid_symtab_smob_arg_unsafe (SCM self, int arg_pos,
   return st_smob;
 }
 
-/* Helper function for stscm_del_objfile_symtabs to mark the symtab
-   as invalid.  */
-
-static int
-stscm_mark_symtab_invalid (void **slot, void *info)
-{
-  symtab_smob *st_smob = (symtab_smob *) *slot;
-
-  st_smob->symtab = NULL;
-  return 1;
-}
-
-/* This function is called when an objfile is about to be freed.
-   Invalidate the symbol table as further actions on the symbol table
-   would result in bad data.  All access to st_smob->symtab should be
-   gated by stscm_get_valid_symtab_smob_arg_unsafe which will raise an
-   exception on invalid symbol tables.  */
-
-static void
-stscm_del_objfile_symtabs (struct objfile *objfile, void *datum)
-{
-  htab_t htab = (htab_t) datum;
-
-  if (htab != NULL)
-    {
-      htab_traverse_noresize (htab, stscm_mark_symtab_invalid, NULL);
-      htab_delete (htab);
-    }
-}
 \f
 /* Symbol table methods.  */
 
@@ -687,14 +688,3 @@ gdbscm_initialize_symtabs (void)
 
   gdbscm_define_functions (symtab_functions, 1);
 }
-
-void _initialize_scm_symtab ();
-void
-_initialize_scm_symtab ()
-{
-  /* Register an objfile "free" callback so we can properly
-     invalidate symbol tables, and symbol table and line data
-     structures when an object file that is about to be deleted.  */
-  stscm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, stscm_del_objfile_symtabs);
-}
index dd7eace8d40f69df275c1cd0337ae09a54cb9fd0..2dadbefb3a4494fee348a3518757c7cd1e0198bf 100644 (file)
@@ -81,7 +81,30 @@ static SCM tyscm_next_field_x_proc;
 /* Keywords used in argument passing.  */
 static SCM block_keyword;
 
-static const struct objfile_data *tyscm_objfile_data_key;
+static int tyscm_copy_type_recursive (void **slot, void *info);
+
+/* Called when an objfile is about to be deleted.
+   Make a copy of all types associated with OBJFILE.  */
+
+struct tyscm_deleter
+{
+  void operator() (htab_t htab)
+  {
+    if (!gdb_scheme_initialized)
+      return;
+
+    htab_up copied_types = create_copied_types_hash ();
+
+    if (htab != NULL)
+      {
+       htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ());
+       htab_delete (htab);
+      }
+  }
+};
+
+static const registry<objfile>::key<htab, tyscm_deleter>
+     tyscm_objfile_data_key;
 
 /* Hash table to uniquify global (non-objfile-owned) types.  */
 static htab_t global_types_map;
@@ -158,12 +181,12 @@ tyscm_type_map (struct type *type)
   if (objfile == NULL)
     return global_types_map;
 
-  htab = (htab_t) objfile_data (objfile, tyscm_objfile_data_key);
+  htab = tyscm_objfile_data_key.get (objfile);
   if (htab == NULL)
     {
       htab = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob,
                                                 tyscm_eq_type_smob);
-      set_objfile_data (objfile, tyscm_objfile_data_key, htab);
+      tyscm_objfile_data_key.set (objfile, htab);
     }
 
   return htab;
@@ -345,20 +368,17 @@ tyscm_scm_to_type (SCM t_scm)
   return t_smob->type;
 }
 
-/* Helper function for save_objfile_types to make a deep copy of the type.  */
+/* Helper function to make a deep copy of the type.  */
 
 static int
 tyscm_copy_type_recursive (void **slot, void *info)
 {
   type_smob *t_smob = (type_smob *) *slot;
   htab_t copied_types = (htab_t) info;
-  struct objfile *objfile = t_smob->type->objfile_owner ();
   htab_t htab;
   eqable_gdb_smob **new_slot;
   type_smob t_smob_for_lookup;
 
-  gdb_assert (objfile != NULL);
-
   htab_empty (copied_types);
   t_smob->type = copy_type_recursive (t_smob->type, copied_types);
 
@@ -380,25 +400,6 @@ tyscm_copy_type_recursive (void **slot, void *info)
   return 1;
 }
 
-/* Called when OBJFILE is about to be deleted.
-   Make a copy of all types associated with OBJFILE.  */
-
-static void
-save_objfile_types (struct objfile *objfile, void *datum)
-{
-  htab_t htab = (htab_t) datum;
-
-  if (!gdb_scheme_initialized)
-    return;
-
-  htab_up copied_types = create_copied_types_hash ();
-
-  if (htab != NULL)
-    {
-      htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ());
-      htab_delete (htab);
-    }
-}
 \f
 /* Administrivia for field smobs.  */
 
@@ -1510,13 +1511,3 @@ Internal function to assist the type fields iterator."));
   global_types_map = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob,
                                                         tyscm_eq_type_smob);
 }
-
-void _initialize_scm_type ();
-void
-_initialize_scm_type ()
-{
-  /* Register an objfile "free" callback so we can properly copy types
-     associated with the objfile when it's about to be deleted.  */
-  tyscm_objfile_data_key
-    = register_objfile_data_with_cleanup (save_objfile_types, NULL);
-}
index 9f93a945a6a3ec9b10d8abaa47a72bb023f40f8d..54b3d22a2d093062ebb17287b17f2765da384eca 100644 (file)
@@ -84,7 +84,8 @@ struct hppa_objfile_private
    that separately and make this static. The solib data is probably hpux-
    specific, so we can create a separate extern objfile_data that is registered
    by hppa-hpux-tdep.c and shared with pa64solib.c and somsolib.c.  */
-static const struct objfile_key<hppa_objfile_private> hppa_objfile_priv_data;
+static const registry<objfile>::key<hppa_objfile_private>
+  hppa_objfile_priv_data;
 
 /* Get at various relevant fields of an instruction word.  */
 #define MASK_5 0x1f
index 606b4189181df7a3916fa3b28cb3c67f1adff4cd..7eb2bd97907832df22b485a1eb227de2afcc778e 100644 (file)
 #include "gdbsupport/buildargv.h"
 #include "cli/cli-style.h"
 
-/* Keep a registry of per-inferior data-pointers required by other GDB
-   modules.  */
-
-DEFINE_REGISTRY (inferior, REGISTRY_ACCESS_FIELD)
-
 intrusive_list<inferior> inferior_list;
 static int highest_inferior_num;
 
@@ -76,18 +71,14 @@ inferior::~inferior ()
   inferior *inf = this;
 
   m_continuations.clear ();
-  inferior_free_data (inf);
   target_desc_info_free (inf->tdesc_info);
 }
 
 inferior::inferior (int pid_)
   : num (++highest_inferior_num),
     pid (pid_),
-    environment (gdb_environ::from_host_environ ()),
-    registry_data ()
+    environment (gdb_environ::from_host_environ ())
 {
-  inferior_alloc_data (this);
-
   m_target_stack.push (get_dummy_target ());
 }
 
index c376d780de0c9ff4104dbe1ee5f08373d03a01a1..017800165b4b39bdf6dd47bc43cc69a4e535b449 100644 (file)
@@ -595,7 +595,7 @@ public:
   displaced_step_inferior_state displaced_step_state;
 
   /* Per inferior data-pointers required by other GDB modules.  */
-  REGISTRY_FIELDS;
+  registry<inferior> registry_fields;
 
 private:
   /* The inferior's target stack.  */
@@ -615,11 +615,6 @@ private:
   std::string m_cwd;
 };
 
-/* Keep a registry of per-inferior data-pointers required by other GDB
-   modules.  */
-
-DECLARE_REGISTRY (inferior);
-
 /* Add an inferior to the inferior list, print a message that a new
    inferior is found, and return the pointer to the new inferior.
    Caller may use this pointer to initialize the private inferior
index 9c7e2907625a9004a1cf7b67ac429082a8ef97d1..5477624bcd5bb68a1f8ae51cf9cad315a8e6f90b 100644 (file)
@@ -599,7 +599,7 @@ child_pass_ctrlc (struct target_ops *self)
 }
 
 /* Per-inferior data key.  */
-static const struct inferior_key<terminal_info> inflow_inferior_data;
+static const registry<inferior>::key<terminal_info> inflow_inferior_data;
 
 terminal_info::~terminal_info ()
 {
index 8a83ed320cfeec937837a833c182f12634b4cbdf..4e6a48b1d206118888d3ed3c9281824fdc160a2d 100644 (file)
@@ -236,7 +236,7 @@ struct linux_info
 };
 
 /* Per-inferior data key.  */
-static const struct inferior_key<linux_info> linux_inferior_data;
+static const registry<inferior>::key<linux_info> linux_inferior_data;
 
 /* Frees whatever allocated space there is to be freed and sets INF's
    linux cache data pointer to NULL.  */
index a2280c3ba8d9f5d7c0ba73467ee4fe862d010c11..001042b9cf529e23156717e1db85ef6139c5e2f1 100644 (file)
@@ -1354,8 +1354,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
 
 /* Basic types.  */
 
-static const struct objfile_key<struct type *,
-                               gdb::noop_deleter<struct type *>>
+static const registry<objfile>::key<struct type *,
+                                   gdb::noop_deleter<struct type *>>
   basic_type_data;
 
 static struct type *
index e94768ac69ca38a93df56566a9b6ec6fa0cc4310..dbbdf85e08cc612213ea9921a6d4d32c094d67dd 100644 (file)
@@ -28,7 +28,7 @@
 
 /* We stash a reference to the .gnu_debugdata BFD on the enclosing
    BFD.  */
-static const bfd_key<gdb_bfd_ref_ptr> gnu_debug_key;
+static const registry<bfd>::key<gdb_bfd_ref_ptr> gnu_debug_key;
 
 #include <lzma.h>
 
index 9b08adfa18c0088c6eb1ad7cc59349f82e1f9a64..301d403eb137c02ab7d2f1755a7f4750511f5163 100644 (file)
@@ -51,7 +51,7 @@ static char default_nto_target[] = "";
 
 struct nto_target_ops current_nto_target;
 
-static const struct inferior_key<struct nto_inferior_data>
+static const registry<inferior>::key<struct nto_inferior_data>
   nto_inferior_data_reg;
 
 static char *
index 37008da529a688ba87533879de0e8bbe2c34039b..4429d4a7d44a7045d571c50fdb4de42e62474043 100644 (file)
@@ -76,7 +76,7 @@ struct objc_method {
   CORE_ADDR imp;
 };
 
-static const struct objfile_key<unsigned int> objc_objfile_data;
+static const registry<objfile>::key<unsigned int> objc_objfile_data;
 
 /* Lookup a structure type named "struct NAME", visible in lexical
    block BLOCK.  If NOERR is nonzero, return zero if NAME is not
index f4625575473440515ce61927fb7952e4434ffe6f..7759311afca14e93c1a3775d156716f8b3c2a8df 100644 (file)
 #include <algorithm>
 #include <vector>
 
-/* Keep a registry of per-objfile data-pointers required by other GDB
-   modules.  */
-
-DEFINE_REGISTRY (objfile, REGISTRY_ACCESS_FIELD)
-
 /* Externally visible variables that are owned by this module.
    See declarations in objfile.h for more info.  */
 
@@ -85,7 +80,7 @@ struct objfile_pspace_info
 };
 
 /* Per-program-space data key.  */
-static const struct program_space_key<objfile_pspace_info>
+static const registry<program_space>::key<objfile_pspace_info>
   objfiles_pspace_data;
 
 objfile_pspace_info::~objfile_pspace_info ()
@@ -112,7 +107,7 @@ get_objfile_pspace_data (struct program_space *pspace)
 
 /* Per-BFD data key.  */
 
-static const struct bfd_key<objfile_per_bfd_storage> objfiles_bfd_data;
+static const registry<bfd>::key<objfile_per_bfd_storage> objfiles_bfd_data;
 
 objfile_per_bfd_storage::~objfile_per_bfd_storage ()
 {
@@ -329,8 +324,6 @@ objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
      gdb_obstack.h specifies the alloc/dealloc functions.  */
   obstack_init (&objfile_obstack);
 
-  objfile_alloc_data (this);
-
   std::string name_holder;
   if (name == NULL)
     {
@@ -563,10 +556,6 @@ objfile::~objfile ()
   if (sf != NULL)
     (*sf->sym_finish) (this);
 
-  /* Discard any data modules have associated with the objfile.  The function
-     still may reference obfd.  */
-  objfile_free_data (this);
-
   if (obfd)
     gdb_bfd_unref (obfd);
   else
index a7098b46279cb6601917be35b10906e1b3929f67..e724a4e87648830397278782faebdaf02eff63ce 100644 (file)
@@ -682,7 +682,7 @@ public:
 
   /* Per objfile data-pointers required by other GDB modules.  */
 
-  REGISTRY_FIELDS {};
+  registry<objfile> registry_fields;
 
   /* Set of relocation offsets to apply to each section.
      The table is indexed by the_bfd_section->index, thus it is generally
@@ -900,10 +900,6 @@ in_plt_section (CORE_ADDR pc)
          || pc_in_section (pc, ".plt.sec"));
 }
 
-/* Keep a registry of per-objfile data-pointers required by other GDB
-   modules.  */
-DECLARE_REGISTRY(objfile);
-
 /* In normal use, the section map will be rebuilt by find_pc_section
    if objfiles have been added, removed or relocated since it was last
    called.  Calling inhibit_section_map_updates will inhibit this
index c2e2da5a7dc947f5f28ecb91b36b16fa212a4f0e..90003d964fe775b4c4ce1fa582f91793b75ac8a4 100644 (file)
@@ -43,24 +43,11 @@ static int highest_address_space_num;
 
 \f
 
-/* Keep a registry of per-program_space data-pointers required by other GDB
-   modules.  */
-
-DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD)
-
-/* Keep a registry of per-address_space data-pointers required by other GDB
-   modules.  */
-
-DEFINE_REGISTRY (address_space, REGISTRY_ACCESS_FIELD)
-
-\f
-
 /* Create a new address space object, and add it to the list.  */
 
 address_space::address_space ()
   : m_num (++highest_address_space_num)
 {
-  address_space_alloc_data (this);
 }
 
 /* Maybe create a new address space object, and add it to the list, or
@@ -81,11 +68,6 @@ maybe_new_address_space (void)
   return new address_space ();
 }
 
-address_space::~address_space ()
-{
-  address_space_free_data (this);
-}
-
 /* Start counting over from scratch.  */
 
 static void
@@ -115,8 +97,6 @@ program_space::program_space (address_space *aspace_)
   : num (++last_program_space_num),
     aspace (aspace_)
 {
-  program_space_alloc_data (this);
-
   program_spaces.push_back (this);
 }
 
@@ -140,8 +120,6 @@ program_space::~program_space ()
   clear_symtab_users (SYMFILE_DEFER_BP_RESET);
   if (!gdbarch_has_shared_address_space (target_gdbarch ()))
     delete this->aspace;
-    /* Discard any data modules have associated with the PSPACE.  */
-  program_space_free_data (this);
 }
 
 /* See progspace.h.  */
index 8531da4a095ee4e343755490d314467acd4209b7..febdcef40282a8fa9ef377511beb7d05d3b1ded5 100644 (file)
@@ -37,8 +37,7 @@ struct objfile;
 struct inferior;
 struct exec;
 struct address_space;
-struct program_space_data;
-struct address_space_data;
+struct program_space;
 struct so_list;
 
 typedef std::list<std::unique_ptr<objfile>> objfile_list;
@@ -372,7 +371,7 @@ struct program_space
   std::vector<std::string> deleted_solibs;
 
   /* Per pspace data-pointers required by other GDB modules.  */
-  REGISTRY_FIELDS {};
+  registry<program_space> registry_fields;
 
 private:
   /* The set of target sections matching the sections mapped into
@@ -387,7 +386,6 @@ struct address_space
 {
   /* Create a new address space object, and add it to the list.  */
   address_space ();
-  ~address_space ();
   DISABLE_COPY_AND_ASSIGN (address_space);
 
   /* Returns the integer address space id of this address space.  */
@@ -397,7 +395,7 @@ struct address_space
   }
 
   /* Per aspace data-pointers required by other GDB modules.  */
-  REGISTRY_FIELDS {};
+  registry<address_space> registry_fields;
 
 private:
   int m_num;
@@ -457,14 +455,4 @@ extern struct address_space *maybe_new_address_space (void);
    mappings.  */
 extern void update_address_spaces (void);
 
-/* Keep a registry of per-pspace data-pointers required by other GDB
-   modules.  */
-
-DECLARE_REGISTRY (program_space);
-
-/* Keep a registry of per-aspace data-pointers required by other GDB
-   modules.  */
-
-DECLARE_REGISTRY (address_space);
-
 #endif
index 872fb89ba834a0bf1c85aaf571d98c8153352232..b9aea3aca69ca84430c7b1477cb299eaebf65999 100644 (file)
@@ -77,9 +77,33 @@ struct block_syms_iterator_object {
       }                                                                        \
   } while (0)
 
+/* This is called when an objfile is about to be freed.
+   Invalidate the block as further actions on the block would result
+   in bad data.  All access to obj->symbol should be gated by
+   BLPY_REQUIRE_VALID which will raise an exception on invalid
+   blocks.  */
+struct blpy_deleter
+{
+  void operator() (block_object *obj)
+  {
+    while (obj)
+      {
+       block_object *next = obj->next;
+
+       obj->block = NULL;
+       obj->objfile = NULL;
+       obj->next = NULL;
+       obj->prev = NULL;
+
+       obj = next;
+      }
+  }
+};
+
 extern PyTypeObject block_syms_iterator_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("block_syms_iterator_object");
-static const struct objfile_data *blpy_objfile_data_key;
+static const registry<objfile>::key<block_object, blpy_deleter>
+     blpy_objfile_data_key;
 
 static PyObject *
 blpy_iter (PyObject *self)
@@ -269,10 +293,7 @@ blpy_dealloc (PyObject *obj)
   if (block->prev)
     block->prev->next = block->next;
   else if (block->objfile)
-    {
-      set_objfile_data (block->objfile, blpy_objfile_data_key,
-                       block->next);
-    }
+    blpy_objfile_data_key.set (block->objfile, block->next);
   if (block->next)
     block->next->prev = block->prev;
   block->block = NULL;
@@ -293,11 +314,10 @@ set_block (block_object *obj, const struct block *block,
   if (objfile)
     {
       obj->objfile = objfile;
-      obj->next = ((block_object *)
-                  objfile_data (objfile, blpy_objfile_data_key));
+      obj->next = blpy_objfile_data_key.get (objfile);
       if (obj->next)
        obj->next->prev = obj;
-      set_objfile_data (objfile, blpy_objfile_data_key, obj);
+      blpy_objfile_data_key.set (objfile, obj);
     }
   else
     obj->next = NULL;
@@ -404,40 +424,6 @@ blpy_iter_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
-/* This function is called when an objfile is about to be freed.
-   Invalidate the block as further actions on the block would result
-   in bad data.  All access to obj->symbol should be gated by
-   BLPY_REQUIRE_VALID which will raise an exception on invalid
-   blocks.  */
-static void
-del_objfile_blocks (struct objfile *objfile, void *datum)
-{
-  block_object *obj = (block_object *) datum;
-
-  while (obj)
-    {
-      block_object *next = obj->next;
-
-      obj->block = NULL;
-      obj->objfile = NULL;
-      obj->next = NULL;
-      obj->prev = NULL;
-
-      obj = next;
-    }
-}
-
-void _initialize_py_block ();
-void
-_initialize_py_block ()
-{
-  /* Register an objfile "free" callback so we can properly
-     invalidate blocks when an object file is about to be
-     deleted.  */
-  blpy_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
-}
-
 int
 gdbpy_initialize_blocks (void)
 {
index 61ed342d1c1b7da826ec57b7144065afe512e929..6ea384e26a0595c1660fb382486ad198b6f0c670 100644 (file)
@@ -60,7 +60,35 @@ struct inferior_object
 extern PyTypeObject inferior_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
 
-static const struct inferior_data *infpy_inf_data_key;
+/* Deleter to clean up when an inferior is removed.  */
+struct infpy_deleter
+{
+  void operator() (inferior_object *obj)
+  {
+    struct threadlist_entry *th_entry, *th_tmp;
+
+    if (!gdb_python_initialized)
+      return;
+
+    gdbpy_enter enter_py;
+    gdbpy_ref<inferior_object> inf_obj (obj);
+
+    inf_obj->inferior = NULL;
+
+    /* Deallocate threads list.  */
+    for (th_entry = inf_obj->threads; th_entry != NULL;)
+      {
+       th_tmp = th_entry;
+       th_entry = th_entry->next;
+       delete th_tmp;
+      }
+
+    inf_obj->nthreads = 0;
+  }
+};
+
+static const registry<inferior>::key<inferior_object, infpy_deleter>
+     infpy_inf_data_key;
 
 /* Require that INFERIOR be a valid inferior ID.  */
 #define INFPY_REQUIRE_VALID(Inferior)                          \
@@ -221,7 +249,7 @@ inferior_to_inferior_object (struct inferior *inferior)
 {
   inferior_object *inf_obj;
 
-  inf_obj = (inferior_object *) inferior_data (inferior, infpy_inf_data_key);
+  inf_obj = infpy_inf_data_key.get (inferior);
   if (!inf_obj)
     {
       inf_obj = PyObject_New (inferior_object, &inferior_object_type);
@@ -234,7 +262,7 @@ inferior_to_inferior_object (struct inferior *inferior)
 
       /* PyObject_New initializes the new object with a refcount of 1.  This
         counts for the reference we are keeping in the inferior data.  */
-      set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
+      infpy_inf_data_key.set (inferior, inf_obj);
     }
 
   /* We are returning a new reference.  */
@@ -795,32 +823,6 @@ infpy_dealloc (PyObject *obj)
   Py_TYPE (obj)->tp_free (obj);
 }
 
-/* Clear the INFERIOR pointer in an Inferior object and clear the
-   thread list.  */
-static void
-py_free_inferior (struct inferior *inf, void *datum)
-{
-  struct threadlist_entry *th_entry, *th_tmp;
-
-  if (!gdb_python_initialized)
-    return;
-
-  gdbpy_enter enter_py;
-  gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
-
-  inf_obj->inferior = NULL;
-
-  /* Deallocate threads list.  */
-  for (th_entry = inf_obj->threads; th_entry != NULL;)
-    {
-      th_tmp = th_entry;
-      th_entry = th_entry->next;
-      delete th_tmp;
-    }
-
-  inf_obj->nthreads = 0;
-}
-
 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
    Returns the current inferior object.  */
 
@@ -831,14 +833,6 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args)
          inferior_to_inferior_object (current_inferior ()).release ());
 }
 
-void _initialize_py_inferior ();
-void
-_initialize_py_inferior ()
-{
-  infpy_inf_data_key =
-    register_inferior_data_with_cleanup (NULL, py_free_inferior);
-}
-
 int
 gdbpy_initialize_inferior (void)
 {
index 298f3f23632776bd1e4df3206825231416631189..4cc570286dc910a3cfb5181e68a0781b00ae4893 100644 (file)
@@ -55,7 +55,20 @@ struct objfile_object
 extern PyTypeObject objfile_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_object");
 
-static const struct objfile_data *objfpy_objfile_data_key;
+/* Clear the OBJFILE pointer in an Objfile object and remove the
+   reference.  */
+struct objfpy_deleter
+{
+  void operator() (objfile_object *obj)
+  {
+    gdbpy_enter enter_py;
+    gdbpy_ref<objfile_object> object (obj);
+    object->objfile = nullptr;
+  }
+};
+
+static const registry<objfile>::key<objfile_object, objfpy_deleter>
+     objfpy_objfile_data_key;
 
 /* Require that OBJF be a valid objfile.  */
 #define OBJFPY_REQUIRE_VALID(obj)                              \
@@ -668,16 +681,6 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
 
 \f
 
-/* Clear the OBJFILE pointer in an Objfile object and remove the
-   reference.  */
-static void
-py_free_objfile (struct objfile *objfile, void *datum)
-{
-  gdbpy_enter enter_py (objfile->arch ());
-  gdbpy_ref<objfile_object> object ((objfile_object *) datum);
-  object->objfile = NULL;
-}
-
 /* Return a new reference to the Python object of type Objfile
    representing OBJFILE.  If the object has already been created,
    return it.  Otherwise, create it.  Return NULL and set the Python
@@ -687,7 +690,7 @@ gdbpy_ref<>
 objfile_to_objfile_object (struct objfile *objfile)
 {
   PyObject *result
-    = ((PyObject *) objfile_data (objfile, objfpy_objfile_data_key));
+    = (PyObject *) objfpy_objfile_data_key.get (objfile);
   if (result == NULL)
     {
       gdbpy_ref<objfile_object> object
@@ -698,21 +701,13 @@ objfile_to_objfile_object (struct objfile *objfile)
        return NULL;
 
       object->objfile = objfile;
-      set_objfile_data (objfile, objfpy_objfile_data_key, object.get ());
+      objfpy_objfile_data_key.set (objfile, object.get ());
       result = (PyObject *) object.release ();
     }
 
   return gdbpy_ref<>::new_reference (result);
 }
 
-void _initialize_py_objfile ();
-void
-_initialize_py_objfile ()
-{
-  objfpy_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, py_free_objfile);
-}
-
 int
 gdbpy_initialize_objfile (void)
 {
index 5ec5986fce87edec4b09623e3f0387a0d767b544..4eb33e8292f3fb4c21f301bfef55e8d93553b0f1 100644 (file)
@@ -57,7 +57,30 @@ struct pspace_object
 extern PyTypeObject pspace_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object");
 
-static const struct program_space_data *pspy_pspace_data_key;
+/* Clear the PSPACE pointer in a Pspace object and remove the reference.  */
+struct pspace_deleter
+{
+  void operator() (pspace_object *obj)
+  {
+    /* This is a fiction, but we're in a nasty spot: The pspace is in the
+       process of being deleted, we can't rely on anything in it.  Plus
+       this is one time when the current program space and current inferior
+       are not in sync: All inferiors that use PSPACE may no longer exist.
+       We don't need to do much here, and since "there is always an inferior"
+       using target_gdbarch suffices.
+       Note: We cannot call get_current_arch because it may try to access
+       the target, which may involve accessing data in the pspace currently
+       being deleted.  */
+    struct gdbarch *arch = target_gdbarch ();
+
+    gdbpy_enter enter_py (arch);
+    gdbpy_ref<pspace_object> object (obj);
+    object->pspace = NULL;
+  }
+};
+
+static const registry<program_space>::key<pspace_object, pspace_deleter>
+     pspy_pspace_data_key;
 
 /* Require that PSPACE_OBJ be a valid program space ID.  */
 #define PSPY_REQUIRE_VALID(pspace_obj)                         \
@@ -463,27 +486,6 @@ pspy_is_valid (PyObject *o, PyObject *args)
 
 \f
 
-/* Clear the PSPACE pointer in a Pspace object and remove the reference.  */
-
-static void
-py_free_pspace (struct program_space *pspace, void *datum)
-{
-  /* This is a fiction, but we're in a nasty spot: The pspace is in the
-     process of being deleted, we can't rely on anything in it.  Plus
-     this is one time when the current program space and current inferior
-     are not in sync: All inferiors that use PSPACE may no longer exist.
-     We don't need to do much here, and since "there is always an inferior"
-     using target_gdbarch suffices.
-     Note: We cannot call get_current_arch because it may try to access
-     the target, which may involve accessing data in the pspace currently
-     being deleted.  */
-  struct gdbarch *arch = target_gdbarch ();
-
-  gdbpy_enter enter_py (arch);
-  gdbpy_ref<pspace_object> object ((pspace_object *) datum);
-  object->pspace = NULL;
-}
-
 /* Return a new reference to the Python object of type Pspace
    representing PSPACE.  If the object has already been created,
    return it.  Otherwise, create it.  Return NULL and set the Python
@@ -492,8 +494,7 @@ py_free_pspace (struct program_space *pspace, void *datum)
 gdbpy_ref<>
 pspace_to_pspace_object (struct program_space *pspace)
 {
-  PyObject *result
-    ((PyObject *) program_space_data (pspace, pspy_pspace_data_key));
+  PyObject *result = (PyObject *) pspy_pspace_data_key.get (pspace);
   if (result == NULL)
     {
       gdbpy_ref<pspace_object> object
@@ -504,7 +505,7 @@ pspace_to_pspace_object (struct program_space *pspace)
        return NULL;
 
       object->pspace = pspace;
-      set_program_space_data (pspace, pspy_pspace_data_key, object.get ());
+      pspy_pspace_data_key.set (pspace, object.get ());
       result = (PyObject *) object.release ();
     }
 
@@ -528,14 +529,6 @@ gdbpy_is_progspace (PyObject *obj)
   return PyObject_TypeCheck (obj, &pspace_object_type);
 }
 
-void _initialize_py_progspace ();
-void
-_initialize_py_progspace ()
-{
-  pspy_pspace_data_key
-    = register_program_space_data_with_cleanup (NULL, py_free_pspace);
-}
-
 int
 gdbpy_initialize_pspace (void)
 {
index 23495b66d422352a8c15eac7bda131ad69e65261..e5fe5cf8c923663e0dd66e52bd395c8dc32f31f3 100644 (file)
@@ -50,7 +50,26 @@ struct symbol_object {
       }                                                        \
   } while (0)
 
-static const struct objfile_data *sympy_objfile_data_key;
+/* A deleter that is used when an objfile is about to be freed.  */
+struct symbol_object_deleter
+{
+  void operator() (symbol_object *obj)
+  {
+    while (obj)
+      {
+       symbol_object *next = obj->next;
+
+       obj->symbol = NULL;
+       obj->next = NULL;
+       obj->prev = NULL;
+
+       obj = next;
+      }
+  }
+};
+
+static const registry<objfile>::key<symbol_object, symbol_object_deleter>
+     sympy_objfile_data_key;
 
 static PyObject *
 sympy_str (PyObject *self)
@@ -307,11 +326,10 @@ set_symbol (symbol_object *obj, struct symbol *symbol)
     {
       struct objfile *objfile = symbol->objfile ();
 
-      obj->next = ((symbol_object *)
-                  objfile_data (objfile, sympy_objfile_data_key));
+      obj->next = sympy_objfile_data_key.get (objfile);
       if (obj->next)
        obj->next->prev = obj;
-      set_objfile_data (objfile, sympy_objfile_data_key, obj);
+      sympy_objfile_data_key.set (objfile, obj);
     }
   else
     obj->next = NULL;
@@ -350,10 +368,7 @@ sympy_dealloc (PyObject *obj)
   else if (sym_obj->symbol != NULL
           && sym_obj->symbol->is_objfile_owned ()
           && sym_obj->symbol->symtab () != NULL)
-    {
-      set_objfile_data (sym_obj->symbol->objfile (),
-                       sympy_objfile_data_key, sym_obj->next);
-    }
+    sympy_objfile_data_key.set (sym_obj->symbol->objfile (), sym_obj->next);
   if (sym_obj->next)
     sym_obj->next->prev = sym_obj->prev;
   sym_obj->symbol = NULL;
@@ -596,38 +611,6 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
   return return_list.release ();
 }
 
-/* This function is called when an objfile is about to be freed.
-   Invalidate the symbol as further actions on the symbol would result
-   in bad data.  All access to obj->symbol should be gated by
-   SYMPY_REQUIRE_VALID which will raise an exception on invalid
-   symbols.  */
-static void
-del_objfile_symbols (struct objfile *objfile, void *datum)
-{
-  symbol_object *obj = (symbol_object *) datum;
-  while (obj)
-    {
-      symbol_object *next = obj->next;
-
-      obj->symbol = NULL;
-      obj->next = NULL;
-      obj->prev = NULL;
-
-      obj = next;
-    }
-}
-
-void _initialize_py_symbol ();
-void
-_initialize_py_symbol ()
-{
-  /* Register an objfile "free" callback so we can properly
-     invalidate symbol when an object file that is about to be
-     deleted.  */
-  sympy_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, del_objfile_symbols);
-}
-
 int
 gdbpy_initialize_symbols (void)
 {
index 7ed62716b67833502e1a8b17d73136cc85b91d51..03c274dfff615b0e7cd6443f83cdd3e0d669dddf 100644 (file)
@@ -37,9 +37,31 @@ struct symtab_object {
   symtab_object *next;
 };
 
+/* This function is called when an objfile is about to be freed.
+   Invalidate the symbol table as further actions on the symbol table
+   would result in bad data.  All access to obj->symtab should be
+   gated by STPY_REQUIRE_VALID which will raise an exception on
+   invalid symbol tables.  */
+struct stpy_deleter
+{
+  void operator() (symtab_object *obj)
+  {
+    while (obj)
+      {
+       symtab_object *next = obj->next;
+
+       obj->symtab = NULL;
+       obj->next = NULL;
+       obj->prev = NULL;
+       obj = next;
+      }
+  }
+};
+
 extern PyTypeObject symtab_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symtab_object");
-static const struct objfile_data *stpy_objfile_data_key;
+static const registry<objfile>::key<symtab_object, stpy_deleter>
+     stpy_objfile_data_key;
 
 /* Require a valid symbol table.  All access to symtab_object->symtab
    should be gated by this call.  */
@@ -68,9 +90,39 @@ struct sal_object {
   sal_object *next;
 };
 
+/* This is called when an objfile is about to be freed.  Invalidate
+   the sal object as further actions on the sal would result in bad
+   data.  All access to obj->sal should be gated by
+   SALPY_REQUIRE_VALID which will raise an exception on invalid symbol
+   table and line objects.  */
+struct salpy_deleter
+{
+  void operator() (sal_object *obj)
+  {
+    gdbpy_enter enter_py;
+
+    while (obj)
+      {
+       sal_object *next = obj->next;
+
+       gdbpy_ref<> tmp (obj->symtab);
+       obj->symtab = Py_None;
+       Py_INCREF (Py_None);
+
+       obj->next = NULL;
+       obj->prev = NULL;
+       xfree (obj->sal);
+       obj->sal = NULL;
+
+       obj = next;
+      }
+  }
+};
+
 extern PyTypeObject sal_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("sal_object");
-static const struct objfile_data *salpy_objfile_data_key;
+static const registry<objfile>::key<sal_object, salpy_deleter>
+     salpy_objfile_data_key;
 
 /* Require a valid symbol table and line object.  All access to
    sal_object->sal should be gated by this call.  */
@@ -246,10 +298,8 @@ stpy_dealloc (PyObject *obj)
   if (symtab->prev)
     symtab->prev->next = symtab->next;
   else if (symtab->symtab)
-    {
-      set_objfile_data (symtab->symtab->compunit ()->objfile (),
-                       stpy_objfile_data_key, symtab->next);
-    }
+    stpy_objfile_data_key.set (symtab->symtab->compunit ()->objfile (),
+                              symtab->next);
   if (symtab->next)
     symtab->next->prev = symtab->prev;
   symtab->symtab = NULL;
@@ -329,9 +379,9 @@ salpy_dealloc (PyObject *self)
   if (self_sal->prev)
     self_sal->prev->next = self_sal->next;
   else if (self_sal->symtab != Py_None)
-    set_objfile_data
+    salpy_objfile_data_key.set
       (symtab_object_to_symtab (self_sal->symtab)->compunit ()->objfile (),
-       salpy_objfile_data_key, self_sal->next);
+       self_sal->next);
 
   if (self_sal->next)
     self_sal->next->prev = self_sal->prev;
@@ -378,13 +428,11 @@ set_sal (sal_object *sal_obj, struct symtab_and_line sal)
       symtab *symtab = symtab_object_to_symtab (sal_obj->symtab);
 
       sal_obj->next
-       = ((sal_object *) objfile_data (symtab->compunit ()->objfile (),
-                                       salpy_objfile_data_key));
+       = salpy_objfile_data_key.get (symtab->compunit ()->objfile ());
       if (sal_obj->next)
        sal_obj->next->prev = sal_obj;
 
-      set_objfile_data (symtab->compunit ()->objfile (),
-                       salpy_objfile_data_key, sal_obj);
+      salpy_objfile_data_key.set (symtab->compunit ()->objfile (), sal_obj);
     }
   else
     sal_obj->next = NULL;
@@ -404,14 +452,10 @@ set_symtab (symtab_object *obj, struct symtab *symtab)
   obj->prev = NULL;
   if (symtab)
     {
-      obj->next
-       = ((symtab_object *)
-          objfile_data (symtab->compunit ()->objfile (),
-                        stpy_objfile_data_key));
+      obj->next = stpy_objfile_data_key.get (symtab->compunit ()->objfile ());
       if (obj->next)
        obj->next->prev = obj;
-      set_objfile_data (symtab->compunit ()->objfile (),
-                       stpy_objfile_data_key, obj);
+      stpy_objfile_data_key.set (symtab->compunit ()->objfile (), obj);
     }
   else
     obj->next = NULL;
@@ -465,68 +509,6 @@ symtab_object_to_symtab (PyObject *obj)
   return ((symtab_object *) obj)->symtab;
 }
 
-/* This function is called when an objfile is about to be freed.
-   Invalidate the symbol table as further actions on the symbol table
-   would result in bad data.  All access to obj->symtab should be
-   gated by STPY_REQUIRE_VALID which will raise an exception on
-   invalid symbol tables.  */
-static void
-del_objfile_symtab (struct objfile *objfile, void *datum)
-{
-  symtab_object *obj = (symtab_object *) datum;
-
-  while (obj)
-    {
-      symtab_object *next = obj->next;
-
-      obj->symtab = NULL;
-      obj->next = NULL;
-      obj->prev = NULL;
-      obj = next;
-    }
-}
-
-/* This function is called when an objfile is about to be freed.
-   Invalidate the sal object as further actions on the sal
-   would result in bad data.  All access to obj->sal should be
-   gated by SALPY_REQUIRE_VALID which will raise an exception on
-   invalid symbol table and line objects.  */
-static void
-del_objfile_sal (struct objfile *objfile, void *datum)
-{
-  sal_object *obj = (sal_object *) datum;
-
-  while (obj)
-    {
-      sal_object *next = obj->next;
-
-      gdbpy_ref<> tmp (obj->symtab);
-      obj->symtab = Py_None;
-      Py_INCREF (Py_None);
-
-      obj->next = NULL;
-      obj->prev = NULL;
-      xfree (obj->sal);
-      obj->sal = NULL;
-
-      obj = next;
-    }
-}
-
-void _initialize_py_symtab ();
-void
-_initialize_py_symtab ()
-{
-  /* Register an objfile "free" callback so we can properly
-     invalidate symbol tables, and symbol table and line data
-     structures when an object file that is about to be
-     deleted.  */
-  stpy_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, del_objfile_symtab);
-  salpy_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, del_objfile_sal);
-}
-
 int
 gdbpy_initialize_symtabs (void)
 {
index 7cfc8d16233a3420235ca77516a1ed23b36e2ce5..d14f9e428538df6d71c86c19e69d3c3b18b11e9c 100644 (file)
@@ -1109,36 +1109,38 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
 
 \f
 
-static const struct objfile_data *typy_objfile_data_key;
-
-static void
-save_objfile_types (struct objfile *objfile, void *datum)
+/* Deleter that saves types when an objfile is being destroyed.  */
+struct typy_deleter
 {
-  type_object *obj = (type_object *) datum;
+  void operator() (type_object *obj)
+  {
+    if (!gdb_python_initialized)
+      return;
 
-  if (!gdb_python_initialized)
-    return;
+    /* This prevents another thread from freeing the objects we're
+       operating on.  */
+    gdbpy_enter enter_py;
 
-  /* This prevents another thread from freeing the objects we're
-     operating on.  */
-  gdbpy_enter enter_py (objfile->arch ());
+    htab_up copied_types = create_copied_types_hash ();
 
-  htab_up copied_types = create_copied_types_hash ();
+    while (obj)
+      {
+       type_object *next = obj->next;
 
-  while (obj)
-    {
-      type_object *next = obj->next;
+       htab_empty (copied_types.get ());
 
-      htab_empty (copied_types.get ());
+       obj->type = copy_type_recursive (obj->type, copied_types.get ());
 
-      obj->type = copy_type_recursive (obj->type, copied_types.get ());
+       obj->next = NULL;
+       obj->prev = NULL;
 
-      obj->next = NULL;
-      obj->prev = NULL;
+       obj = next;
+      }
+  }
+};
 
-      obj = next;
-    }
-}
+static const registry<objfile>::key<type_object, typy_deleter>
+     typy_objfile_data_key;
 
 static void
 set_type (type_object *obj, struct type *type)
@@ -1149,11 +1151,10 @@ set_type (type_object *obj, struct type *type)
     {
       struct objfile *objfile = type->objfile_owner ();
 
-      obj->next = ((type_object *)
-                  objfile_data (objfile, typy_objfile_data_key));
+      obj->next = typy_objfile_data_key.get (objfile);
       if (obj->next)
        obj->next->prev = obj;
-      set_objfile_data (objfile, typy_objfile_data_key, obj);
+      typy_objfile_data_key.set (objfile, obj);
     }
   else
     obj->next = NULL;
@@ -1172,7 +1173,7 @@ typy_dealloc (PyObject *obj)
       struct objfile *objfile = type->type->objfile_owner ();
 
       if (objfile)
-       set_objfile_data (objfile, typy_objfile_data_key, type->next);
+       typy_objfile_data_key.set (objfile, type->next);
     }
   if (type->next)
     type->next->prev = type->prev;
@@ -1464,14 +1465,6 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
   return type_to_type_object (type);
 }
 
-void _initialize_py_type ();
-void
-_initialize_py_type ()
-{
-  typy_objfile_data_key
-    = register_objfile_data_with_cleanup (save_objfile_types, NULL);
-}
-
 int
 gdbpy_initialize_types (void)
 {
diff --git a/gdb/registry.c b/gdb/registry.c
deleted file mode 100644 (file)
index 2e977e2..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Support functions for general registry objects.
-
-   Copyright (C) 2011-2022 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/>.  */
-
-#include "defs.h"
-#include "registry.h"
-const struct registry_data *
-register_data_with_cleanup (struct registry_data_registry *registry,
-                           registry_data_callback save,
-                           registry_data_callback free)
-{
-  struct registry_data_registration **curr;
-
-  /* Append new registration.  */
-  for (curr = &registry->registrations;
-       *curr != NULL;
-       curr = &(*curr)->next)
-    ;
-
-  *curr = XNEW (struct registry_data_registration);
-  (*curr)->next = NULL;
-  (*curr)->data = XNEW (struct registry_data);
-  (*curr)->data->index = registry->num_registrations++;
-  (*curr)->data->save = save;
-  (*curr)->data->free = free;
-
-  return (*curr)->data;
-}
-
-void
-registry_alloc_data (struct registry_data_registry *registry,
-                      struct registry_fields *fields)
-{
-  gdb_assert (fields->data == NULL);
-  fields->num_data = registry->num_registrations;
-  fields->data = XCNEWVEC (void *, fields->num_data);
-}
-
-void
-registry_clear_data (struct registry_data_registry *data_registry,
-                    registry_callback_adaptor adaptor,
-                    struct registry_container *container,
-                    struct registry_fields *fields)
-{
-  struct registry_data_registration *registration;
-  int i;
-
-  gdb_assert (fields->data != NULL);
-
-  /* Process all the save handlers.  */
-
-  for (registration = data_registry->registrations, i = 0;
-       i < fields->num_data;
-       registration = registration->next, i++)
-    if (fields->data[i] != NULL && registration->data->save != NULL)
-      adaptor (registration->data->save, container, fields->data[i]);
-
-  /* Now process all the free handlers.  */
-
-  for (registration = data_registry->registrations, i = 0;
-       i < fields->num_data;
-       registration = registration->next, i++)
-    if (fields->data[i] != NULL && registration->data->free != NULL)
-      adaptor (registration->data->free, container, fields->data[i]);
-
-  memset (fields->data, 0, fields->num_data * sizeof (void *));
-}
-
-void
-registry_container_free_data (struct registry_data_registry *data_registry,
-                             registry_callback_adaptor adaptor,
-                             struct registry_container *container,
-                             struct registry_fields *fields)
-{
-  void ***rdata = &fields->data;
-  gdb_assert (*rdata != NULL);
-  registry_clear_data (data_registry, adaptor, container, fields);
-  xfree (*rdata);
-  *rdata = NULL;
-}
-
-void
-registry_set_data (struct registry_fields *fields,
-                  const struct registry_data *data,
-                  void *value)
-{
-  gdb_assert (data->index < fields->num_data);
-  fields->data[data->index] = value;
-}
-
-void *
-registry_data (struct registry_fields *fields,
-              const struct registry_data *data)
-{
-  gdb_assert (data->index < fields->num_data);
-  return fields->data[data->index];
-}
index 1475fd2ec2621f14417cac1c0cdabcc03a031c2e..cab9f44e3ba7c42ffafc7c90a8fe54780edec094 100644 (file)
 
 #include <type_traits>
 
-/* The macros here implement a template type and functions for
-   associating some user data with a container object.
-
-   A registry is associated with a struct tag name.  To attach a
-   registry to a structure, use DEFINE_REGISTRY.  This takes the
-   structure tag and an access method as arguments.  In the usual
-   case, where the registry fields appear directly in the struct, you
-   can use the 'REGISTRY_FIELDS' macro to declare the fields in the
-   struct definition, and you can pass 'REGISTRY_ACCESS_FIELD' as the
-   access argument to DEFINE_REGISTRY.  In other cases, use
-   REGISTRY_FIELDS to define the fields in the appropriate spot, and
-   then define your own accessor to find the registry field structure
-   given an instance of your type.
-
-   The API user requests a key from a registry during gdb
-   initialization.  Later this key can be used to associate some
-   module-specific data with a specific container object.
-
-   The exported API is best used via the wrapper macros:
-   
-   - register_TAG_data(TAG)
-   Get a new key for the container type TAG.
-   
-   - register_TAG_data_with_cleanup(TAG, SAVE, FREE)
-   Get a new key for the container type TAG.
-   SAVE and FREE are defined as void (*) (struct TAG *object, void *data)
-   When the container object OBJECT is destroyed, first all registered SAVE
-   functions are called.
-   Then all FREE functions are called.
-   Either or both may be NULL.  DATA is the data associated with the
-   container object OBJECT.
-   
-   - clear_TAG_data(TAG, OBJECT)
-   Clear all the data associated with OBJECT.  Should be called by the
-   container implementation when a container object is destroyed.
-   
-   - set_TAG_data(TAG, OBJECT, KEY, DATA)
-   Set the data on an object.
-   
-   - TAG_data(TAG, OBJECT, KEY)
-   Fetch the data for an object; returns NULL if it has not been set.
-*/
-
-/* This structure is used in a container to hold the data that the
-   registry uses.  */
-
-struct registry_fields
-{
-  void **data;
-  unsigned num_data;
-};
+template<typename T> class registry;
 
-/* This macro is used in a container struct definition to define the
-   fields used by the registry code.  */
+/* An accessor class that is used by registry_key.
 
-#define REGISTRY_FIELDS                                \
-  struct registry_fields registry_data
+   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.
 
-/* A convenience macro for the typical case where the registry data is
-   kept as fields of the object.  This can be passed as the ACCESS
-   method to DEFINE_REGISTRY.  */
+   However, a container may sometimes need to store the registry
+   elsewhere.  In this case, registry_accessor can be specialized to
+   perform the needed indirection.  */
 
-#define REGISTRY_ACCESS_FIELD(CONTAINER) \
-  (CONTAINER)
+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;
+  }
+};
 
-/* Opaque type representing a container type with a registry.  This
-   type is never defined.  This is used to factor out common
-   functionality of all struct tag names into common code.  IOW,
-   "struct tag name" pointers are cast to and from "struct
-   registry_container" pointers when calling the common registry
-   "backend" functions.  */
-struct registry_container;
+/* 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).
 
-/* Registry callbacks have this type.  */
-typedef void (*registry_data_callback) (struct registry_container *, void *);
+   This is handled using the registry system.
 
-struct registry_data
-{
-  unsigned index;
-  registry_data_callback save;
-  registry_data_callback free;
-};
+   A class needing to allow this sort registration can add a registry
+   field.  For example, you would write:
 
-struct registry_data_registration
-{
-  struct registry_data *data;
-  struct registry_data_registration *next;
-};
+   class some_container { registry<some_container> registry_fields; };
 
-struct registry_data_registry
-{
-  struct registry_data_registration *registrations;
-  unsigned num_registrations;
-};
+   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.  */
 
-/* Registry backend functions.  Client code uses the frontend
-   functions defined by DEFINE_REGISTRY below instead.  */
-
-const struct registry_data *register_data_with_cleanup
-  (struct registry_data_registry *registry,
-   registry_data_callback save,
-   registry_data_callback free);
-
-void registry_alloc_data (struct registry_data_registry *registry,
-                         struct registry_fields *registry_fields);
-
-/* Cast FUNC and CONTAINER to the real types, and call FUNC, also
-   passing DATA.  */
-typedef void (*registry_callback_adaptor) (registry_data_callback func,
-                                          struct registry_container *container,
-                                          void *data);
-
-void registry_clear_data (struct registry_data_registry *data_registry,
-                         registry_callback_adaptor adaptor,
-                         struct registry_container *container,
-                         struct registry_fields *fields);
-
-void registry_container_free_data (struct registry_data_registry *data_registry,
-                                  registry_callback_adaptor adaptor,
-                                  struct registry_container *container,
-                                  struct registry_fields *fields);
-
-void registry_set_data (struct registry_fields *fields,
-                       const struct registry_data *data,
-                       void *value);
-
-void *registry_data (struct registry_fields *fields,
-                    const struct registry_data *data);
-
-/* Define a new registry implementation.  */
-
-#define DEFINE_REGISTRY(TAG, ACCESS)                                   \
-static struct registry_data_registry TAG ## _data_registry = { NULL, 0 }; \
-                                                                       \
-const struct TAG ## _data *                                            \
-register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \
-                                       void (*free) (struct TAG *, void *)) \
-{                                                                      \
-  return (struct TAG ## _data *)                                       \
-    register_data_with_cleanup (&TAG ## _data_registry,                        \
-                               (registry_data_callback) save,          \
-                               (registry_data_callback) free);         \
-}                                                                      \
-                                                                       \
-const struct TAG ## _data *                                            \
-register_ ## TAG ## _data (void)                                       \
-{                                                                      \
-  return register_ ## TAG ## _data_with_cleanup (NULL, NULL);          \
-}                                                                      \
-                                                                       \
-static void                                                            \
-TAG ## _alloc_data (struct TAG *container)                             \
-{                                                                      \
-  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
-                                                                       \
-  registry_alloc_data (&TAG ## _data_registry, rdata);                 \
-}                                                                      \
-                                                                       \
-static void                                                            \
-TAG ## registry_callback_adaptor (registry_data_callback func,         \
-                                 struct registry_container *container, \
-                                 void *data)                           \
-{                                                                      \
-  struct TAG *tagged_container = (struct TAG *) container;             \
-                                                                       \
-  registry_ ## TAG ## _callback tagged_func                            \
-    = (registry_ ## TAG ## _callback) func;                            \
-                                                                       \
-  tagged_func (tagged_container, data);                                        \
-}                                                                      \
-                                                                       \
-void                                                                   \
-clear_ ## TAG ## _data (struct TAG *container)                         \
-{                                                                      \
-  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
-                                                                       \
-  registry_clear_data (&TAG ## _data_registry,                         \
-                      TAG ## registry_callback_adaptor,                \
-                      (struct registry_container *) container,         \
-                      rdata);                                          \
-}                                                                      \
-                                                                       \
-static void                                                            \
-TAG ## _free_data (struct TAG *container)                              \
-{                                                                      \
-  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
-                                                                       \
-  registry_container_free_data (&TAG ## _data_registry,                        \
-                               TAG ## registry_callback_adaptor,       \
-                               (struct registry_container *) container, \
-                               rdata);                                 \
-}                                                                      \
-                                                                       \
-void                                                                   \
-set_ ## TAG ## _data (struct TAG *container,                           \
-                     const struct TAG ## _data *data,                  \
-                     void *value)                                      \
-{                                                                      \
-  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
-                                                                       \
-  registry_set_data (rdata,                                            \
-                    (struct registry_data *) data,                     \
-                    value);                                            \
-}                                                                      \
-                                                                       \
-void *                                                                 \
-TAG ## _data (struct TAG *container, const struct TAG ## _data *data)  \
-{                                                                      \
-  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
-                                                                       \
-  return registry_data (rdata,                                         \
-                       (struct registry_data *) data);                 \
-}
-
-
-/* External declarations for the registry functions.  */
-
-#define DECLARE_REGISTRY(TAG)                                          \
-struct TAG ## _data;                                                   \
-typedef void (*registry_ ## TAG ## _callback) (struct TAG *, void *);  \
-extern const struct TAG ## _data *register_ ## TAG ## _data (void);    \
-extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \
- (registry_ ## TAG ## _callback save, registry_ ## TAG ## _callback free); \
-extern void clear_ ## TAG ## _data (struct TAG *);                     \
-extern void set_ ## TAG ## _data (struct TAG *,                                \
-                                 const struct TAG ## _data *data,      \
-                                 void *value);                         \
-extern void *TAG ## _data (struct TAG *,                               \
-                          const struct TAG ## _data *data);            \
-                                                                       \
-template<typename DATA, typename Deleter = std::default_delete<DATA>>  \
-class TAG ## _key                                                      \
-{                                                                      \
-public:                                                                        \
-                                                                       \
-  TAG ## _key ()                                                       \
-    : m_key (register_ ## TAG ## _data_with_cleanup (nullptr,          \
-                                                    cleanup))          \
-  {                                                                    \
-  }                                                                    \
-                                                                       \
-  DATA *get (struct TAG *obj) const                                    \
-  {                                                                    \
-    return (DATA *) TAG ## _data (obj, m_key);                         \
-  }                                                                    \
-                                                                       \
-  void set (struct TAG *obj, DATA *data) const                         \
-  {                                                                    \
-    set_ ## TAG ## _data (obj, m_key, data);                           \
-  }                                                                    \
-                                                                       \
-  template<typename Dummy = DATA *, typename... Args>                  \
-  typename std::enable_if<std::is_same<Deleter,                                \
-                                      std::default_delete<DATA>>::value, \
-                         Dummy>::type                                  \
-  emplace (struct TAG *obj, Args &&...args) const                      \
-  {                                                                    \
-    DATA *result = new DATA (std::forward<Args> (args)...);            \
-    set (obj, result);                                                 \
-    return result;                                                     \
-  }                                                                    \
-                                                                       \
-  void clear (struct TAG *obj) const                                   \
-  {                                                                    \
-    DATA *datum = get (obj);                                           \
-    if (datum != nullptr)                                              \
-      {                                                                        \
-       cleanup (obj, datum);                                           \
-       set (obj, nullptr);                                             \
-      }                                                                        \
-  }                                                                    \
-                                                                       \
-private:                                                               \
-                                                                       \
-  static void cleanup (struct TAG *obj, void *arg)                     \
-  {                                                                    \
-    DATA *datum = (DATA *) arg;                                                \
-    Deleter d;                                                         \
-    d (datum);                                                         \
-  }                                                                    \
-                                                                       \
-  const struct TAG ## _data *m_key;                                    \
+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, 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 typename registry<T>::registry_data *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.  */
+    for (const auto &datum : get_registrations ())
+      {
+       void *elt = m_fields[datum->index];
+       if (elt != nullptr)
+         {
+           datum->free (elt);
+           m_fields[datum->index] = nullptr;
+         }
+      }
+  }
+
+private:
+
+  /* Registry callbacks have this type.  */
+  typedef void (*registry_data_callback) (void *);
+
+  /* The type of a key.  */
+  struct registry_data
+  {
+    unsigned index;
+    registry_data_callback free;
+  };
+
+  /* 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 const registry_data *new_key (registry_data_callback free)
+  {
+    std::unique_ptr<registry_data> result (new registry_data);
+    std::vector<std::unique_ptr<registry_data>> &registrations
+      = get_registrations ();
+    result->index = registrations.size ();
+    result->free = free;
+    registrations.emplace_back (std::move (result));
+    return registrations.back ().get ();
+  }
+
+  /* Set the datum associated with KEY in this container.  */
+  void set (const registry_data *key, void *datum)
+  {
+    m_fields[key->index] = datum;
+  }
+
+  /* Fetch the datum associated with KEY in this container.  If 'set'
+     has not been called for this key, nullptr is returned.  */
+  void *get (const registry_data *key)
+  {
+    return m_fields[key->index];
+  }
+
+  /* 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.  We do separate allocations here so that the
+     addresses are stable and can be used as keys.  */
+  static std::vector<std::unique_ptr<registry_data>> &get_registrations ()
+  {
+    static std::vector<std::unique_ptr<registry_data>> registrations;
+    return registrations;
+  }
 };
 
 #endif /* REGISTRY_H */
index 4b8afd276887b5958c238d42d4d55945153f36cf..01f88fc9da296bd841e00c925d210552c8cc8838 100644 (file)
@@ -178,7 +178,7 @@ private:
 
 static struct gdbsim_target gdbsim_ops;
 
-static inferior_key<sim_inferior_data> sim_inferior_data_key;
+static const registry<inferior>::key<sim_inferior_data> sim_inferior_data_key;
 
 /* Flag indicating the "open" status of this module.  It's set to 1
    in gdbsim_open() and 0 in gdbsim_close().  */
index f91973458ea6ad4a61cdf36956f75e33fa38954d..39d0a794a21b3590ddeececde72e3272d10dcd46 100644 (file)
@@ -1033,7 +1033,7 @@ is_remote_target (process_stratum_target *target)
 }
 
 /* Per-program-space data key.  */
-static const struct program_space_key<char, gdb::xfree_deleter<char>>
+static const registry<program_space>::key<char, gdb::xfree_deleter<char>>
   remote_pspace_data;
 
 /* The variable registered as the control variable used by the
index 640459f1c281ffed518b6d83f920f1feee8bd8d3..1be3e4d61cd7735e7da649e619af2c3e17d392d4 100644 (file)
@@ -155,7 +155,7 @@ static const char *powerpc_vector_abi_string = "auto";
 
 /* PowerPC-related per-inferior data.  */
 
-static inferior_key<ppc_inferior_data> ppc_inferior_data_key;
+static registry<inferior>::key<ppc_inferior_data> ppc_inferior_data_key;
 
 /* Get the per-inferior PowerPC data for INF.  */
 
index 3a8debf2c5a71d977f6dd5c13e0d73f891329d77..33b15a9d8ad2aae70dbdcf4914d2cefd19fdf7c5 100644 (file)
@@ -80,7 +80,8 @@ struct solib_aix_inferior_data
 };
 
 /* Key to our per-inferior data.  */
-static inferior_key<solib_aix_inferior_data> solib_aix_inferior_data_handle;
+static const registry<inferior>::key<solib_aix_inferior_data>
+  solib_aix_inferior_data_handle;
 
 /* Return this module's data for the given inferior.
    If none is found, add a zero'ed one now.  */
index d7789f68dfecbfa6a63976a9771ef7322f6d2d4a..e61ec0d4bf3554112cb3101f9a556ccf119b3aea 100644 (file)
@@ -80,7 +80,8 @@ struct darwin_info
 };
 
 /* Per-program-space data key.  */
-static program_space_key<darwin_info> solib_darwin_pspace_data;
+static const registry<program_space>::key<darwin_info>
+  solib_darwin_pspace_data;
 
 /* Get the current darwin data.  If none is found yet, add it now.  This
    function always returns a valid object.  */
index 6af472172612f69a28ad874521af9f4ecc6c4bb8..b4cd16327a69781574dba0b28aabb7132fbc05c9 100644 (file)
@@ -164,7 +164,7 @@ struct dsbt_info
 };
 
 /* Per-program-space data key.  */
-static program_space_key<dsbt_info> solib_dsbt_pspace_data;
+static const registry<program_space>::key<dsbt_info> solib_dsbt_pspace_data;
 
 /* Get the current dsbt data.  If none is found yet, add it now.  This
    function always returns a valid object.  */
index 5c046d3fab55a586a06cdd94a352fd82be5ed55f..f9a43e2396949e1073b9520c931ec0d3968d12bd 100644 (file)
@@ -365,7 +365,7 @@ struct svr4_info
 };
 
 /* Per-program-space data key.  */
-static const struct program_space_key<svr4_info> solib_svr4_pspace_data;
+static const registry<program_space>::key<svr4_info> solib_svr4_pspace_data;
 
 /* Free the probes table.  */
 
index 7d4734b00127ec1d37fa98fa92074aa0f070f294..b9ddd049b005e8070d38c81ea6dad4168c0c6dfa 100644 (file)
@@ -529,7 +529,8 @@ typedef std::unordered_map<std::string, std::string> soname_build_id_map;
 
 /* Key used to associate a soname_build_id_map to a core file bfd.  */
 
-static const struct bfd_key<soname_build_id_map> cbfd_soname_build_id_data_key;
+static const struct registry<bfd>::key<soname_build_id_map>
+     cbfd_soname_build_id_data_key;
 
 /* See solib.h.  */
 
index 8691113c729019e1dc9894df7fd30fc9f09f7e17..425b02fc3a0face2a9fd37e971fcc6de4d06c3b4 100644 (file)
@@ -115,7 +115,8 @@ private:
   int m_line = 0;
 };
 
-static program_space_key<current_source_location> current_source_key;
+static const registry<program_space>::key<current_source_location>
+     current_source_key;
 
 /* Default number of lines to print with commands like "list".
    This is based on guessing how many long (i.e. more than chars_per_line
index ab74cee6487ae5fbd8803a4c3aa27b6977ea5416..cd6e6a92f8593c93a3833503db14f6ff78159e67 100644 (file)
@@ -2016,8 +2016,8 @@ again:
 /* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1.
    Return the proper type node for a given builtin type number.  */
 
-static const struct objfile_key<struct type *,
-                               gdb::noop_deleter<struct type *>>
+static const registry<objfile>::key<struct type *,
+                                   gdb::noop_deleter<struct type *>>
   rs6000_builtin_type_data;
 
 static struct type *
index 2af044334446571f9b55701d91dc58f19dfc54e8..5972629001142bde1ad8cbac0366ee293e8bf909 100644 (file)
@@ -47,7 +47,7 @@ struct debug_sym_fns_data
 
 /* We need to record a pointer to the real set of functions for each
    objfile.  */
-static const struct objfile_key<debug_sym_fns_data>
+static const registry<objfile>::key<debug_sym_fns_data>
   symfile_debug_objfile_data_key;
 
 /* If true all calls to the symfile functions are logged.  */
index 6f546f5b0591927a7e637a7c6dc630b15c1458fa..ec3244269b13d1322dff4a5c000ca6bc961086b8 100644 (file)
@@ -2500,7 +2500,7 @@ reread_symbols (int from_tty)
              (*objfile->sf->sym_finish) (objfile);
            }
 
-         clear_objfile_data (objfile);
+         objfile->registry_fields.clear_registry ();
 
          /* Clean up any state BFD has sitting around.  */
          {
@@ -2638,7 +2638,7 @@ reread_symbols (int from_tty)
     {
       clear_symtab_users (0);
 
-      /* clear_objfile_data for each objfile was called before freeing it and
+      /* The registry for each objfile was cleared and
         gdb::observers::new_objfile.notify (NULL) has been called by
         clear_symtab_users above.  Notify the new files now.  */
       for (auto iter : new_objfiles)
index 03aa2a96b87def873ef8c164765763e978a42d8f..40887f59d1f3956966c5b91beddc4cad3f4ce189 100644 (file)
@@ -121,7 +121,7 @@ struct main_info
 
 /* Program space key for finding name and language of "main".  */
 
-static const program_space_key<main_info> main_progspace_key;
+static const registry<program_space>::key<main_info> main_progspace_key;
 
 /* The default symbol cache size.
    There is no extra cpu cost for large N (except when flushing the cache,
@@ -251,7 +251,7 @@ struct symbol_cache
 
 /* Program space key for finding its symbol cache.  */
 
-static const program_space_key<symbol_cache> symbol_cache_key;
+static const registry<program_space>::key<symbol_cache> symbol_cache_key;
 
 /* When non-zero, print debugging messages related to symtab creation.  */
 unsigned int symtab_create_debug = 0;
index 0aa53302ceacf5e017fa27c4f3f46f92c30c3306..3e3c0c6ee4de036f5705e11657167035013d2154 100644 (file)
@@ -24,7 +24,7 @@
 /* The target dcache is kept per-address-space.  This key lets us
    associate the cache with the address space.  */
 
-static const struct address_space_key<DCACHE, dcache_deleter>
+static const registry<address_space>::key<DCACHE, dcache_deleter>
   target_dcache_aspace_key;
 
 /* Target dcache is initialized or not.  */
index 9e571d0419cf74e93a519d7c9370845a3d3ac437..bcb667b29e74b8b2d8fcd7977d1e850ee7f0db82 100644 (file)
@@ -147,7 +147,7 @@ struct xcoff_symfile_info
 
 /* Key for XCOFF-associated data.  */
 
-static const struct objfile_key<xcoff_symfile_info> xcoff_objfile_data_key;
+static const registry<objfile>::key<xcoff_symfile_info> xcoff_objfile_data_key;
 
 /* Convenience macro to access the per-objfile XCOFF data.  */