hpp-corbaserver  4.11.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 // This file is part of the hpp-corbaserver.
4 //
5 // This software is provided "as is" without warranty of any kind,
6 // either expressed or implied, including but not limited to the
7 // implied warranties of fitness for a particular purpose.
8 //
9 // See the COPYING file for more information.
10 
11 #ifndef HPP_CORBASERVER_SERVANT_BASE_HH
12 # define HPP_CORBASERVER_SERVANT_BASE_HH
13 
14 # include <hpp/common-idl.hh>
15 # include <hpp/corbaserver/server.hh>
16 
17 namespace hpp
18 {
19  namespace corbaServer
20  {
51 
52 #define SERVANT_BASE_TYPEDEFS(idlObj, hppObj) \
53  protected: \
54  using ::hpp::corbaServer::AbstractServantBase<hppObj>::server_; \
55  public: \
56  typedef _Base Base; \
57  typedef _Storage Storage; \
58  typedef idlObj Object; \
59  typedef idlObj ## _ptr Object_ptr; \
60  typedef idlObj ## _var Object_var; \
61  typedef ::hpp::corbaServer::ServantBase<hppObj, _Storage> _ServantBase; \
62  using _ServantBase::get; \
63  using _ServantBase::getT; \
64  using _ServantBase::getS
65 
66  template <typename T> struct hpp_traits {};
67 
70  {
71  public:
72  virtual Server::ServantKey getServantKey () const = 0;
73  };
74 
79  template <typename T> class AbstractServantBase : AbstractServantKey
80  {
81  public:
82  virtual ~AbstractServantBase () {}
83 
84  typedef shared_ptr<T> TShPtr_t;
85  typedef weak_ptr <T> TWkPtr_t;
86 
87  virtual TShPtr_t get() const = 0;
88 
90  {
91  return get().get();
92  }
93 
94  protected:
95  AbstractServantBase (Server* server) : server_ (server) {}
96 
98  };
99 
100  template <typename T, typename _Storage> class ServantBase : public AbstractServantBase<T>
101  {
102  public:
103  typedef _Storage Storage;
104  using typename AbstractServantBase<T>::TShPtr_t;
105  using typename AbstractServantBase<T>::TWkPtr_t;
106  typedef weak_ptr<typename Storage::element_type> StorageElementWkPtr_t;
107  typedef shared_ptr<typename Storage::element_type> StorageElementShPtr_t;
108 
109  virtual ~ServantBase () {}
110 
111  virtual TShPtr_t get () const
112  {
113  TWkPtr_t wk ((StorageElementWkPtr_t) wrappedObject_);
114  if (wk.expired()) {
115  // Object expired. Remove the servant and throw.
116  objectExpired();
117  }
118  return wk.lock();
119  }
120 
121  StorageElementShPtr_t getT () const
122  {
123  StorageElementWkPtr_t wk ((StorageElementWkPtr_t) wrappedObject_);
124  if (wk.expired()) {
125  // Object expired. Remove the servant and throw.
126  objectExpired();
127  }
128  return wk.lock();
129  }
130 
131  const Storage& getS () const
132  {
133  return wrappedObject_;
134  }
135 
137  void persistantStorage (bool persistant)
138  {
139  if (persistant) p_ = get();
140  else p_.reset();
141  }
142 
144  bool persistantStorage () const
145  {
146  return p_;
147  }
148 
149  void deleteThis ()
150  {
151  persistantStorage(false);
152 
153  // Object expired. Try to remove the server.
154  PortableServer::Servant servant = dynamic_cast<PortableServer::Servant>(this);
155  if (servant == NULL)
156  throw Error ("The object was deleted. I could not delete the servant.");
157  this->server_->removeServant (servant);
158  // Deactivate object
159  PortableServer::ObjectId_var objectId
160  = this->server_->poa()->servant_to_id(servant);
161  this->server_->poa()->deactivate_object(objectId.in());
162  }
163 
164  protected:
165  ServantBase (Server* server, const Storage& _s)
166  : AbstractServantBase<T> (server), wrappedObject_(_s)
167  {
168  persistantStorage (true);
169  }
170 
171  Storage wrappedObject_;
172 
173  private:
174  void objectExpired () const
175  {
176  // Object expired. Try to remove the server.
177  PortableServer::Servant servant = dynamic_cast<PortableServer::Servant>(const_cast<ServantBase*>(this));
178  if (servant == NULL)
179  throw Error ("The object was deleted. I could not delete the servant.");
180  this->server_->removeServant (servant);
181  // Deactivate object
182  PortableServer::ObjectId_var objectId
183  = this->server_->poa()->servant_to_id(servant);
184  this->server_->poa()->deactivate_object(objectId.in());
185  throw Error ("The object has been deleted. I delete the servant.");
186  }
187 
188  TShPtr_t p_;
189  };
190 
206  template <typename T, typename Base> class AbstractStorage
207  {
208  public:
209  typedef weak_ptr<T> ptr_t;
210 
211  ptr_t element;
212 
213  AbstractStorage (const ptr_t& _element) : element(_element) {}
214  operator shared_ptr<T > () const { return element.lock(); }
215  operator weak_ptr <T > () const { return element; }
216  long use_count() const { return element.use_count(); }
217 
218  // Mimic shared_ptr<D> interface:
219  typedef T element_type;
220  operator bool () const { return use_count()>0; }
221  };
222 
223  typedef PortableServer::Servant_var<PortableServer::ServantBase> ServantBase_var;
224 
225  template <typename S, typename P> PortableServer::Servant_var<S> reference_to_servant (Server* server, const P& p)
226  {
227  PortableServer::Servant s = server->poa()->reference_to_servant(p);
228  if (s == NULL) throw Error ("The servant is not located here");
229  return dynamic_cast<S*> (s);
230  }
231 
234  template <typename T, typename P> AbstractServantBase<T>* reference_to_servant_base (Server* server, const P& p)
235  {
236  ServantBase_var s = server->poa()->reference_to_servant(p);
237  if (s.in() == NULL) throw Error ("The servant is not located here");
238  return dynamic_cast<AbstractServantBase<T>*> (s.in());
239  }
240 
249  template <typename P, typename S> P makeServant (Server* server, S* s)
250  {
251  Server::ServantKey servantKey = s->getServantKey();
252  S* servant = dynamic_cast<S*> (server->getServant (servantKey));
253  if (servant != NULL) {
254  delete s;
255  return servant->_this();
256  }
257 
258  PortableServer::Servant_var<S> d (s);
259  // ObjectId_var object is here to delete the servantId.
260  PortableServer::ObjectId_var servantId = server->poa()->activate_object(d);
261  (void) servantId;
262 
263  server->addServantKeyAndServant (servantKey, d.in());
264  return d->_this();
265  }
266 
268  namespace details
269  {
271  template <typename U, typename V, template<typename> class StorageTpl>
272  struct storage_cast_impl {
273  static StorageTpl<U> run (const StorageTpl<V>& o) {
274  return o.template cast<U>();
275  }
276  };
277 
279  template <typename U, typename V>
280  struct storage_cast_impl<U, V, shared_ptr> {
281  static shared_ptr<U> run (const shared_ptr<V>& o) {
282  return dynamic_pointer_cast<U>(o);
283  }
284  };
285 
287  template <typename U, typename V>
288  struct storage_cast_impl<U, V, weak_ptr> {
289  static weak_ptr<U> run (const weak_ptr<V>& o) {
290  return dynamic_pointer_cast<U>(o.lock());
291  }
292  };
293  }
295 
297  template <typename U, typename V, template<typename> class StorageTpl>
298  static StorageTpl<U> storage_cast(const StorageTpl<V>& o)
299  {
300  return details::storage_cast_impl<U, V, StorageTpl>::run (o);
301  }
302 
305  template <typename T, typename P> auto reference_to_object (Server* server, const P& p)
306  {
307  ServantBase_var s = server->poa()->reference_to_servant(p);
308  if (s.in() == NULL) throw Error ("The servant is not located here");
309  typedef typename hpp_traits<T>::Base TBase;
310  AbstractServantBase<TBase>* asb = dynamic_cast<AbstractServantBase<TBase>*>(s.in());
311  if (asb == NULL) throw Error ("Not an object of the correct type.");
312  auto ret = storage_cast<T>(asb->get());
313  if (!ret) throw Error("Object is not of the correct type.");
314  return ret;
315  }
316 
320  template <typename ServantBaseType>
322  {
323  public:
324  typedef typename ServantBaseType::Storage Storage;
325  typedef typename ServantBaseType::Object_var Object_var;
326 
327  ServantFactoryBase (const size_type& depth) : depth_ (depth) {}
328 
329  virtual Object_var servant (Server* server, const Storage& obj) = 0;
330 
334  size_type depth () const
335  {
336  return depth_;
337  }
338  private:
339  size_type depth_;
340  };
341 
342  template <typename ServantBaseType, typename ServantType>
343  struct ServantFactory : ServantFactoryBase<ServantBaseType>
344  {
345  typedef typename ServantBaseType::Object_var Object_var;
346  typedef typename ServantBaseType::Storage StorageBase;
347 
348  ServantFactory (const size_type& depth) :
349  ServantFactoryBase<ServantBaseType> (depth) {}
350 
351  virtual Object_var servant (Server* s, const StorageBase& o)
352  {
353  typedef typename ServantType::Storage Storage;
354  Storage u = storage_cast<typename Storage::element_type>(o);
355  Object_var ret;
356  if (u.use_count()>0) ret = makeServant <Object_var> (s, new ServantType (s, u));
357  return ret;
358  }
359  };
360 
361  template <typename ServantBaseType>
362  std::vector< ServantFactoryBase<ServantBaseType>* >& objectDowncasts ();
363 
364  template <typename ServantBaseType>
366  {
367  typedef std::vector< ServantFactoryBase<ServantBaseType>* > vector_t;
368  typedef typename vector_t::iterator iterator;
369 
370  vector_t& vec = objectDowncasts<ServantBaseType>();
371  size_type d = object->depth();
372  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
373  if (d >= (*_obj)->depth()) {
374  vec.insert(_obj, object);
375  return;
376  }
377  }
378  vec.push_back(object);
379  }
380 
383  template <typename ServantBaseType, typename ReturnType>
384  typename ReturnType::Object_var makeServantDownCast (Server* server, const typename ServantBaseType::Storage& t)
385  {
386  typedef typename ServantBaseType::Object_var BaseObject_var;
387  typedef typename ReturnType::Object_var Object_var;
388  BaseObject_var servant;
389  assert (CORBA::Object_Helper::is_nil(servant.in()));
390 
391  typedef std::vector< ServantFactoryBase<ServantBaseType>* > vector_t;
392  typedef typename vector_t::iterator iterator;
393 
394  vector_t& vec = objectDowncasts<ServantBaseType>();
395  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
396  servant = (*_obj)->servant(server, t);
397  if (!CORBA::Object_Helper::is_nil(servant.in())) {
398  // Cast to child type.
399  return Object_var (ReturnType::Object::_narrow (servant._retn()));
400  }
401  }
402  return Object_var();
403  }
404 
405  template <typename ServantBaseType>
406  typename ServantBaseType::Object_var makeServantDownCast (Server* server, const typename ServantBaseType::Storage& t)
407  {
408  //TODO
409  //return makeServantDownCast <ServantBaseType, ServantBaseType> (server, t);
410  typedef typename ServantBaseType::Object_var Object_var;
411  Object_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())) break;
421  }
422 
423  return servant;
424  }
425 
426  template <typename OutType, typename InnerBaseType, typename InnerType = InnerBaseType>
428  {
430 
431  vectorToSeqServant (Server* _s) : wrappedObject_ (_s) {}
432 
433  template <typename InContainer>
434  inline OutType* operator() (const InContainer& input)
435  {
436  std::size_t len = std::distance (input.begin(), input.end());
437  OutType* seq = new OutType ();
438  seq->length ((CORBA::ULong) len);
439 
440  std::size_t i = 0;
441  typename InContainer::const_iterator it = input.begin();
442  while (it != input.end()) {
443  (*seq)[(CORBA::ULong)i] = makeServantDownCast<InnerBaseType,
444  InnerType> (wrappedObject_, *it)._retn();
445  ++it;
446  ++i;
447  }
448  return seq;
449  }
450  };
451 
453  } // end of namespace corbaServer.
454 } // end of namespace hpp.
455 
464 #define HPP_CORBASERVER_ADD_DOWNCAST_OBJECT(ServantType, BaseServantType, depth) \
465  struct HPP_CORE_DLLAPI __InitializerClass_##ServantType { \
466  __InitializerClass_##ServantType () { \
467  ::hpp::corbaServer::addDowncastObjects<BaseServantType> \
468  ( new ::hpp::corbaServer::ServantFactory<BaseServantType, ServantType> (depth)); \
469  } \
470  }; \
471  HPP_CORBASERVER_DLLLOCAL __InitializerClass_##ServantType __instance_##ServantType;
472 
473 #endif // HPP_CORBASERVER_SERVANT_BASE_HH
Definition: servant-base.hh:100
auto reference_to_object(Server *server, const P &p)
Definition: servant-base.hh:305
PortableServer::Servant_var< PortableServer::ServantBase > ServantBase_var
Definition: servant-base.hh:223
std::vector< ServantFactoryBase< ServantBaseType > *> & objectDowncasts()
ServantFactory(const size_type &depth)
Definition: servant-base.hh:348
Definition: servant-base.hh:343
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:325
Implement CORBA interface ``Obstacle&#39;&#39;.
Definition: basic-server.hh:27
AbstractServantBase(Server *server)
Definition: servant-base.hh:95
weak_ptr< typename Storage::element_type > StorageElementWkPtr_t
Definition: servant-base.hh:106
AbstractServantBase< T > * reference_to_servant_base(Server *server, const P &p)
Definition: servant-base.hh:234
T element_type
Definition: servant-base.hh:219
ptr_t element
Definition: servant-base.hh:211
size_type depth() const
Definition: servant-base.hh:334
Abstract class used to avoid duplication of the servants.
Definition: servant-base.hh:69
PortableServer::Servant_var< S > reference_to_servant(Server *server, const P &p)
Definition: servant-base.hh:225
virtual TShPtr_t get() const =0
void addServantKeyAndServant(ServantKey servantKey, PortableServer::Servant servant)
Server * server_
Definition: servant-base.hh:97
Corba exception travelling through the Corba channel.
Definition: common.idl:25
Storage wrappedObject_
Definition: servant-base.hh:171
Definition: servant-base.hh:206
bool persistantStorage() const
See persistantStorage(bool)
Definition: servant-base.hh:144
Definition: servant-base.hh:321
void addDowncastObjects(ServantFactoryBase< ServantBaseType > *const object)
Definition: servant-base.hh:365
pinocchio::vector_t vector_t
Definition: fwd.hh:89
const Storage & getS() const
Definition: servant-base.hh:131
ReturnType::Object_var makeServantDownCast(Server *server, const typename ServantBaseType::Storage &t)
Definition: servant-base.hh:384
PortableServer::POA_var poa()
Definition: server.hh:88
ServantBase(Server *server, const Storage &_s)
Definition: servant-base.hh:165
P makeServant(Server *server, S *s)
Definition: servant-base.hh:249
Server * wrappedObject_
Definition: servant-base.hh:429
AbstractStorage(const ptr_t &_element)
Definition: servant-base.hh:213
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:345
virtual ~ServantBase()
Definition: servant-base.hh:109
vectorToSeqServant(Server *_s)
Definition: servant-base.hh:431
Definition: servant-base.hh:427
virtual Object_var servant(Server *s, const StorageBase &o)
Definition: servant-base.hh:351
weak_ptr< T > ptr_t
Definition: servant-base.hh:209
ServantBaseType::Storage StorageBase
Definition: servant-base.hh:346
Implementation of Hpp module Corba server.
Definition: server.hh:54
virtual Server::ServantKey getServantKey() const
Definition: servant-base.hh:89
PortableServer::Servant getServant(ServantKey servantKey) const
shared_ptr< typename Storage::element_type > StorageElementShPtr_t
Definition: servant-base.hh:107
Definition: servant-base.hh:79
void persistantStorage(bool persistant)
Set to true if the servant should take ownership of this object.
Definition: servant-base.hh:137
void * ServantKey
Definition: server.hh:146
Definition: servant-base.hh:66
shared_ptr< T > TShPtr_t
Definition: servant-base.hh:84
_Storage Storage
Definition: servant-base.hh:103
StorageElementShPtr_t getT() const
Definition: servant-base.hh:121
_CORBA_MODULE hpp _CORBA_MODULE_BEG _CORBA_MODULE core_idl _CORBA_MODULE_BEG typedef ::CORBA::ULongLong size_t
Definition: paths-idl.hh:75
void deleteThis()
Definition: servant-base.hh:149
weak_ptr< T > TWkPtr_t
Definition: servant-base.hh:85
ServantBaseType::Storage Storage
Definition: servant-base.hh:324
long use_count() const
Definition: servant-base.hh:216
pinocchio::size_type size_type
Definition: fwd.hh:92
virtual ~AbstractServantBase()
Definition: servant-base.hh:82
ServantFactoryBase(const size_type &depth)
Definition: servant-base.hh:327