xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/registry.h (revision 325dc460fcb903ba21d515d6422d8abf39bc692e)
1 /* Macros for general registry objects.
2 
3    Copyright (C) 2011-2020 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
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.
11 
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.
16 
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/>.  */
19 
20 #ifndef REGISTRY_H
21 #define REGISTRY_H
22 
23 #include <type_traits>
24 
25 /* The macros here implement a template type and functions for
26    associating some user data with a container object.
27 
28    A registry is associated with a struct tag name.  To attach a
29    registry to a structure, use DEFINE_REGISTRY.  This takes the
30    structure tag and an access method as arguments.  In the usual
31    case, where the registry fields appear directly in the struct, you
32    can use the 'REGISTRY_FIELDS' macro to declare the fields in the
33    struct definition, and you can pass 'REGISTRY_ACCESS_FIELD' as the
34    access argument to DEFINE_REGISTRY.  In other cases, use
35    REGISTRY_FIELDS to define the fields in the appropriate spot, and
36    then define your own accessor to find the registry field structure
37    given an instance of your type.
38 
39    The API user requests a key from a registry during gdb
40    initialization.  Later this key can be used to associate some
41    module-specific data with a specific container object.
42 
43    The exported API is best used via the wrapper macros:
44 
45    - register_TAG_data(TAG)
46    Get a new key for the container type TAG.
47 
48    - register_TAG_data_with_cleanup(TAG, SAVE, FREE)
49    Get a new key for the container type TAG.
50    SAVE and FREE are defined as void (*) (struct TAG *object, void *data)
51    When the container object OBJECT is destroyed, first all registered SAVE
52    functions are called.
53    Then all FREE functions are called.
54    Either or both may be NULL.  DATA is the data associated with the
55    container object OBJECT.
56 
57    - clear_TAG_data(TAG, OBJECT)
58    Clear all the data associated with OBJECT.  Should be called by the
59    container implementation when a container object is destroyed.
60 
61    - set_TAG_data(TAG, OBJECT, KEY, DATA)
62    Set the data on an object.
63 
64    - TAG_data(TAG, OBJECT, KEY)
65    Fetch the data for an object; returns NULL if it has not been set.
66 */
67 
68 /* This structure is used in a container to hold the data that the
69    registry uses.  */
70 
71 struct registry_fields
72 {
73   void **data;
74   unsigned num_data;
75 };
76 
77 /* This macro is used in a container struct definition to define the
78    fields used by the registry code.  */
79 
80 #define REGISTRY_FIELDS				\
81   struct registry_fields registry_data
82 
83 /* A convenience macro for the typical case where the registry data is
84    kept as fields of the object.  This can be passed as the ACCESS
85    method to DEFINE_REGISTRY.  */
86 
87 #define REGISTRY_ACCESS_FIELD(CONTAINER) \
88   (CONTAINER)
89 
90 /* Opaque type representing a container type with a registry.  This
91    type is never defined.  This is used to factor out common
92    functionality of all struct tag names into common code.  IOW,
93    "struct tag name" pointers are cast to and from "struct
94    registry_container" pointers when calling the common registry
95    "backend" functions.  */
96 struct registry_container;
97 
98 /* Registry callbacks have this type.  */
99 typedef void (*registry_data_callback) (struct registry_container *, void *);
100 
101 struct registry_data
102 {
103   unsigned index;
104   registry_data_callback save;
105   registry_data_callback free;
106 };
107 
108 struct registry_data_registration
109 {
110   struct registry_data *data;
111   struct registry_data_registration *next;
112 };
113 
114 struct registry_data_registry
115 {
116   struct registry_data_registration *registrations;
117   unsigned num_registrations;
118 };
119 
120 /* Registry backend functions.  Client code uses the frontend
121    functions defined by DEFINE_REGISTRY below instead.  */
122 
123 const struct registry_data *register_data_with_cleanup
124   (struct registry_data_registry *registry,
125    registry_data_callback save,
126    registry_data_callback free);
127 
128 void registry_alloc_data (struct registry_data_registry *registry,
129 			  struct registry_fields *registry_fields);
130 
131 /* Cast FUNC and CONTAINER to the real types, and call FUNC, also
132    passing DATA.  */
133 typedef void (*registry_callback_adaptor) (registry_data_callback func,
134 					   struct registry_container *container,
135 					   void *data);
136 
137 void registry_clear_data (struct registry_data_registry *data_registry,
138 			  registry_callback_adaptor adaptor,
139 			  struct registry_container *container,
140 			  struct registry_fields *fields);
141 
142 void registry_container_free_data (struct registry_data_registry *data_registry,
143 				   registry_callback_adaptor adaptor,
144 				   struct registry_container *container,
145 				   struct registry_fields *fields);
146 
147 void registry_set_data (struct registry_fields *fields,
148 			const struct registry_data *data,
149 			void *value);
150 
151 void *registry_data (struct registry_fields *fields,
152 		     const struct registry_data *data);
153 
154 /* Define a new registry implementation.  */
155 
156 #define DEFINE_REGISTRY(TAG, ACCESS)					\
157 struct registry_data_registry TAG ## _data_registry = { NULL, 0 };	\
158 									\
159 const struct TAG ## _data *						\
160 register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \
161 					void (*free) (struct TAG *, void *)) \
162 {									\
163   return (struct TAG ## _data *)					\
164     register_data_with_cleanup (&TAG ## _data_registry,			\
165 				(registry_data_callback) save,		\
166 				(registry_data_callback) free);		\
167 }									\
168 									\
169 const struct TAG ## _data *						\
170 register_ ## TAG ## _data (void)					\
171 {									\
172   return register_ ## TAG ## _data_with_cleanup (NULL, NULL);		\
173 }									\
174 									\
175 static void								\
176 TAG ## _alloc_data (struct TAG *container)				\
177 {									\
178   struct registry_fields *rdata = &ACCESS (container)->registry_data;	\
179 									\
180   registry_alloc_data (&TAG ## _data_registry, rdata);			\
181 }									\
182 									\
183 static void								\
184 TAG ## registry_callback_adaptor (registry_data_callback func,		\
185 				  struct registry_container *container, \
186 				  void *data)				\
187 {									\
188   struct TAG *tagged_container = (struct TAG *) container;		\
189 									\
190   registry_ ## TAG ## _callback tagged_func				\
191     = (registry_ ## TAG ## _callback) func;				\
192 									\
193   tagged_func (tagged_container, data);					\
194 }									\
195 									\
196 void									\
197 clear_ ## TAG ## _data (struct TAG *container)				\
198 {									\
199   struct registry_fields *rdata = &ACCESS (container)->registry_data;	\
200 									\
201   registry_clear_data (&TAG ## _data_registry,				\
202 		       TAG ## registry_callback_adaptor,		\
203 		       (struct registry_container *) container,		\
204 		       rdata);						\
205 }									\
206 									\
207 static void								\
208 TAG ## _free_data (struct TAG *container)				\
209 {									\
210   struct registry_fields *rdata = &ACCESS (container)->registry_data;	\
211 									\
212   registry_container_free_data (&TAG ## _data_registry,			\
213 				TAG ## registry_callback_adaptor,	\
214 				(struct registry_container *) container, \
215 				rdata);					\
216 }									\
217 									\
218 void									\
219 set_ ## TAG ## _data (struct TAG *container,				\
220 		      const struct TAG ## _data *data,			\
221 		      void *value)					\
222 {									\
223   struct registry_fields *rdata = &ACCESS (container)->registry_data;	\
224 									\
225   registry_set_data (rdata,						\
226 		     (struct registry_data *) data,			\
227 		     value);						\
228 }									\
229 									\
230 void *									\
231 TAG ## _data (struct TAG *container, const struct TAG ## _data *data)	\
232 {									\
233   struct registry_fields *rdata = &ACCESS (container)->registry_data;	\
234 									\
235   return registry_data (rdata,						\
236 			(struct registry_data *) data);			\
237 }
238 
239 
240 /* External declarations for the registry functions.  */
241 
242 #define DECLARE_REGISTRY(TAG)						\
243 struct TAG ## _data;							\
244 typedef void (*registry_ ## TAG ## _callback) (struct TAG *, void *);	\
245 extern const struct TAG ## _data *register_ ## TAG ## _data (void);	\
246 extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \
247  (registry_ ## TAG ## _callback save, registry_ ## TAG ## _callback free); \
248 extern void clear_ ## TAG ## _data (struct TAG *);			\
249 extern void set_ ## TAG ## _data (struct TAG *,				\
250 				  const struct TAG ## _data *data,	\
251 				  void *value);				\
252 extern void *TAG ## _data (struct TAG *,				\
253 			   const struct TAG ## _data *data);		\
254 									\
255 template<typename DATA, typename Deleter = std::default_delete<DATA>>	\
256 class TAG ## _key							\
257 {									\
258 public:									\
259 									\
260   TAG ## _key ()							\
261     : m_key (register_ ## TAG ## _data_with_cleanup (nullptr,		\
262 						     cleanup))		\
263   {									\
264   }									\
265 									\
266   DATA *get (struct TAG *obj) const					\
267   {									\
268     return (DATA *) TAG ## _data (obj, m_key);				\
269   }									\
270 									\
271   void set (struct TAG *obj, DATA *data) const				\
272   {									\
273     set_ ## TAG ## _data (obj, m_key, data);				\
274   }									\
275 									\
276   template<typename Dummy = DATA *, typename... Args>			\
277   typename std::enable_if<std::is_same<Deleter,				\
278 				       std::default_delete<DATA>>::value, \
279 			  Dummy>::type					\
280   emplace (struct TAG *obj, Args &&...args) const			\
281   {									\
282     DATA *result = new DATA (std::forward<Args> (args)...);		\
283     set (obj, result);							\
284     return result;							\
285   }									\
286 									\
287   void clear (struct TAG *obj) const					\
288   {									\
289     DATA *datum = get (obj);						\
290     if (datum != nullptr)						\
291       {									\
292 	cleanup (obj, datum);						\
293 	set (obj, nullptr);						\
294       }									\
295   }									\
296 									\
297 private:								\
298 									\
299   static void cleanup (struct TAG *obj, void *arg)			\
300   {									\
301     DATA *datum = (DATA *) arg;						\
302     Deleter d;								\
303     d (datum);								\
304   }									\
305 									\
306   const struct TAG ## _data *m_key;					\
307 };
308 
309 #endif /* REGISTRY_H */
310