hpp-corbaserver  6.0.0
Corba server for Humanoid Path Planner applications
servant-base.hh
Go to the documentation of this file.
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>
39 
40 namespace hpp {
41 namespace corbaServer {
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 
93  public:
94  virtual Server::ServantKey getServantKey() const = 0;
95 
96  virtual bool expired() const = 0;
97 };
98 
103 template <typename T>
105  public:
106  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  virtual Server::ServantKey getServantKey() const { return get().get(); }
114 
115  protected:
116  AbstractServantBase(Server* server) : server_(server) {}
117 
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  virtual ~ServantBase() {}
131 
132  virtual TShPtr_t get() const {
134  if (wk.expired()) {
135  // Object expired. Remove the servant and throw.
136  objectExpired();
137  }
138  return wk.lock();
139  }
140 
141  bool expired() const final {
143  return wk.expired();
144  }
145 
148  if (wk.expired()) {
149  // Object expired. Remove the servant and throw.
150  objectExpired();
151  }
152  return wk.lock();
153  }
154 
155  const Storage& getS() const { return wrappedObject_; }
156 
158  void persistantStorage(bool persistant) {
159  if (persistant)
160  p_ = get();
161  else
162  p_.reset();
163  }
164 
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 
184  if (expired()) {
185  deleteThis();
186  return true;
187  }
188  return false;
189  }
190 
191  protected:
192  ServantBase(Server* server, const Storage& _s)
193  : AbstractServantBase<T>(server), wrappedObject_(_s) {
194  persistantStorage(true);
195  }
196 
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 
232 template <typename T, typename Base>
234  public:
235  typedef weak_ptr<T> ptr_t;
236 
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>
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 
262 template <typename T, typename 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 
278 template <typename P, typename S>
279 P makeServant(Server* server, S* s) {
280  Server::ServantKey servantKey = s->getServantKey();
281  S* servant = dynamic_cast<S*>(server->getServant(servantKey));
282  if (servant != NULL) {
283  delete s;
284  return servant->_this();
285  }
286 
287  PortableServer::Servant_var<S> d(s);
288  // ObjectId_var object is here to delete the servantId.
289  PortableServer::ObjectId_var servantId = server->poa()->activate_object(d);
290  (void)servantId;
291 
292  server->addServantKeyAndServant(servantKey, d.in());
293  return d->_this();
294 }
295 
297 namespace details {
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 
307 template <typename U, typename V>
308 struct storage_cast_impl<U, V, shared_ptr> {
309  static shared_ptr<U> run(const shared_ptr<V>& o) {
310  return dynamic_pointer_cast<U>(o);
311  }
312 };
313 
315 template <typename U, typename V>
316 struct storage_cast_impl<U, V, weak_ptr> {
317  static weak_ptr<U> run(const weak_ptr<V>& o) {
318  return dynamic_pointer_cast<U>(o.lock());
319  }
320 };
321 } // namespace details
323 
325 template <typename U, typename V, template <typename> class StorageTpl>
326 static StorageTpl<U> storage_cast(const StorageTpl<V>& o) {
327  return details::storage_cast_impl<U, V, StorageTpl>::run(o);
328 }
329 
332 template <typename T, typename P>
333 auto reference_to_object(Server* server, const P& p) {
334  ServantBase_var s = server->poa()->reference_to_servant(p);
335  if (s.in() == NULL) throw Error("The servant is not located here");
336  typedef typename hpp_traits<T>::Base TBase;
338  dynamic_cast<AbstractServantBase<TBase>*>(s.in());
339  if (asb == NULL) throw Error("Not an object of the correct type.");
340  auto ret = storage_cast<T>(asb->get());
341  if (!ret) throw Error("Object is not of the correct type.");
342  return ret;
343 }
344 
348 template <typename ServantBaseType>
350  public:
351  typedef typename ServantBaseType::Storage Storage;
352  typedef typename ServantBaseType::Object_var Object_var;
353 
355 
356  virtual Object_var servant(Server* server, const Storage& obj) = 0;
357 
361  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 
373  : ServantFactoryBase<ServantBaseType>(depth) {}
374 
375  virtual Object_var servant(Server* s, const StorageBase& o) {
376  typedef typename ServantType::Storage Storage;
377  Storage u = storage_cast<typename Storage::element_type>(o);
378  Object_var ret;
379  if (u.use_count() > 0)
380  ret = makeServant<Object_var>(s, new ServantType(s, u));
381  return ret;
382  }
383 };
384 
385 template <typename ServantBaseType>
386 std::vector<ServantFactoryBase<ServantBaseType>*>& objectDowncasts();
387 
388 template <typename ServantBaseType>
390  typedef std::vector<ServantFactoryBase<ServantBaseType>*> vector_t;
391  typedef typename vector_t::iterator iterator;
392 
393  vector_t& vec = objectDowncasts<ServantBaseType>();
394  size_type d = object->depth();
395  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
396  if (d >= (*_obj)->depth()) {
397  vec.insert(_obj, object);
398  return;
399  }
400  }
401  vec.push_back(object);
402 }
403 
406 template <typename ServantBaseType, typename ReturnType>
407 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  BaseObject_var servant;
412  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  vector_t& vec = objectDowncasts<ServantBaseType>();
418  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
419  servant = (*_obj)->servant(server, t);
420  if (!CORBA::Object_Helper::is_nil(servant.in())) {
421  // Cast to child type.
422  return Object_var(ReturnType::Object::_narrow(servant._retn()));
423  }
424  }
425  return Object_var();
426 }
427 
428 template <typename ServantBaseType>
429 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  Object_var servant;
435  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  vector_t& vec = objectDowncasts<ServantBaseType>();
441  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
442  servant = (*_obj)->servant(server, t);
443  if (!CORBA::Object_Helper::is_nil(servant.in())) break;
444  }
445 
446  return servant;
447 }
448 
449 template <typename OutType, typename InnerBaseType,
450  typename InnerType = InnerBaseType>
453 
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 
476 } // end of namespace corbaServer.
477 } // end of namespace hpp.
478 
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  HPP_CORBASERVER_DLLLOCAL __InitializerClass_##ServantType \
497  __instance_##ServantType;
498 
499 #endif // HPP_CORBASERVER_SERVANT_BASE_HH
Definition: servant-base.hh:104
weak_ptr< T > TWkPtr_t
Definition: servant-base.hh:109
virtual ~AbstractServantBase()
Definition: servant-base.hh:106
shared_ptr< T > TShPtr_t
Definition: servant-base.hh:108
AbstractServantBase(Server *server)
Definition: servant-base.hh:116
Server * server_
Definition: servant-base.hh:118
virtual TShPtr_t get() const =0
virtual Server::ServantKey getServantKey() const
Definition: servant-base.hh:113
Abstract class used to avoid duplication of the servants.
Definition: servant-base.hh:92
virtual bool expired() const =0
virtual Server::ServantKey getServantKey() const =0
Definition: servant-base.hh:233
long use_count() const
Definition: servant-base.hh:242
weak_ptr< T > ptr_t
Definition: servant-base.hh:235
T element_type
Definition: servant-base.hh:245
ptr_t element
Definition: servant-base.hh:237
AbstractStorage(const ptr_t &_element)
Definition: servant-base.hh:239
Definition: servant-base.hh:122
void deleteThis()
Definition: servant-base.hh:168
bool persistantStorage() const
See persistantStorage(bool)
Definition: servant-base.hh:166
virtual ~ServantBase()
Definition: servant-base.hh:130
_Storage Storage
Definition: servant-base.hh:124
Storage wrappedObject_
Definition: servant-base.hh:197
bool deleteIfExpired()
Definition: servant-base.hh:183
ServantBase(Server *server, const Storage &_s)
Definition: servant-base.hh:192
weak_ptr< typename Storage::element_type > StorageElementWkPtr_t
Definition: servant-base.hh:127
shared_ptr< typename Storage::element_type > StorageElementShPtr_t
Definition: servant-base.hh:128
bool expired() const final
Definition: servant-base.hh:141
void persistantStorage(bool persistant)
Set to true if the servant should take ownership of this object.
Definition: servant-base.hh:158
StorageElementShPtr_t getT() const
Definition: servant-base.hh:146
const Storage & getS() const
Definition: servant-base.hh:155
virtual TShPtr_t get() const
Definition: servant-base.hh:132
Definition: servant-base.hh:349
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:352
size_type depth() const
Definition: servant-base.hh:361
ServantFactoryBase(const size_type &depth)
Definition: servant-base.hh:354
virtual Object_var servant(Server *server, const Storage &obj)=0
ServantBaseType::Storage Storage
Definition: servant-base.hh:351
Implementation of Hpp module Corba server.
Definition: server.hh:78
PortableServer::Servant getServant(ServantKey servantKey) const
void addServantKeyAndServant(ServantKey servantKey, PortableServer::Servant servant)
void removeServant(PortableServer::Servant servant)
PortableServer::POA_var poa()
Definition: server.hh:114
void * ServantKey
Definition: server.hh:161
Corba exception travelling through the Corba channel.
Definition: common.idl:27
ReturnType::Object_var makeServantDownCast(Server *server, const typename ServantBaseType::Storage &t)
Definition: servant-base.hh:407
P makeServant(Server *server, S *s)
Definition: servant-base.hh:279
void addDowncastObjects(ServantFactoryBase< ServantBaseType > *const object)
Definition: servant-base.hh:389
std::vector< ServantFactoryBase< ServantBaseType > * > & objectDowncasts()
PortableServer::Servant_var< PortableServer::ServantBase > ServantBase_var
Definition: servant-base.hh:250
AbstractServantBase< T > * reference_to_servant_base(Server *server, const P &p)
Definition: servant-base.hh:263
PortableServer::Servant_var< S > reference_to_servant(Server *server, const P &p)
Definition: servant-base.hh:253
auto reference_to_object(Server *server, const P &p)
Definition: servant-base.hh:333
pinocchio::vector_t vector_t
Definition: fwd.hh:108
pinocchio::size_type size_type
Definition: fwd.hh:111
Implement CORBA interface `‘Obstacle’'.
Definition: client.hh:46
_CORBA_MODULE hpp _CORBA_MODULE_BEG _CORBA_MODULE core_idl _CORBA_MODULE_BEG typedef ::CORBA::ULongLong size_t
Definition: paths-idl.hh:75
Definition: servant-base.hh:368
ServantBaseType::Storage StorageBase
Definition: servant-base.hh:370
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:369
ServantFactory(const size_type &depth)
Definition: servant-base.hh:372
virtual Object_var servant(Server *s, const StorageBase &o)
Definition: servant-base.hh:375
Definition: servant-base.hh:89
Definition: servant-base.hh:451
Server * wrappedObject_
Definition: servant-base.hh:452
vectorToSeqServant(Server *_s)
Definition: servant-base.hh:454
OutType * operator()(const InContainer &input)
Definition: servant-base.hh:457