X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fregistry.h;h=683d905f7636884203b6d477f18185919c5e587a;hb=84e098cdea4eb6a5ddc525a2145ffe66475fa2af;hp=423caa6d0321a443db100bf06d1854df9e2eb69f;hpb=6b81941e358ef95a24d90b971dd05f6c30dfa9a7;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/registry.h b/gdb/registry.h index 423caa6d03..683d905f76 100644 --- a/gdb/registry.h +++ b/gdb/registry.h @@ -1,7 +1,6 @@ /* Macros for general registry objects. - Copyright (C) 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 2011-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +20,8 @@ #ifndef REGISTRY_H #define REGISTRY_H +#include + /* The macros here implement a template type and functions for associating some user data with a container object. @@ -46,11 +47,12 @@ - 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 @@ -85,48 +87,83 @@ struct registry_fields #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, ACCESS) \ -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 }; \ +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 * \ @@ -139,77 +176,134 @@ static void \ TAG ## _alloc_data (struct TAG *container) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (rdata->data == NULL); \ - rdata->num_data = TAG ## _data_registry.num_registrations; \ - rdata->data = XCALLOC (rdata->num_data, void *); \ + \ + 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 registry_fields *rdata = &ACCESS (container)->registry_data; \ - struct TAG ## _data_registration *registration; \ - int i; \ - \ - gdb_assert (rdata->data != NULL); \ + struct TAG *tagged_container = (struct TAG *) container; \ \ - /* Process all the save handlers. */ \ + registry_ ## TAG ## _callback tagged_func \ + = (registry_ ## TAG ## _callback) func; \ \ - for (registration = TAG ## _data_registry.registrations, i = 0; \ - i < rdata->num_data; \ - registration = registration->next, i++) \ - if (rdata->data[i] != NULL && registration->data->save != NULL) \ - registration->data->save (container, rdata->data[i]); \ - \ - /* Now process all the free handlers. */ \ + tagged_func (tagged_container, data); \ +} \ \ - for (registration = TAG ## _data_registry.registrations, i = 0; \ - i < rdata->num_data; \ - registration = registration->next, i++) \ - if (rdata->data[i] != NULL && registration->data->free != NULL) \ - registration->data->free (container, rdata->data[i]); \ +void \ +clear_ ## TAG ## _data (struct TAG *container) \ +{ \ + struct registry_fields *rdata = &ACCESS (container)->registry_data; \ \ - memset (rdata->data, 0, rdata->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) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (rdata->data != NULL); \ - clear_ ## TAG ## _data (container); \ - xfree (rdata->data); \ - rdata->data = NULL; \ + \ + 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) \ { \ struct registry_fields *rdata = &ACCESS (container)->registry_data; \ - gdb_assert (data->index < rdata->num_data); \ - rdata->data[data->index] = value; \ + \ + 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; \ - gdb_assert (data->index < rdata->num_data); \ - return rdata->data[data->index]; \ + \ + 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> \ +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 std::enable_if>::value, \ + Dummy>::type \ + emplace (struct TAG *obj, Args &&...args) const \ + { \ + DATA *result = new DATA (std::forward (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 */