File: Plugin.hh

package info (click to toggle)
ignition-plugin 1.2.1%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 728 kB
  • sloc: cpp: 4,712; ansic: 277; ruby: 128; sh: 38; makefile: 12
file content (220 lines) | stat: -rw-r--r-- 9,589 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * Copyright (C) 2017 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */


#ifndef IGNITION_PLUGIN_PLUGIN_HH_
#define IGNITION_PLUGIN_PLUGIN_HH_

#include <memory>
#include <map>
#include <string>

#include <ignition/utilities/SuppressWarning.hh>

#include <ignition/plugin/Export.hh>
#include <ignition/plugin/Info.hh>

namespace ignition
{
  namespace plugin
  {
    // Forward declaration
    namespace detail {
      template <class, class> class ComposePlugin;
      template <class> class SelectSpecializers;
    }
    class EnablePluginFromThis;
    class WeakPluginPtr;

    class IGNITION_PLUGIN_VISIBLE Plugin
    {
      // -------------------- Public API ---------------------

      /// \brief Get an interface of the specified type, if it is provided by
      /// this plugin.
      ///
      /// Note that the interface pointer you receive is owned by the Plugin
      /// object. You MUST NOT ever try to deallocate it yourself. Moreover, the
      /// pointer will be invalidated once all Plugin objects that refer to the
      /// same Plugin instance are destructed. Use the QueryInterfaceSharedPtr
      /// function in order to get a reference-counting pointer to an interface
      /// of this Plugin object. The pointer will remain valid as long as the
      /// std::shared_ptr provided by QueryInterfaceSharedPtr is alive.
      ///
      /// \return A raw pointer to the specified interface. If the requested
      /// _interfaceName is not provided by this Plugin, this returns a nullptr.
      /// This pointer is invalidated when the reference count of the plugin
      /// instance drops to zero.
      public: template <class Interface>
              Interface *QueryInterface();

      /// \brief const-qualified version of QueryInterface<Interface>()
      public: template <class Interface>
              const Interface *QueryInterface() const;

      /// \brief This function has been deprecated in favor of the version of
      /// QueryInterface which does not take a std::string argument.
      public: template <class Interface>
              IGN_DEPRECATED(0.0)
              Interface *QueryInterface(const std::string &/*_interfaceName*/);

      /// \brief const-qualified version of
      /// QueryInterface<Interface>(std::string)
      public: template <class Interface>
              IGN_DEPRECATED(0.0)
              const Interface *QueryInterface(
                  const std::string &/*_interfaceName*/) const;

      /// \brief Get the requested interface as a std::shared_ptr. The template
      /// argument Interface must exactly match the underlying type associated
      /// with _interfaceName, or else the behavior of this function is
      /// undefined.
      ///
      /// This std::shared_ptr and the interface+plugin that it refers to will
      /// remain valid, even if all Plugin objects which refer to the plugin
      /// instance are destructed.
      ///
      /// You MUST NOT attempt to pass a QueryInterface pointer into a
      /// std::shared_ptr yourself; that will result in double-delete memory
      /// errors. You must always call QueryInterfaceSharedPtr for a reference-
      /// counting pointer to an interface.
      ///
      /// \return A reference-counting pointer to the specified interface. This
      /// will keep the interface valid and the plugin instance alive, even if
      /// all Plugin objects that refer to this plugin instance are destructed.
      public: template <class Interface>
              std::shared_ptr<Interface> QueryInterfaceSharedPtr();

      /// \brief Same as QueryInterfaceSharedPtr<Interface>(), but it returns a
      /// std::shared_ptr to a const-qualified Interface.
      public: template <class Interface>
              std::shared_ptr<const Interface> QueryInterfaceSharedPtr() const;

      /// \brief This version of QueryInterfaceSharedPtr has been deprecated in
      /// favor of the version that does not take a std::string argument.
      public: template <class Interface>
              IGN_DEPRECATED(0.0)
              std::shared_ptr<Interface> QueryInterfaceSharedPtr(
                  const std::string &/*_interfaceName*/);

      /// \brief Same as QueryInterfaceSharedPtr<Interface>(std::string), but
      /// it returns a std::shared_ptr to a const-qualified Interface.
      public: template <class Interface>
              IGN_DEPRECATED(0.0)
              std::shared_ptr<const Interface> QueryInterfaceSharedPtr(
                  const std::string &/*_interfaceName*/) const;

      /// \brief Checks if this Plugin has the specified type of interface.
      /// \return Returns true if this Plugin has the specified type of
      /// interface, and false otherwise.
      public: template <class Interface>
              bool HasInterface() const;

      /// \brief Checks if this Plugin has the specified type of interface.
      ///
      /// By default, we expect you to pass in a demangled version of the
      /// interface name. If you want to use a mangled version of the name,
      /// set the `demangled` argument to false.
      ///
      /// \param[in] _interfaceName The name of the desired interface, as a
      /// std::string. Note that this expects the name to be mangled.
      /// \param[in] _demangled If _interfaceName is demangled, set this to
      /// true. If you are instead using the raw mangled name that gets provided
      /// by typeid(T).name(), then set _demangled to false.
      /// \return Returns true if this Plugin has the specified type of
      /// interface, and false otherwise.
      public: bool HasInterface(const std::string &_interfaceName,
                                const bool _demangled = true) const;

      /// \brief Gets the name of this Plugin.
      /// \return A pointer to the name of this Plugin, or nullptr if this
      /// Plugin is not instantiated.
      public: const std::string *Name() const;

      // -------------------- Private API -----------------------

      template <class> friend class TemplatePluginPtr;
      template <class...> friend class SpecializedPlugin;
      template <class, class> friend class detail::ComposePlugin;
      template <class> friend class detail::SelectSpecializers;
      friend class EnablePluginFromThis;
      friend class WeakPluginPtr;

      /// \brief Default constructor. This is kept protected to discourage users
      /// from instantiating them directly. They should instead only be
      /// retrieved as a PluginPtr from the plugin Loader.
      protected: Plugin();

      /// \brief Type-agnostic retriever for interfaces
      private: void *PrivateQueryInterface(
                  const std::string &_interfaceName) const;

      /// \brief Copy the plugin instance from another Plugin object
      private: void PrivateCopyPluginInstance(const Plugin &_other) const;

      /// \brief Copy an existing plugin instance into this plugin
      /// \param[in] _info
      ///   Pointer to the Info for this plugin
      /// \param[in] _instancePtr
      ///   Pointer to an already-existing abstract plugin instance pointer
      private: void PrivateCopyPluginInstance(
                  const ConstInfoPtr &_info,
                  const std::shared_ptr<void> &_instancePtr) const;

      /// \brief Create a new plugin instance based on the info provided
      /// \param[in] _info
      ///   Pointer to the Info for this plugin
      /// \param[in] _dlHandlePtr
      ///   Reference counter for the dl handle of this Plugin
      private: void PrivateCreatePluginInstance(
                  const ConstInfoPtr &_info,
                  const std::shared_ptr<void> &_dlHandlePtr) const;

      /// \brief Get a reference to the abstract instance being managed by this
      /// wrapper
      private: const std::shared_ptr<void> &PrivateGetInstancePtr() const;

      /// \brief Get a reference to the Info being used by this wrapper
      private: const ConstInfoPtr &PrivateGetInfoPtr() const;

      /// \brief The InterfaceMap type needs to get used in several places, like
      /// Plugin::Implementation and SpecializedPlugin<T>. We make the typedef
      /// public so that those other classes can use it without needing to be
      /// friends of Plugin. End-users should not have any need for this
      /// typedef.
      public: using InterfaceMap = std::map<std::string, void*>;

      /// \brief Get or create an iterator to the std::map that holds pointers
      /// to the various interfaces provided by this plugin instance.
      private: InterfaceMap::iterator PrivateGetOrCreateIterator(
          const std::string &_interfaceName);

      class Implementation;
      IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING
      /// \brief PIMPL pointer to the implementation of this class.
      private: const std::unique_ptr<Implementation> dataPtr;
      IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING

      /// \brief Virtual destructor
      public: virtual ~Plugin();
    };
  }
}

#include "ignition/plugin/detail/Plugin.hh"

#endif