File: SpecializedPlugin.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 (165 lines) | stat: -rw-r--r-- 6,497 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
/*
 * 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_SPECIALIZEDPLUGIN_HH_
#define IGNITION_PLUGIN_SPECIALIZEDPLUGIN_HH_

#include <memory>
#include "ignition/plugin/Plugin.hh"

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

    // Forward declaration of the variadic template SpecializedPlugin class.
    template <class... OtherSpecInterfaces>
    class SpecializedPlugin;

    /// \brief This class allows Plugin instances to have high-speed access to
    /// interfaces that can be anticipated at compile time. The plugin does
    /// not have to actually offer the specialized interface in order to get
    /// this performance improvement. This template is variadic, so it can
    /// support arbitrarily many interfaces.
    ///
    /// Usage example:
    ///
    /// \code
    ///     using MySpecialPluginPtr = SpecializedPluginPtr<
    ///         MyInterface1, FooInterface, MyInterface2, BarInterface>;
    ///
    ///     MySpecialPluginPtr plugin = loader->Instantiate(pluginName);
    /// \endcode
    ///
    /// Then, calling the function
    ///
    /// \code
    ///     plugin->QueryInterface<FooInterface>();
    /// \endcode
    ///
    /// will have extremely high-speed associated with it. It will provide
    /// direct access to the the `FooInterface*` of `plugin`. If `plugin` does
    /// not actually offer `FooInterface`, then it will return a nullptr, still
    /// at extremely high speed.
    template <class SpecInterface>
    class SpecializedPlugin<SpecInterface> : public virtual Plugin
    {
      // -------------------- Public API ---------------------

      // Inherit function overloads
      public: using Plugin::QueryInterface;
      public: using Plugin::QueryInterfaceSharedPtr;
      public: using Plugin::HasInterface;

      // Documentation inherited
      public: template <class Interface>
              Interface *QueryInterface();

      // Documentation inherited
      public: template <class Interface>
              const Interface *QueryInterface() const;

      // Documentation inherited
      public: template <class Interface>
              std::shared_ptr<Interface> QueryInterfaceSharedPtr();

      // Documentation inherited
      public: template <class Interface>
              std::shared_ptr<const Interface> QueryInterfaceSharedPtr() const;

      // Documentation inherited
      public: template <class Interface>
              bool HasInterface() const;


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

      // Declare friendship
      template <class...> friend class SpecializedPlugin;
      template <class, class> friend class detail::ComposePlugin;
      template <class> friend class detail::SelectSpecializers;
      template <class> friend class TemplatePluginPtr;

      /// \brief type is an empty placeholder class which is used by the private
      /// member functions to provide two overloads: a high-performance one for
      /// the specialized interface, and a normal-performance one for all other
      /// Interface types.
      private: template <class T> struct type { };

      /// \brief Delegate the function to the standard Plugin method
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return Pointer to the intergace
      private: template <class Interface>
               Interface *PrivateQueryInterface(type<Interface>);

      /// \brief Use a high-speed accessor to provide this specialized interface
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return Pointer to the specialized intergace
      private: SpecInterface *PrivateQueryInterface(type<SpecInterface>);

      /// \brief Delegate the function to the standard Plugin method
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return Pointer to the specialized intergace
      private: template <class Interface>
               const Interface *PrivateQueryInterface(type<Interface>) const;

      /// \brief Use a high-speed accessor to provide this specialized interface
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return Pointer to the specialized intergace
      private: const SpecInterface *PrivateQueryInterface(
                   type<SpecInterface>) const;

      /// \brief Delegate the function to the standard PluginPtr method
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return True if the interface is present.
      private: template <class Interface>
               bool PrivateHasInterface(type<Interface>) const;

      /// \brief Use a high-speed accessor to check this specialized interface
      /// \param[in] _type Empty object meant to guide the compiler to pick the
      /// desired implementation.
      /// \return True if the interface is present.
      private: bool PrivateHasInterface(type<SpecInterface>) const;

      // Dev note (MXG): The privateSpecializedInterfaceIterator object must be
      // available to the user during their compile time, so it cannot be hidden
      // using PIMPL. The iterator is const because it must always point to the
      // same entry throughout its entire lifecycle.
      /// \brief Iterator that points to the entry of the specialized interface
      private:
      const Plugin::InterfaceMap::iterator privateSpecializedInterfaceIterator;

      /// \brief Default constructor
      protected: SpecializedPlugin();
    };
  }
}

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

#endif