| Directory: | ./ |
|---|---|
| File: | include/hpp/corbaserver/servant-base.hh |
| Date: | 2025-05-11 11:10:19 |
| 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 |