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 |