123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /* Macros 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/>. */
- #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.
- 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;
- };
- /* This macro is used in a container struct definition to define the
- fields used by the registry code. */
- #define REGISTRY_FIELDS \
- 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, 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; \
- };
- #endif /* REGISTRY_H */
|