1 /* Macros for general registry objects.
3 Copyright (C) 2011-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #ifndef GDB_REGISTRY_H
21 #define GDB_REGISTRY_H
23 #include <type_traits>
25 template<typename T
> class registry
;
27 /* An accessor class that is used by registry_key.
29 Normally, a container class has a registry<> field named
30 "registry_fields". In this case, the default accessor is used, as
31 it simply returns the object.
33 However, a container may sometimes need to store the registry
34 elsewhere. In this case, registry_accessor can be specialized to
35 perform the needed indirection. */
38 struct registry_accessor
40 /* Given a container of type T, return its registry. */
41 static registry
<T
> *get (T
*obj
)
43 return &obj
->registry_fields
;
47 /* In gdb, sometimes there is a need for one module (e.g., the Python
48 Type code) to attach some data to another object (e.g., an
49 objfile); but it's also desirable that this be done such that the
50 base object (the objfile in this example) not need to know anything
51 about the attaching module (the Python code).
53 This is handled using the registry system.
55 A class needing to allow this sort registration can add a registry
56 field. For example, you would write:
58 class some_container { registry<some_container> registry_fields; };
60 The name of the field matters by default, see registry_accessor.
62 A module wanting to attach data to instances of some_container uses
63 the "key" class to register a key. This key can then be passed to
64 the "get" and "set" methods to handle this module's data. */
72 : m_fields (get_registrations ().size ())
81 DISABLE_COPY_AND_ASSIGN (registry
);
83 /* A type-safe registry key.
85 The registry itself holds just a "void *". This is not always
86 convenient to manage, so this template class can be used instead,
87 to provide a type-safe interface, that also helps manage the
88 lifetime of the stored objects.
90 When the container is destroyed, this key arranges to destroy the
91 underlying data using Deleter. This defaults to
92 std::default_delete. */
94 template<typename DATA
, typename Deleter
= std::default_delete
<DATA
>>
100 : m_key (registry
<T
>::new_key (cleanup
))
104 DISABLE_COPY_AND_ASSIGN (key
);
106 /* Fetch the data attached to OBJ that is associated with this key.
107 If no such data has been attached, nullptr is returned. */
108 DATA
*get (T
*obj
) const
110 registry
<T
> *reg_obj
= registry_accessor
<T
>::get (obj
);
111 return (DATA
*) reg_obj
->get (m_key
);
114 /* Attach DATA to OBJ, associated with this key. Note that any
115 previous data is simply dropped -- if destruction is needed,
116 'clear' should be called. */
117 void set (T
*obj
, DATA
*data
) const
119 registry
<T
> *reg_obj
= registry_accessor
<T
>::get (obj
);
120 reg_obj
->set (m_key
, (typename
std::remove_const
<DATA
> *) data
);
123 /* If this key uses the default deleter, then this method is
124 available. It emplaces a new instance of the associated data
125 type and attaches it to OBJ using this key. The arguments, if
126 any, are forwarded to the constructor. */
127 template<typename Dummy
= DATA
*, typename
... Args
>
128 typename
std::enable_if
<std::is_same
<Deleter
,
129 std::default_delete
<DATA
>>::value
,
131 emplace (T
*obj
, Args
&&...args
) const
133 DATA
*result
= new DATA (std::forward
<Args
> (args
)...);
138 /* Clear the data attached to OBJ that is associated with this KEY.
139 Any existing data is destroyed using the deleter, and the data is
141 void clear (T
*obj
) const
143 DATA
*datum
= get (obj
);
144 if (datum
!= nullptr)
153 /* A helper function that is called by the registry to delete the
155 static void cleanup (void *arg
)
157 DATA
*datum
= (DATA
*) arg
;
162 /* The underlying key. */
163 const unsigned m_key
;
166 /* Clear all the data associated with this container. This is
167 dangerous and should not normally be done. */
168 void clear_registry ()
170 /* Call all the free functions. */
171 std::vector
<registry_data_callback
> ®istrations
172 = get_registrations ();
173 unsigned last
= registrations
.size ();
174 for (unsigned i
= 0; i
< last
; ++i
)
176 void *elt
= m_fields
[i
];
179 registrations
[i
] (elt
);
180 m_fields
[i
] = nullptr;
187 /* Registry callbacks have this type. */
188 typedef void (*registry_data_callback
) (void *);
190 /* Get a new key for this particular registry. FREE is a callback.
191 When the container object is destroyed, all FREE functions are
192 called. The data associated with the container object is passed
194 static unsigned new_key (registry_data_callback free
)
196 std::vector
<registry_data_callback
> ®istrations
197 = get_registrations ();
198 unsigned result
= registrations
.size ();
199 registrations
.push_back (free
);
203 /* Set the datum associated with KEY in this container. */
204 void set (unsigned key
, void *datum
)
206 m_fields
[key
] = datum
;
209 /* Fetch the datum associated with KEY in this container. If 'set'
210 has not been called for this key, nullptr is returned. */
211 void *get (unsigned key
)
213 return m_fields
[key
];
216 /* The data stored in this instance. */
217 std::vector
<void *> m_fields
;
219 /* Return a reference to the vector of all the registrations that
221 static std::vector
<registry_data_callback
> &get_registrations ()
223 static std::vector
<registry_data_callback
> registrations
;
224 return registrations
;
228 #endif /* GDB_REGISTRY_H */