ServiceProviderWrappers.h
Go to the documentation of this file.
1 /**
2  * @file ServiceProviderWrappers.h
3  * @brief Skeleton for a art service interface to service providers
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date April 19, 2016
6  *
7  * This is a pure template library.
8  * The callers will need to link to:
9  *
10  * * `${ART_FRAMEWORK_SERVICES_REGISTRY}`
11  *
12  * It provides:
13  *
14  * * SimpleServiceProviderWrapper: wrap a service with a single implementation
15  * * ServiceProviderImplementationWrapper: wrap a concrete implementation of a
16  * service provider interface supporting multiple implementations
17  *
18  */
19 
20 #ifndef COREUTILS_SERVICEPROVIDERWRAPPERS_H
21 #define COREUTILS_SERVICEPROVIDERWRAPPERS_H 1
22 
23 
24 // GArSoft libraries
25 #include "CoreUtils/ServiceUtil.h" // gar::providerFrom() (for includers)
26 
27 // framework and support libraries
31 
32 // C/C++ standard libraries
33 #include <memory> // std::unique_ptr<>
34 
35 
36 // forward declarations
37 namespace art { class ActivityRegistry; }
38 namespace fhicl { class ParameterSet; }
39 
40 
41 namespace gar {
42 
43  /** **********************************************************************
44  * @brief Service returning a provider
45  * @tparam PROVIDER type of service provider to be returned
46  *
47  * This class provides the simplest possible art service to wrap a GArSoft
48  * service provider.
49  * The service is not reacting to any framework events.
50  *
51  * The configuration is passed directly to the provider.
52  *
53  * The simplest way to create an art service with this template is:
54  *
55  * #include "CoreUtils/ServiceProviderWrappers.h"
56  * #include "path/to/MyProvider.h"
57  *
58  * #include "art/Framework/Services/Registry/ServiceDeclarationMacros.h"
59  * #include "art/Framework/Services/Registry/ServiceDefinitionMacros.h"
60  *
61  * namespace myprov {
62  *
63  * using MyService = gar::SimpleServiceProviderWrapper<MyProvider>;
64  *
65  * }
66  *
67  * DECLARE_ART_SERVICE(myprov::MyService, LEGACY)
68  *
69  * An implementation file is necessary too, that will look like:
70  *
71  * #include "path/to/MyService.h"
72  *
73  * DEFINE_ART_SERVICE(myprov::MyService)
74  *
75  * If callback registration is needed, a class can derive from this template
76  * and still gain a bit of boilerplate facility. That is:
77  * - a `provider_type` definition (required by `gar::providerFrom()`)
78  * - a `provider()` method to access the provider (required by
79  * `gar::providerFrom()`)
80  * - a `Parameters` definition (used by art to print accepted configuration)
81  * - a constructor supporting FHiCL configuration validation
82  * - transparent life management of the provider instance
83  *
84  * Requirements on the service provider:
85  * - a data type `Config` being the configuration object. This is the object
86  * wrapped by `fhicl::Table` when performing FHiCL validation.
87  * - a constructor with as argument a constant reference to a Config object.
88  * The provider should be configured by that constructor.
89  *
90  */
91  template <class PROVIDER>
93 
94  public:
95  using provider_type = PROVIDER; ///< type of the service provider
96 
97  /// Type of configuration parameter (for art description)
99 
100 
101  /// Constructor (using a configuration table)
104  : prov(std::make_unique<provider_type>(config()))
105  {}
106 
107 
108  /// Returns a constant pointer to the service provider
109  provider_type const* provider() const { return prov.get(); }
110 
111 
112  private:
113 
114  std::unique_ptr<provider_type> prov; ///< service provider
115 
116  }; // SimpleServiceProviderWrapper<>
117 
118 
119 
120  /** **********************************************************************
121  * @brief Service returning a provider interface
122  * @tparam PROVIDER type of service provider interface to be returned
123  * @see ServiceProviderImplementationWrapper
124  *
125  * This class provides a art service to wrap a GArSoft service provider
126  * interface.
127  *
128  * The behaviour of the implementations is not constrained by this interface.
129  * It only adds support for `gar::providerFrom()` function.
130  *
131  * Implementations must override `do_provider()` to return a pointer which
132  * `provider()` will forward to the caller.
133  *
134  */
135  template <class PROVIDER>
137 
138  public:
139  using provider_type = PROVIDER; ///< type of the service provider
140 
141  /// Virtual destructor
142  virtual ~ServiceProviderInterfaceWrapper() = default;
143 
144 
145  /// Returns a constant pointer to the service provider interface
146  provider_type const* provider() const { return do_provider(); }
147 
148 
149  protected:
150 
151  /// Implementation of the provider() function, to be overridden
152  virtual provider_type const* do_provider() const = 0;
153 
154  }; // ServiceProviderInterfaceWrapper<>
155 
156 
157 
158  /** *************************************************************************
159  * @brief Service implementation returning a provider
160  * @tparam INTERFACE type of art service being implemented
161  * @tparam PROVIDER type of service provider to be returned
162  * @see ServiceProviderInterfaceWrapper
163  *
164  * This class is suitable for a simple art service implementing an interface.
165  * This is the case of a service that can have multiple implementations,
166  * for example an experiment-specific access to a database.
167  * In this case, the art service is described by an interface, and many
168  * services can inherit and implement it.
169  *
170  * In the factorization model recommended in GArSoft, this hierarchy of art
171  * service implementations derived by a common interface is mirrored in a
172  * matching hierarchy of service provider implementation derived by a common
173  * service provider interface.
174  * In this model, services are basically trivial classes that return a
175  * pointer to the provider through a prescribed interface. The only relevant
176  * exception is that services may also register framework callbacks.
177  *
178  * Given the nature of the service returning a provider, its structure is
179  * repetitive. This class implements most of that repetitive frame.
180  * The resulting service is not reacting to any framework events.
181  *
182  * The configuration of the service is passed directly to the provider.
183  *
184  * Given that we want to have a service that implements the service
185  * `MyServiceInterface` and returns a provider implementation "A" called
186  * `MyProviderA`, the simplest way to create it with this template is:
187  *
188  * #include "CoreUtils/ServiceProviderWrappers.h"
189  * #include "path/to/MyProviderA.h"
190  * #include "path/to/MyServiceInterface.h"
191  *
192  * #include "art/Framework/Services/Registry/ServiceDeclarationMacros.h"
193  * #include "art/Framework/Services/Registry/ServiceDefinitionMacros.h"
194  *
195  * namespace myprov {
196  *
197  * using MyServiceA = gar::ServiceProviderImplementationWrapper
198  * <MyProviderA, MyServiceInterface>;
199  *
200  * }
201  *
202  * DECLARE_ART_SERVICE_INTERFACE_IMPL
203  * (myprov::MyServiceA, myprov::MyService, LEGACY)
204  *
205  *
206  * The class `MyServiceInterface` is expected to have been defined via
207  * `ServiceProviderInterfaceWrapper`.
208  * An implementation file is necessary too, that will look like:
209  *
210  * #include "path/to/MyServiceA.h"
211  *
212  * DEFINE_ART_SERVICE_INTERFACE_IMPL
213  * (myprov::MyServiceA, myprov::MyService)
214  *
215  * If callback registration is needed, a class can derive from this template
216  * and still gain a bit of boilerplate facility. That is:
217  *
218  * * a `provider_type` definition (required by `gar::providerFrom()`)
219  * * a `provider()` method to access the provider (required by
220  * `gar::providerFrom()`)
221  * - a `Parameters` definition (used by art to print accepted configuration)
222  * - a constructor supporting FHiCL configuration validation
223  * - transparent life management of the provider instance
224  * * a `concrete_provider_type` definition (that is PROVIDER)
225  * * a `service_interface_type` definition (that is INTERFACE)
226  *
227  * Requirements on the service provider (PROVIDER):
228  * - a data type `Config` being the configuration object. This is the object
229  * wrapped by `fhicl::Table` when performing FHiCL validation.
230  * - a constructor with as argument a constant reference to a Config object.
231  * The provider should be configured by that constructor.
232  *
233  * Requirements on the service interface (INTERFACE):
234  * - a data type `provider_type` representing the abstract interface of the
235  * service provider
236  * - a virtual method `do_provider()` where the retrieval of the provider
237  * is expected to happen; this method is overridden
238  *
239  */
240  template <typename PROVIDER, typename INTERFACE>
241  class ServiceProviderImplementationWrapper: public INTERFACE {
242 
243  public:
244  /// type of service provider implementation
245  using concrete_provider_type = PROVIDER;
246 
247  /// art service interface class
248  using service_interface_type = INTERFACE;
249 
250  /// type of service provider interface
251  using provider_type = typename service_interface_type::provider_type;
252 
253  /// Type of configuration parameter (for art description)
254  using Parameters
256 
257 
258  /// Constructor (using a configuration table)
260  (Parameters const& config, ::art::ActivityRegistry&)
261  : prov(std::make_unique<concrete_provider_type>(config()))
262  {}
263 
264 
265  private:
266  std::unique_ptr<concrete_provider_type> prov; ///< service provider
267 
268  /// Returns a constant pointer to the service provider
269  virtual provider_type const* do_provider() const override
270  { return prov.get(); }
271 
272  }; // ServiceProviderImplementationWrapper
273 
274 
275 } // namespace gar
276 
277 
278 #endif // COREUTILS_SERVICEPROVIDERWRAPPERS_H
PROVIDER provider_type
type of the service provider
PROVIDER concrete_provider_type
type of service provider implementation
std::unique_ptr< concrete_provider_type > prov
service provider
std::unique_ptr< provider_type > prov
service provider
provider_type const * provider() const
Returns a constant pointer to the service provider.
Service returning a provider.
Service returning a provider interface.
INTERFACE service_interface_type
art service interface class
static Config * config
Definition: config.cpp:1054
virtual provider_type const * do_provider() const override
Returns a constant pointer to the service provider.
Service implementation returning a provider.
provider_type const * provider() const
Returns a constant pointer to the service provider interface.
typename service_interface_type::provider_type provider_type
type of service provider interface
General GArSoft Utilities.
PROVIDER provider_type
type of the service provider