Tweak handling of remote errors in response to resumption packet
[deliverable/binutils-gdb.git] / gdb / registry.h
index d69678116a7f0673bfa44ad13d3c136d1a3d8c83..09e2b67c938dbc8b6605bf247b67472910966d00 100644 (file)
@@ -1,7 +1,6 @@
 /* Macros for general registry objects.
 
-   Copyright (C) 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 2011-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #ifndef REGISTRY_H
 #define REGISTRY_H
 
+#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.
 
-   A registry is associated with a struct tag name.
-
    The exported API is best used via the wrapper macros:
    
    - register_TAG_data(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 *, void *)
-   When the container is destroyed, first all registered SAVE
+   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.
+   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
    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;
+};
+
 /* This macro is used in a container struct definition to define the
    fields used by the registry code.  */
 
 #define REGISTRY_FIELDS                                \
-  void **data;                                 \
-  unsigned num_data
+  struct registry_fields registry_data
+
+/* 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.  */
+
+#define REGISTRY_ACCESS_FIELD(CONTAINER) \
+  (CONTAINER)
+
+/* 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;
+
+/* Registry callbacks have this type.  */
+typedef void (*registry_data_callback) (struct registry_container *, void *);
+
+struct registry_data
+{
+  unsigned index;
+  registry_data_callback save;
+  registry_data_callback free;
+};
+
+struct registry_data_registration
+{
+  struct registry_data *data;
+  struct registry_data_registration *next;
+};
+
+struct registry_data_registry
+{
+  struct registry_data_registration *registrations;
+  unsigned num_registrations;
+};
+
+/* 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)                                           \
-struct TAG ## _data                                                    \
-{                                                                      \
-  unsigned index;                                                      \
-  void (*save) (struct TAG *, void *);                                 \
-  void (*free) (struct TAG *, void *);                                 \
-};                                                                     \
-                                                                       \
-struct TAG ## _data_registration                                       \
-{                                                                      \
-  struct TAG ## _data *data;                                           \
-  struct TAG ## _data_registration *next;                              \
-};                                                                     \
-                                                                       \
-struct TAG ## _data_registry                                           \
-{                                                                      \
-  struct TAG ## _data_registration *registrations;                     \
-  unsigned num_registrations;                                          \
-};                                                                     \
-                                                                       \
-struct TAG ## _data_registry TAG ## _data_registry = { NULL, 0 };      \
+#define DEFINE_REGISTRY(TAG, ACCESS)                                   \
+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 *)) \
+                                       void (*free) (struct TAG *, void *)) \
 {                                                                      \
-  struct TAG ## _data_registration **curr;                             \
-                                                                       \
-  /* Append new registration.  */                                      \
-  for (curr = &TAG ## _data_registry.registrations;                    \
-       *curr != NULL; curr = &(*curr)->next);                          \
-                                                                       \
-  *curr = XMALLOC (struct TAG ## _data_registration);                  \
-  (*curr)->next = NULL;                                                        \
-  (*curr)->data = XMALLOC (struct TAG ## _data);                       \
-  (*curr)->data->index = TAG ## _data_registry.num_registrations++;    \
-  (*curr)->data->save = save;                                          \
-  (*curr)->data->free = free;                                          \
-                                                                       \
-  return (*curr)->data;                                                        \
+  return (struct TAG ## _data *)                                       \
+    register_data_with_cleanup (&TAG ## _data_registry,                        \
+                               (registry_data_callback) save,          \
+                               (registry_data_callback) free);         \
 }                                                                      \
                                                                        \
 const struct TAG ## _data *                                            \
@@ -114,74 +175,135 @@ register_ ## TAG ## _data (void)                                 \
 static void                                                            \
 TAG ## _alloc_data (struct TAG *container)                             \
 {                                                                      \
-  gdb_assert (container->data == NULL);                                        \
-  container->num_data = TAG ## _data_registry.num_registrations;       \
-  container->data = XCALLOC (container->num_data, void *);             \
+  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
+                                                                       \
+  registry_alloc_data (&TAG ## _data_registry, rdata);                 \
 }                                                                      \
                                                                        \
-void                                                                   \
-clear_ ## TAG ## _data (struct TAG *container)                         \
+static void                                                            \
+TAG ## registry_callback_adaptor (registry_data_callback func,         \
+                                 struct registry_container *container, \
+                                 void *data)                           \
 {                                                                      \
-  struct TAG ## _data_registration *registration;                      \
-  int i;                                                               \
+  struct TAG *tagged_container = (struct TAG *) container;             \
                                                                        \
-  gdb_assert (container->data != NULL);                                        \
+  registry_ ## TAG ## _callback tagged_func                            \
+    = (registry_ ## TAG ## _callback) func;                            \
                                                                        \
-  /* Process all the save handlers.  */                                        \
-                                                                       \
-  for (registration = TAG ## _data_registry.registrations, i = 0;      \
-       i < container->num_data;                                                \
-       registration = registration->next, i++)                         \
-    if (container->data[i] != NULL && registration->data->save != NULL)        \
-      registration->data->save (container, container->data[i]);                \
-                                                                       \
-  /* Now process all the free handlers.  */                            \
+  tagged_func (tagged_container, data);                                        \
+}                                                                      \
                                                                        \
-  for (registration = TAG ## _data_registry.registrations, i = 0;      \
-       i < container->num_data;                                                \
-       registration = registration->next, i++)                         \
-    if (container->data[i] != NULL && registration->data->free != NULL)        \
-      registration->data->free (container, container->data[i]);                \
+void                                                                   \
+clear_ ## TAG ## _data (struct TAG *container)                         \
+{                                                                      \
+  struct registry_fields *rdata = &ACCESS (container)->registry_data;  \
                                                                        \
-  memset (container->data, 0, container->num_data * sizeof (void *));  \
+  registry_clear_data (&TAG ## _data_registry,                         \
+                      TAG ## registry_callback_adaptor,                \
+                      (struct registry_container *) container,         \
+                      rdata);                                          \
 }                                                                      \
                                                                        \
 static void                                                            \
 TAG ## _free_data (struct TAG *container)                              \
 {                                                                      \
-  void ***rdata = &container->data;                                    \
-  gdb_assert (*rdata != NULL);                                         \
-  clear_ ## TAG ## _data (container);                                  \
-  xfree (*rdata);                                                      \
-  *rdata = NULL;                                                       \
+  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)                                          \
+set_ ## TAG ## _data (struct TAG *container,                           \
+                     const struct TAG ## _data *data,                  \
+                     void *value)                                      \
 {                                                                      \
-  gdb_assert (data->index < container->num_data);                      \
-  container->data[data->index] = 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)  \
 {                                                                      \
-  gdb_assert (data->index < container->num_data);                      \
-  return container->data[data->index];                                 \
+  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 \
- (void (*save) (struct TAG *, void *), void (*free) (struct TAG *, void *)); \
-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);
+ (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;                                    \
+};
 
 #endif /* REGISTRY_H */
This page took 0.030676 seconds and 4 git commands to generate.