Free Electron
Component.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_Component_h__
8 #define __plugin_Component_h__
9 
10 #define FE_COMPONENT_TRACK FE_COUNTED_TRACK
11 
12 namespace fe
13 {
14 
15 /**************************************************************************//**
16  @brief Base for all interfacable components
17 
18  @ingroup plugin
19 *//***************************************************************************/
20 class FE_DL_EXPORT Component:
21  public Handled<Component>,
22  public CastableAs<Component>,
23  virtual public Initialized
24 {
25  private:
26 
27  /// @brief Reference hub used by Component::adjoin()
28  class Hub: public Handled<Hub>
29  {
30  public:
31  Hub(void);
32  virtual ~Hub(void);
33 
34  const String& name(void) const { return m_name; }
35  void setName(const String& name) { m_name=name; }
36 
37  void attach(Component* pComponent,BWORD singleton);
38  void detach(Component* pComponent,BWORD singleton);
39 
40  private:
41  List< sp<Component> > m_persistList;
42  String m_name;
43  U32 m_singletonCount;
44  };
45 
46 
47  public:
48  Component(void);
49 virtual ~Component(void);
50 
51 #if FE_CPLUSPLUS >= 201103L
52  Component(Component&&) =delete;
53  Component(const Component&) =delete;
54 
55  Component& operator=(Component&&) =delete;
56  Component& operator=(const Component&) =delete;
57 #endif
58 
59  /** @fn void fe::Component::initialize(void)
60 
61  @brief Called after construction and basic
62  factory initialization.
63 
64  This is an optional site for setup steps that
65  use members not available during true
66  construction.
67 
68  Any derived class can supply an additional
69  non-virtual initialize function.
70 
71  To allow all the initialize functions to be
72  called, any class @em T supplying an
73  @em initialize method must also derive from
74  Initialize <T>. */
75 
76  /// @brief Return the components chosen name
77 const String& name(void) const { return m_name; }
78  /// @brief Return the annotated chosen name
79 const String verboseName(void) const { return name(); }
80  /** @brief Rename the component to anything you want
81 
82  The default name is the implementation name
83  as given by the factory. */
84  void setName(const String& name) { m_name=name; }
85 
86  /** @brief Get the Registry that created this
87  component
88 
89  This allows any component to easily create
90  other components. The Registry can also point
91  you to the Master. */
92  hp<Registry> registry(void) const;
93 
94  /** @brief Tie this component's lifetime to another
95 
96  A hub is used to keep all components in a
97  group alive as long as at least one of them is
98  referenced (in addition to one reference each
99  by the hub). Once the reference count of every
100  component in the group drops to one, the
101  hub destructs and all the components
102  collapse.
103 
104  Each component can only be adjoined once.
105  A component can be adjoined to by any number
106  of other components.
107 
108  Adjoining can happen in any order and it
109  doesn't matter which existing component in a
110  particular group a component adjoins to.
111 
112  fe::hp's do not count as references. It is
113  usually good practice for Components within
114  the same hub to only retain fe::hp's to
115  each other, not fe::sp's. As long as
116  fe::sp's exist, other than from the hub, the
117  group will persist indefinitely. */
118  void adjoin(sp<Component> spComponent);
119 
120  /** Convienience function to registry()->create()
121  */
122  sp<Component> create(const String &implementation,
123  BWORD quiet=FALSE) const;
124 
125  /// @brief Untie component from Hub, if connected
126  void disjoin(void);
127 
128  String factoryName(void);
129 
130  /** @brief Store a reference to the
131  library used to instantiate this component.
132 
133  Setting this value externally may be ignored or
134  cause an assertion.
135 
136  This reference provide two roles:
137  - It prevents this library from being unloaded
138  while this component persists.
139  - If this is the last component of an abandoned
140  library, the end-life of this component
141  will cause the library to unload.
142 
143 
144  @internal */
145  void setLibrary(sp<Library> spLibrary);
146 
147  /** @brief Get the library that created the component.
148 
149  @internal */
150  sp<Library> library(void) { return m_spLibrary; }
151 
152  /** @brief Set the library's factory index
153 
154  @internal */
155  void setFactoryIndex(I32 a_factoryIndex)
156  { m_factoryIndex=a_factoryIndex; }
157 
158  /** @brief Get the library's factory index
159 
160  A negative number indicates no known factory.
161 
162  @internal */
163  I32 factoryIndex(void) { return m_factoryIndex; }
164 
165  /** @brief Specify whether component is a singleton
166 
167  @internal */
168  void setSingleton(BWORD set) { m_singleton=set; }
169  /// @brief Return whether component is a singleton
170  BWORD isSingleton(void) { return m_singleton; }
171 
172  using Counted::acquire;
173 
174  /** @brief Specialized reference increment
175 
176  @internal */
177 virtual void acquire(void);
178  /** @brief Specialized reference decrement
179 
180  This virtual adds functionality to unload
181  libraries under specific circumstances.
182 
183  @internal */
184 virtual void release(void);
185 
186 
187  private:
188  void assignHub(Hub* pHub);
189  void setStray(BWORD stray);
190 
191  String m_name;
192  sp<Library> m_spLibrary;
193  hp<Hub> m_hpHub;
194  I32 m_factoryIndex;
195 
196  //* TODO combine flags
197  BWORD m_singleton;
198  BWORD m_stray;
199 };
200 
201 namespace internal
202 {
203 /** @brief Delete the component and unload libraries where appropriate
204 
205  @relates fe::Component
206 
207  Under the right circumstances, this unloads one or more unneeded libraries.
208  This function is reused by fe::Registry with pComponent=NULL.
209 
210  @internal */
211 FE_DL_EXPORT void FE_CDECL checkUnload(sp<Library>& pLibrary,
212  Component* pComponent=NULL);
213 } // namespace internal
214 
215 inline void Component::acquire(void)
216 {
217 // feLog("+%p Component::acquire %d %s\n",(U32)this,count(),name().c_str());
218 
219 #if FE_COUNTED_MT && FE_COMPONENT_TRACK
220  RecursiveMutex::Guard guard(Counted::ms_counted_mutex);
221 #endif
222 
223  int refCount;
224  Counted::acquire(refCount);
225 
226  if(m_hpHub.isValid())
227  {
228  if(refCount==2+isSingleton())
229  {
230  setStray(FALSE);
231  }
232  if(refCount==2)
233  {
234  m_hpHub->acquire();
235  m_hpHub->trackReference(this,"Component::acquire");
236  }
237  }
238 
239 #if FE_COMPONENT_TRACK
240  if(refCount && registry().isValid())
241  {
242  registry()->tracker().acquire(this,name(),refCount);
243  }
244 #endif
245 
246 // feLog("-%p Component::acquire\n",(U32)this);
247 }
248 
249 inline void Component::release(void)
250 {
251  int refCount;
252 
253  {
254 // feLog("+%p Component::release %d %s\n",(U32)this,count(),
255 // verboseName().c_str());
256 
257 #if FE_COUNTED_MT && FE_COMPONENT_TRACK
258  RecursiveMutex::Guard guard(Counted::ms_counted_mutex);
259 #endif
260 
261 #if FE_COMPONENT_TRACK
262  if(count() && registry().isValid())
263  {
264  registry()->tracker().release(this,verboseName(),count()-1);
265  }
266 #endif
267 
268  refCount=releaseInternal();
269  if(m_hpHub.isValid())
270  {
271  if(refCount==1+isSingleton())
272  {
273  setStray(TRUE);
274  }
275 
276  if(refCount==1)
277  {
278 // feLog("Component::release release Hub from %s\n",
279 // verboseName().c_str());
280 
281  m_hpHub->release();
282 
283  //* This component might now be deleted,
284  //* but only if it's the last on on the Hub.
285  //* Otherwise, it can be picked up again.
286  return;
287  }
288  }
289  }
290 
291  if(!refCount)
292  {
293  abandonHandle();
294  fe::internal::checkUnload(m_spLibrary,this);
295  }
296 }
297 
298 template <class T>
299 sp<T> component_cast( sp<Component> spC )
300 {
301  sp<T> spT(spC);
302  if(!spT.isValid())
303  {
304  if(spC.isValid())
305  {
306  throw fe::Exception(e_invalidPointer, "Component Assertion Error",
307  "%s as %s", spC->name().c_str(), FE_TYPESTRING(T).c_str());
308  }
309  else
310  {
311  throw fe::Exception(e_invalidPointer, "Component Assertion Error",
312  "invalid component");
313  }
314  }
315  return spT;
316 }
317 
318 #if FE_COMPILER==FE_GNU
319 #define feCast(T, comp) (fe::Exception::stage(__FILE__,__LINE__,__PRETTY_FUNCTION__),component_cast<T>(comp))
320 #elif FE_COMPILER==FE_MICROSOFT
321 #define feCast(T, comp) (fe::Exception::stage(__FILE__,__LINE__,__FUNCTION__),component_cast<T>(comp))
322 #else
323 #define feCast(T, comp) (fe::Exception::stage(__FILE__,__LINE__,__func__),component_cast<T>(comp))
324 #endif
325 
326 } // namespace fe
327 
328 #endif /* __plugin_Component_h__ */
Fully Bidirectional Doubly-Linked List.
Definition: List.h:496
virtual void acquire(void)
Increment the reference count.
Definition: Counted.h:64
const String verboseName(void) const
Return the annotated chosen name.
Definition: Component.h:79
kernel
Definition: namespace.dox:3
I32 factoryIndex(void)
Get the library&#39;s factory index.
Definition: Component.h:163
Generic exception carrying a fe::String payload.
Definition: Exception.h:34
BWORD isSingleton(void)
Return whether component is a singleton.
Definition: Component.h:170
Tracker & tracker(void)
Access the component tracker.
Definition: Registry.h:121
void setSingleton(BWORD set)
Specify whether component is a singleton.
Definition: Component.h:168
Automatically reference-counted string container.
Definition: String.h:128
Base for all interfacable components.
Definition: Component.h:20
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
const String & name(void) const
Return the components chosen name.
Definition: Component.h:77
Base class providing an fe::Handle to the derived class.
Definition: Handled.h:209
sp< Library > library(void)
Get the library that created the component.
Definition: Component.h:150
void setName(const String &name)
Rename the component to anything you want.
Definition: Component.h:84
Base class providing collective initialization (post-constructor)
Definition: Initialized.h:56
virtual void acquire(void)
Specialized reference increment.
Definition: Component.h:215
virtual void release(void)
Specialized reference decrement.
Definition: Component.h:249
void setFactoryIndex(I32 a_factoryIndex)
Set the library&#39;s factory index.
Definition: Component.h:155
Reference hub used by Component::adjoin()
Definition: Component.h:28
Per-class participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:192