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