diff options
author | Tom Tromey <tom@tromey.com> | 2019-04-09 20:21:06 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2019-05-08 16:01:44 -0600 |
commit | 5f6e90a0cec8c269634ba0bff3c9e549a903c39a (patch) | |
tree | 2eb7ff67d1ab10909eb80099f8cf6d76e25f7d0e | |
parent | 1bd0c6e4964f68523794aded05aa4d184db44d48 (diff) | |
download | fsf-binutils-gdb-5f6e90a0cec8c269634ba0bff3c9e549a903c39a.zip fsf-binutils-gdb-5f6e90a0cec8c269634ba0bff3c9e549a903c39a.tar.gz fsf-binutils-gdb-5f6e90a0cec8c269634ba0bff3c9e549a903c39a.tar.bz2 |
Add a type-safe C++ interface to a registry
This changes DECLARE_REGISTRY to add a type-safe interface. This
interface is a C++ class that handles the details of registering a
key, and provides various useful methods, including policy-based
cleanup.
gdb/ChangeLog
2019-05-08 Tom Tromey <tom@tromey.com>
* registry.h (DECLARE_REGISTRY): Define the _key class.
-rw-r--r-- | gdb/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/registry.h | 68 |
2 files changed, 66 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 24cf12c..b5e4422 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,7 @@ +2019-05-08 Tom Tromey <tom@tromey.com> + + * registry.h (DECLARE_REGISTRY): Define the _key class. + 2019-05-08 Andrew Burgess <andrew.burgess@embecosm.com> * NEWS: Merge two 'New commands' sections. diff --git a/gdb/registry.h b/gdb/registry.h index 3881e29..683d905 100644 --- a/gdb/registry.h +++ b/gdb/registry.h @@ -20,6 +20,8 @@ #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. @@ -243,11 +245,65 @@ 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); +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 */ |