GCC Code Coverage Report


Directory: ./
File: include/hpp/corbaserver/servant-base.hh
Date: 2024-12-13 15:50:05
Exec Total Coverage
Lines: 85 132 64.4%
Branches: 70 202 34.7%

Line Branch Exec Source
1 // Copyright (C) 2019 by Joseph Mirabel, LAAS-CNRS.
2 //
3
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 // DAMAGE.
27 //
28 // This software is provided "as is" without warranty of any kind,
29 // either expressed or implied, including but not limited to the
30 // implied warranties of fitness for a particular purpose.
31 //
32 // See the COPYING file for more information.
33
34 #ifndef HPP_CORBASERVER_SERVANT_BASE_HH
35 #define HPP_CORBASERVER_SERVANT_BASE_HH
36
37 #include <hpp/common-idl.hh>
38 #include <hpp/corbaserver/server.hh>
39
40 namespace hpp {
41 namespace corbaServer {
42 /// \addtogroup hpp_corbaserver_extend_bindings Extending the bindings
43 /// Classes and functions related to the addition of HPP class bindings.
44 ///
45 /// Example usage can be found in classes
46 /// hpp::corbaServer::core_idl::Path,
47 /// hpp::corbaServer::core_idl::PathVector,
48 /// hpp::corbaServer::core_idl::Distance
49 ///
50 /// \par Steps for the topmost class of an hierarchy, called ClassA:
51 /// - optionally write a storage class (or use shared_ptr<ClassA>)
52 /// - create a `template <typename _Base, typename _Storage> ClassAServant `
53 /// that inherits
54 /// - \c _Base, this will be an IDL class that inherits from IDLClassA.
55 /// - \c ServantBase<shared_ptr<ClassA>, _Storage >
56 /// - Add `SERVANT_BASE_TYPEDEFS(ClassAServant, shared_ptr<ClassA>);`
57 /// - implement the functions of IDLClassA
58 /// - add after your class `typedef ClassAServant<IDLClassA, Storage> ClassA`.
59 ///
60 /// \par Steps for a derived class of an hierarchy, called ClassB:
61 /// - optionally write a storage class (or use shared_ptr<ClassB>)
62 /// - create a ` template <typename _Base, typename _Storage> ClassBServant`
63 /// that inherits
64 /// - \c ClassAServant<_Base, Storage>
65 /// - implement the functions of IDLClassB
66 /// - add after your class `typedef ClassBServant<IDLClassB, Storage> ClassB`.
67 ///
68 /// \par about the storage class
69 /// See details section of AbstractStorage.
70 ///
71 /// \{
72
73 #define SERVANT_BASE_TYPEDEFS(idlObj, hppObj) \
74 protected: \
75 using ::hpp::corbaServer::AbstractServantBase<hppObj>::server_; \
76 \
77 public: \
78 typedef _Base Base; \
79 typedef _Storage Storage; \
80 typedef idlObj Object; \
81 typedef idlObj##_ptr Object_ptr; \
82 typedef idlObj##_var Object_var; \
83 typedef ::hpp::corbaServer::ServantBase<hppObj, _Storage> _ServantBase; \
84 using _ServantBase::get; \
85 using _ServantBase::getT; \
86 using _ServantBase::getS
87
88 template <typename T>
89 struct hpp_traits {};
90
91 /// Abstract class used to avoid duplication of the servants.
92 class AbstractServantKey {
93 public:
94 virtual Server::ServantKey getServantKey() const = 0;
95
96 virtual bool expired() const = 0;
97 };
98
99 /// Base class for classes which provides bindings for HPP classes.
100 /// Example usage are hpp::corbaServer::core_idl::Path,
101 /// hpp::corbaServer::core_idl::PathVector,
102 /// hpp::corbaServer::core_idl::Distance
103 template <typename T>
104 class AbstractServantBase : AbstractServantKey {
105 public:
106 22 virtual ~AbstractServantBase() {}
107
108 typedef shared_ptr<T> TShPtr_t;
109 typedef weak_ptr<T> TWkPtr_t;
110
111 virtual TShPtr_t get() const = 0;
112
113 13 virtual Server::ServantKey getServantKey() const { return get().get(); }
114
115 protected:
116 13 AbstractServantBase(Server* server) : server_(server) {}
117
118 Server* server_;
119 };
120
121 template <typename T, typename _Storage>
122 class ServantBase : public AbstractServantBase<T> {
123 public:
124 typedef _Storage Storage;
125 using typename AbstractServantBase<T>::TShPtr_t;
126 using typename AbstractServantBase<T>::TWkPtr_t;
127 typedef weak_ptr<typename Storage::element_type> StorageElementWkPtr_t;
128 typedef shared_ptr<typename Storage::element_type> StorageElementShPtr_t;
129
130 22 virtual ~ServantBase() {}
131
132 46 virtual TShPtr_t get() const {
133 46 TWkPtr_t wk((StorageElementWkPtr_t)wrappedObject_);
134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
46 if (wk.expired()) {
135 // Object expired. Remove the servant and throw.
136 objectExpired();
137 }
138 92 return wk.lock();
139 46 }
140
141 bool expired() const final {
142 TWkPtr_t wk((StorageElementWkPtr_t)wrappedObject_);
143 return wk.expired();
144 }
145
146 36 StorageElementShPtr_t getT() const {
147 36 StorageElementWkPtr_t wk((StorageElementWkPtr_t)wrappedObject_);
148
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
36 if (wk.expired()) {
149 // Object expired. Remove the servant and throw.
150 objectExpired();
151 }
152 72 return wk.lock();
153 36 }
154
155 const Storage& getS() const { return wrappedObject_; }
156
157 /// Set to true if the servant should take ownership of this object.
158 20 void persistantStorage(bool persistant) {
159
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
20 if (persistant)
160 19 p_ = get();
161 else
162 1 p_.reset();
163 20 }
164
165 /// See persistantStorage(bool)
166 bool persistantStorage() const { return p_; }
167
168 void deleteThis() {
169 persistantStorage(false);
170
171 // Object expired. Try to remove the server.
172 PortableServer::Servant servant =
173 dynamic_cast<PortableServer::Servant>(this);
174 if (servant == NULL)
175 throw Error("The object was deleted. I could not delete the servant.");
176 this->server_->removeServant(servant);
177 // Deactivate object
178 PortableServer::ObjectId_var objectId =
179 this->server_->poa()->servant_to_id(servant);
180 this->server_->poa()->deactivate_object(objectId.in());
181 }
182
183 bool deleteIfExpired() {
184 if (expired()) {
185 deleteThis();
186 return true;
187 }
188 return false;
189 }
190
191 protected:
192 19 ServantBase(Server* server, const Storage& _s)
193 19 : AbstractServantBase<T>(server), wrappedObject_(_s) {
194
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
19 persistantStorage(true);
195 19 }
196
197 Storage wrappedObject_;
198
199 private:
200 void objectExpired() const {
201 // Object expired. Try to remove the server.
202 PortableServer::Servant servant =
203 dynamic_cast<PortableServer::Servant>(const_cast<ServantBase*>(this));
204 if (servant == NULL)
205 throw Error("The object was deleted. I could not delete the servant.");
206 this->server_->removeServant(servant);
207 // Deactivate object
208 PortableServer::ObjectId_var objectId =
209 this->server_->poa()->servant_to_id(servant);
210 this->server_->poa()->deactivate_object(objectId.in());
211 throw Error("The object has been deleted. I delete the servant.");
212 }
213
214 TShPtr_t p_;
215 };
216
217 /// Abstraction of storage ot HPP class.
218 ///
219 /// In most cases, it is sufficient to use shared_ptr<Class>. However,
220 /// there are some cases where you need more information in the
221 /// AbstractServantBase derived class. For instance, if you want to check the
222 /// inputs (which is recommended), you may need to store the robot. See
223 /// hpp::corbaServer::core_idl::Distance for an example.
224 ///
225 /// Child classed must implement
226 /// \code
227 /// template <typename T> DistanceStorage<T> cast () const
228 /// {
229 /// return DistanceStorage<T> (r, HPP_DYNAMIC_PTR_CAST(T, d));
230 /// }
231 /// \endcode
232 template <typename T, typename Base>
233 class AbstractStorage {
234 public:
235 typedef weak_ptr<T> ptr_t;
236
237 ptr_t element;
238
239 AbstractStorage(const ptr_t& _element) : element(_element) {}
240 operator shared_ptr<T>() const { return element.lock(); }
241 operator weak_ptr<T>() const { return element; }
242 long use_count() const { return element.use_count(); }
243
244 // Mimic shared_ptr<D> interface:
245 typedef T element_type;
246 operator bool() const { return use_count() > 0; }
247 };
248
249 typedef PortableServer::Servant_var<PortableServer::ServantBase>
250 ServantBase_var;
251
252 template <typename S, typename P>
253 PortableServer::Servant_var<S> reference_to_servant(Server* server,
254 const P& p) {
255 PortableServer::Servant s = server->poa()->reference_to_servant(p);
256 if (s == NULL) throw Error("The servant is not located here");
257 return dynamic_cast<S*>(s);
258 }
259
260 /// \tparam T the type of the servant object.
261 /// \tparam P the type of the object which is served.
262 template <typename T, typename P>
263 AbstractServantBase<T>* reference_to_servant_base(Server* server, const P& p) {
264 ServantBase_var s = server->poa()->reference_to_servant(p);
265 if (s.in() == NULL) throw Error("The servant is not located here");
266 return dynamic_cast<AbstractServantBase<T>*>(s.in());
267 }
268
269 /// Create and activate a omniORB servant.
270 ///
271 /// \tparam P An CORBA::Object_ptr (typically S::Object_ptr)
272 /// \tparam S A class deriving from AbstractServantKey and
273 /// PortableServer::ServantBase
274 /// (or a class generated by omniidl in the namespace POA_*).
275 /// \return a reference to the OmniORB servant.
276 /// \note if a OmniORB servant serving s exists, no servant is created and
277 /// a reference to the existing servant is returned.
278 template <typename P, typename S>
279 19 P makeServant(Server* server, S* s) {
280
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
19 Server::ServantKey servantKey = s->getServantKey();
281
3/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 9 times.
19 S* servant = dynamic_cast<S*>(server->getServant(servantKey));
282
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
19 if (servant != NULL) {
283
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 delete s;
284
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 return servant->_this();
285 }
286
287 15 PortableServer::Servant_var<S> d(s);
288 // ObjectId_var object is here to delete the servantId.
289
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
15 PortableServer::ObjectId_var servantId = server->poa()->activate_object(d);
290 (void)servantId;
291
292
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
15 server->addServantKeyAndServant(servantKey, d.in());
293
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
15 return d->_this();
294 15 }
295
296 /// \cond
297 namespace details {
298 /// Enabled only if StorageTpl != shared_ptr
299 template <typename U, typename V, template <typename> class StorageTpl>
300 struct storage_cast_impl {
301 static StorageTpl<U> run(const StorageTpl<V>& o) {
302 return o.template cast<U>();
303 }
304 };
305
306 /// Enabled only if StorageTpl == shared_ptr
307 template <typename U, typename V>
308 struct storage_cast_impl<U, V, shared_ptr> {
309 8 static shared_ptr<U> run(const shared_ptr<V>& o) {
310 8 return dynamic_pointer_cast<U>(o);
311 }
312 };
313
314 /// Enabled only if StorageTpl == weak_ptr
315 template <typename U, typename V>
316 struct storage_cast_impl<U, V, weak_ptr> {
317 35 static weak_ptr<U> run(const weak_ptr<V>& o) {
318 35 return dynamic_pointer_cast<U>(o.lock());
319 }
320 };
321 } // namespace details
322 /// \endcond
323
324 /// Cast the storage class of a servant.
325 template <typename U, typename V, template <typename> class StorageTpl>
326 46 static StorageTpl<U> storage_cast(const StorageTpl<V>& o) {
327 46 return details::storage_cast_impl<U, V, StorageTpl>::run(o);
328 }
329
330 /// \tparam T the desired HPP type
331 /// \tparam P the type of the object which is served.
332 template <typename T, typename P>
333 8 auto reference_to_object(Server* server, const P& p) {
334
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
8 ServantBase_var s = server->poa()->reference_to_servant(p);
335
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8 if (s.in() == NULL) throw Error("The servant is not located here");
336 typedef typename hpp_traits<T>::Base TBase;
337 8 AbstractServantBase<TBase>* asb =
338
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 dynamic_cast<AbstractServantBase<TBase>*>(s.in());
339
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if (asb == NULL) throw Error("Not an object of the correct type.");
340
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 auto ret = storage_cast<T>(asb->get());
341
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8 if (!ret) throw Error("Object is not of the correct type.");
342 16 return ret;
343 }
344
345 /// Class used to dynamiccally cast HPP classes and create the corresponding
346 /// servant.
347 /// \sa HPP_CORBASERVER_ADD_DOWNCAST_OBJECT
348 template <typename ServantBaseType>
349 class ServantFactoryBase {
350 public:
351 typedef typename ServantBaseType::Storage Storage;
352 typedef typename ServantBaseType::Object_var Object_var;
353
354 416 ServantFactoryBase(const size_type& depth) : depth_(depth) {}
355
356 virtual Object_var servant(Server* server, const Storage& obj) = 0;
357
358 /// Get the depth in the hierarchy tree.
359 /// This allows to ensure that child classes are always handled before
360 /// parent classes.
361 600 size_type depth() const { return depth_; }
362
363 private:
364 size_type depth_;
365 };
366
367 template <typename ServantBaseType, typename ServantType>
368 struct ServantFactory : ServantFactoryBase<ServantBaseType> {
369 typedef typename ServantBaseType::Object_var Object_var;
370 typedef typename ServantBaseType::Storage StorageBase;
371
372 528 ServantFactory(const size_type& depth)
373 528 : ServantFactoryBase<ServantBaseType>(depth) {}
374
375 35 virtual Object_var servant(Server* s, const StorageBase& o) {
376 typedef typename ServantType::Storage Storage;
377
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
35 Storage u = storage_cast<typename Storage::element_type>(o);
378
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
35 Object_var ret;
379
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 8 times.
35 if (u.use_count() > 0)
380
4/8
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
19 ret = makeServant<Object_var>(s, new ServantType(s, u));
381 70 return ret;
382 35 }
383 };
384
385 template <typename ServantBaseType>
386 std::vector<ServantFactoryBase<ServantBaseType>*>& objectDowncasts();
387
388 template <typename ServantBaseType>
389 392 void addDowncastObjects(ServantFactoryBase<ServantBaseType>* const object) {
390 typedef std::vector<ServantFactoryBase<ServantBaseType>*> vector_t;
391 typedef typename vector_t::iterator iterator;
392
393 392 vector_t& vec = objectDowncasts<ServantBaseType>();
394 392 size_type d = object->depth();
395
2/2
✓ Branch 4 taken 128 times.
✓ Branch 5 taken 120 times.
392 for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
396
1/2
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
184 if (d >= (*_obj)->depth()) {
397
1/2
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
184 vec.insert(_obj, object);
398 184 return;
399 }
400 }
401 208 vec.push_back(object);
402 }
403
404 /// Create and activate a omniORB servant with class downcasting.
405 /// \tparam ServantBaseType the top classes of the hierarchy.
406 template <typename ServantBaseType, typename ReturnType>
407 10 typename ReturnType::Object_var makeServantDownCast(
408 Server* server, const typename ServantBaseType::Storage& t) {
409 typedef typename ServantBaseType::Object_var BaseObject_var;
410 typedef typename ReturnType::Object_var Object_var;
411
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
10 BaseObject_var servant;
412
3/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
10 assert(CORBA::Object_Helper::is_nil(servant.in()));
413
414 typedef std::vector<ServantFactoryBase<ServantBaseType>*> vector_t;
415 typedef typename vector_t::iterator iterator;
416
417
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
10 vector_t& vec = objectDowncasts<ServantBaseType>();
418
2/2
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 1 times.
20 for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
419
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
18 servant = (*_obj)->servant(server, t);
420
4/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 5 times.
18 if (!CORBA::Object_Helper::is_nil(servant.in())) {
421 // Cast to child type.
422
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 return Object_var(ReturnType::Object::_narrow(servant._retn()));
423 }
424 }
425
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return Object_var();
426 }
427
428 template <typename ServantBaseType>
429 14 typename ServantBaseType::Object_var makeServantDownCast(
430 Server* server, const typename ServantBaseType::Storage& t) {
431 // TODO
432 // return makeServantDownCast <ServantBaseType, ServantBaseType> (server, t);
433 typedef typename ServantBaseType::Object_var Object_var;
434 14 Object_var servant;
435
3/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
14 assert(CORBA::Object_Helper::is_nil(servant.in()));
436
437 typedef std::vector<ServantFactoryBase<ServantBaseType>*> vector_t;
438 typedef typename vector_t::iterator iterator;
439
440
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
14 vector_t& vec = objectDowncasts<ServantBaseType>();
441
1/2
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
20 for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
442
2/4
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
20 servant = (*_obj)->servant(server, t);
443
4/6
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 3 times.
20 if (!CORBA::Object_Helper::is_nil(servant.in())) break;
444 }
445
446 14 return servant;
447 }
448
449 template <typename OutType, typename InnerBaseType,
450 typename InnerType = InnerBaseType>
451 struct vectorToSeqServant {
452 Server* wrappedObject_;
453
454 vectorToSeqServant(Server* _s) : wrappedObject_(_s) {}
455
456 template <typename InContainer>
457 inline OutType* operator()(const InContainer& input) {
458 std::size_t len = std::distance(input.begin(), input.end());
459 OutType* seq = new OutType();
460 seq->length((CORBA::ULong)len);
461
462 std::size_t i = 0;
463 typename InContainer::const_iterator it = input.begin();
464 while (it != input.end()) {
465 (*seq)[(CORBA::ULong)i] =
466 makeServantDownCast<InnerBaseType, InnerType>(wrappedObject_, *it)
467 ._retn();
468 ++it;
469 ++i;
470 }
471 return seq;
472 }
473 };
474
475 /// \}
476 } // end of namespace corbaServer.
477 } // end of namespace hpp.
478
479 /// Declare a new element of a HPP class hierachy.
480 /// \param depth the depth in the hierarchy tree.
481 /// Example:
482 /// \code
483 /// HPP_CORBASERVER_ADD_DOWNCAST_OBJECT(Path , Path, 0)
484 /// // PathVector directly inherits from Path
485 /// HPP_CORBASERVER_ADD_DOWNCAST_OBJECT(PathVector, Path, 1)
486 /// \endcode
487 #define HPP_CORBASERVER_ADD_DOWNCAST_OBJECT(ServantType, BaseServantType, \
488 depth) \
489 struct HPP_CORE_DLLAPI __InitializerClass_##ServantType{ \
490 __InitializerClass_##ServantType(){ \
491 ::hpp::corbaServer::addDowncastObjects<BaseServantType>( \
492 new ::hpp::corbaServer::ServantFactory<BaseServantType, \
493 ServantType>(depth)); \
494 } \
495 } \
496 ; \
497 HPP_CORBASERVER_DLLLOCAL __InitializerClass_##ServantType \
498 __instance_##ServantType;
499
500 #endif // HPP_CORBASERVER_SERVANT_BASE_HH
501