Free Electron
Library.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __plugin_Library_h__
8 #define __plugin_Library_h__
9 
10 namespace fe
11 {
12 
13 /**************************************************************************//**
14  @brief Interface into a dynamic library to access its factories
15 
16  @ingroup plugin
17 
18  Each dynamic library should contain a single code block exposing
19  component implementations it can create. For example,
20 
21  @code
22  extern "C"
23  {
24 
25  FE_DL_EXPORT fe::Library *CreateLibrary(fe::sp<fe::Master>)
26  {
27  fe::Library *pLibrary = new fe::Library();
28  pLibrary->add<MyComponent>("my.component");
29  pLibrary->addSingleton<MySingleton>("my.singleton");
30  return pLibrary;
31  }
32 
33  }
34  @endcode
35 
36  This code block will create the neccessary factories.
37  It is not optional since omitting it makes the library useless
38  (you can set up automatic dynamic linking in your build).
39 
40  Another code block can be optionally used to automatically load
41  any number of other libraries prior to the given library. For example,
42  @code
43  extern "C"
44  {
45 
46  FE_DL_EXPORT void ListDependencies(fe::List<fe::String*>& list)
47  {
48  list.append(new fe::String("otherDL"));
49  list.append(new fe::String("anotherDL"));
50  }
51 
52  }
53  @endcode
54 
55  If this block is omitted, no dependency preloading is performed.
56 
57  By convention, these two blocks are provided together in a file named
58  like moduleDL.cc, one for each module.
59 *//***************************************************************************/
60 class FE_DL_EXPORT Library : public Counted, public ObjectSafe<Library>
61 {
62  /**********************************************************************//**
63  @brief Type-nonspecific base class for factories
64  *//***********************************************************************/
65  class BaseFactory: public Counted
66  {
67  public:
68  BaseFactory(const String& name):
69  m_name(name)
70  { m_className.sPrintf("Factory<%s>",name.c_str());
71  suppressReport(); }
72  virtual ~BaseFactory(void) {}
73 
74  /// @brief Return the factory's type's name
75  const String &name(void) const { return m_name; }
76 
77  /// @brief Return the factory's templated name
78  const String verboseName(void) const { return m_className; }
79 
80  /** @brief Instantiate a component
81 
82  The implementation type is the business of the
83  derived class.
84 
85  @internal */
86  virtual sp<Component> create(Library *pLibrary,
87  I32 a_factoryIndex) const =0;
88 
89  private:
90  String m_name;
91  String m_className;
92  };
93 
94  /**********************************************************************//**
95  @brief Type-specific factory template
96  *//***********************************************************************/
97  template <typename T>
98  class Factory: public BaseFactory
99  {
100  public:
101  Factory(const String& name): BaseFactory(name) {}
102  virtual ~Factory(void) {}
103 
104  //* VC7 can't seem to handle defining this outside
105  //* of the class declaration.
106  /** @brief Instantiate a component
107 
108  @internal */
109  virtual sp<Component> create(Library* pLibrary,
110  I32 a_factoryIndex) const
111  {
112 // feLog("fe::Library::Factory<T>::create()"
113 // " \"%s\"\n",this->name().c_str());
114  sp<Component> spComponent(Library::create<T>(
115  this->name(),pLibrary,a_factoryIndex));
116 // feLog(" \"%s\"=%p\n",this->name().c_str(),
117 // (U32)spComponent.raw());
118 #if FALSE
119  if(!spComponent.isValid())
120  {
121  feX("fe::Library::Factory<T>::create",
122  "%s is not a valid fe::Component",
123  this->name().c_str());
124  }
125 #endif
126  return spComponent;
127  }
128  };
129 
130  public:
131  Library(void);
132 virtual ~Library(void);
133 
134  /** @brief Create a named factory for the given
135  type and add it to the library's collection */
136  template <typename T>
137  void add(const String &name)
138  { addFactory(new Factory<T>(name),FALSE); }
139 
140  /** @brief Create a named factory for the given
141  type, but treat it as a singleton */
142  template <typename T>
143  void addSingleton(const String &name)
144  { addFactory(new Factory<T>(name),TRUE); }
145 
146  /// @brief Return the library name
147 const String& name(void) const { return m_name; }
148 
149  /** @brief Append the names of the available
150  factories to the given array */
151  void populateManifest(Array<String> &names) const;
152 
153  /** @brief Return number of references adjusted
154  for singletons
155 
156  Once this drops to 1 plus the number of
157  factories, there are no outstanding
158  references outside of the Library and the
159  singletons it has instantiated. */
160  U32 adjustedReferences(void) const;
161 
162  /** @brief Release all instantiated singletons
163 
164  @internal
165 
166  This command is intended to be part of
167  an internal shutdown procedure.
168  If any of the singletons was still otherwise
169  referenced and an attempt is made to create the
170  singleton again, a new independent instance
171  of the singleton will be created. */
172  void releaseSingletons(void);
173 
174  I32 strayCount(void) { return m_strayCount; }
175  I32 adjustStrayCount(I32 inc)
176  { return m_strayCount+=inc; }
177 
178  /** @brief Create component using the known index
179 
180  @internal */
181  sp<Component> create(U32 factoryIndex);
182 
183  /// @internal
184  String factoryName(U32 factoryIndex);
185 
186  /// @internal
187  hp<Registry> registry(void) const;
188  /// @internal
189  void setRegistry(sp<Registry> spRegistry);
190 
191  /// @internal
193  { return m_spChainLibrary; }
194  /** @brief Enforce FIFO by referencing prev lib
195  on stack
196 
197  @internal */
198  void setChainLibrary(sp<Library>& rspLibrary)
199  { m_spChainLibrary=rspLibrary; }
200 
201  /// for use in static lib scenario
202  void setName(const char *a_name)
203  { m_name = a_name; }
204 
205  /// @internal
206  DL_Loader* getLoader(void) const { return m_pLoader; }
207  /// @internal
208  void setLoader(DL_Loader* pLoader)
209  {
210  m_pLoader=pLoader;
211  if(m_pLoader)
212  {
213  m_name=m_pLoader->name().basename()
214  .chop(".so").chop(".lib")
215  .prechop("lib");
216  }
217  }
218 
219  /** @brief Instantiate and initialize a component
220  without using a factory
221 
222  This is useful for unit tests that don't want
223  to utilize a proper library.
224  It is not intended for general use.
225 
226  You have to explicitly provide the class
227  type as the template argument. */
228  template<typename T>
229 static sp<Component> create(String name,Library* pLibrary=NULL,
230  I32 a_factoryIndex= -1)
231  {
232  try
233  {
234  T* pT=new T();
235  sp<Component> spComponent(pT);
236  initComponent(spComponent,pT,sizeof(T),
237  name,pLibrary,a_factoryIndex);
238  return spComponent;
239  }
240  catch(fe::Exception &e)
241  {
242  e.log();
243  if(e.getResult()==e_cannotCreate)
244  {
245 #if FE_CODEGEN<=FE_DEBUG
246  feLog("Library::create"
247  " cannot create \"%s\"\n",
248  name.c_str());
249 #endif
250  }
251  else
252  {
253  throw;
254  }
255  }
256  catch(...)
257  {
258  feLog("Library::create"
259  " uncaught exception\n");
260  throw;
261  }
262 
263  return sp<Component>();
264  }
265 
266  private:
267 
268 static void initComponent(sp<Component>& rspComponent,
269  void* ptr,U32 size,String name,
270  Library* pLibrary,I32 a_factoryIndex);
271 
272  class FactoryData
273  {
274  public:
275  sp<BaseFactory> m_spFactory;
276  U32 m_singleton;
277  sp<Component> m_spSingleton;
278  };
279 
280  Array<FactoryData> m_factories;
281 
282  sp<Library> m_spChainLibrary;
283  DL_Loader* m_pLoader;
284  I32 m_strayCount;
285 
286  //* don't hold a reference, Registry manages the Library
287  Registry* m_pRegistry;
288  String m_name;
289 
290  void addFactory(BaseFactory *pFactory,BWORD singleton);
291 };
292 
293 
294 } /* namespace */
295 
296 #endif /* __plugin_Library_h__ */
const String & name(void) const
Return the library name.
Definition: Library.h:147
Object level locking for thread safety.
Definition: Safe.h:216
Raw access to a dynamic library.
Definition: DL_Loader.h:18
Type-nonspecific base class for factories.
Definition: Library.h:65
Type-specific factory template.
Definition: Library.h:98
const FESTRING_I8 * c_str(void) const
Return the contents of the 8-bit buffer cast as signed bytes.
Definition: String.h:352
Heap-based support for classes participating in fe::ptr <>
Definition: Counted.h:35
String prechop(const String &prefix) const
Return the substring after the prefix.
Definition: String.cc:118
void setName(const char *a_name)
for use in static lib scenario
Definition: Library.h:202
kernel
Definition: namespace.dox:3
Dynamic Library Manager.
Definition: Registry.h:25
void log(void)
Send the message to the global log.
Definition: Exception.cc:201
DL_Loader * getLoader(void) const
Definition: Library.h:206
Generic exception carrying a fe::String payload.
Definition: Exception.h:34
void setLoader(DL_Loader *pLoader)
Definition: Library.h:208
String basename(void) const
Return the substring following the last &#39;/&#39;.
Definition: String.cc:98
sp< Library > getChainLibrary(void) const
Definition: Library.h:192
Interface into a dynamic library to access its factories.
Definition: Library.h:60
Automatically reference-counted string container.
Definition: String.h:128
const String & name(void) const
Return the factory&#39;s type&#39;s name.
Definition: Library.h:75
void setChainLibrary(sp< Library > &rspLibrary)
Enforce FIFO by referencing prev lib on stack.
Definition: Library.h:198
Wrapper for std::vector.
Definition: Array.h:21
const String verboseName(void) const
Return the factory&#39;s templated name.
Definition: Library.h:78
static sp< Component > create(String name, Library *pLibrary=NULL, I32 a_factoryIndex=-1)
Instantiate and initialize a component without using a factory.
Definition: Library.h:229
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
void add(const String &name)
Create a named factory for the given type and add it to the library&#39;s collection. ...
Definition: Library.h:137
void addSingleton(const String &name)
Create a named factory for the given type, but treat it as a singleton.
Definition: Library.h:143
virtual sp< Component > create(Library *pLibrary, I32 a_factoryIndex) const
Instantiate a component.
Definition: Library.h:109
const String & name(void) const
Returns the name of the library as it was opened.
Definition: DL_Loader.h:51
String chop(const String &suffix) const
Return the substring before the suffix.
Definition: String.cc:159