hpp-corbaserver  4.10.1
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 <boost/type.hpp>
15 
16 # include <hpp/common-idl.hh>
17 # include <hpp/corbaserver/server.hh>
18 
19 namespace hpp
20 {
21  namespace corbaServer
22  {
53 
54 #define SERVANT_BASE_TYPEDEFS(idlObj, hppObj) \
55  protected: \
56  using ::hpp::corbaServer::AbstractServantBase<hppObj>::server_; \
57  public: \
58  typedef _Base Base; \
59  typedef _Storage Storage; \
60  typedef idlObj Object; \
61  typedef idlObj ## _ptr Object_ptr; \
62  typedef idlObj ## _var Object_var; \
63  typedef ::hpp::corbaServer::ServantBase<hppObj, _Storage> _ServantBase; \
64  using _ServantBase::get; \
65  using _ServantBase::getT; \
66  using _ServantBase::getS
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 boost::shared_ptr<T> TShPtr_t;
85  typedef boost::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 boost:: weak_ptr<typename Storage::element_type> StorageElementWkPtr_t;
107  typedef boost::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) s);
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) s);
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 s;
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), s(_s)
167  {
168  persistantStorage (true);
169  }
170 
171  Storage s;
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 boost::weak_ptr<T> ptr_t;
210 
211  ptr_t element;
212 
213  AbstractStorage (const ptr_t& _element) : element(_element) {}
214  operator boost::shared_ptr<T > () const { return element.lock(); }
215  operator boost::weak_ptr <T > () const { return element; }
216  long use_count() const { return element.use_count(); }
217 
218  // Mimic boost::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, boost::shared_ptr> {
281  static boost::shared_ptr<U> run (const boost::shared_ptr<V>& o) {
282  return boost::dynamic_pointer_cast<U>(o);
283  }
284  };
285 
287  template <typename U, typename V>
288  struct storage_cast_impl<U, V, boost::weak_ptr> {
289  static boost::weak_ptr<U> run (const boost::weak_ptr<V>& o) {
290  return boost::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 
306  template <typename ServantBaseType>
308  {
309  public:
310  typedef typename ServantBaseType::Storage Storage;
311  typedef typename ServantBaseType::Object_var Object_var;
312 
313  ServantFactoryBase (const size_type& depth) : depth_ (depth) {}
314 
315  virtual Object_var servant (Server* server, const Storage& obj) = 0;
316 
320  size_type depth () const
321  {
322  return depth_;
323  }
324  private:
325  size_type depth_;
326  };
327 
328  template <typename ServantBaseType, typename ServantType>
329  struct ServantFactory : ServantFactoryBase<ServantBaseType>
330  {
331  typedef typename ServantBaseType::Object_var Object_var;
332  typedef typename ServantBaseType::Storage StorageBase;
333 
334  ServantFactory (const size_type& depth) :
335  ServantFactoryBase<ServantBaseType> (depth) {}
336 
337  virtual Object_var servant (Server* s, const StorageBase& o)
338  {
339  typedef typename ServantType::Storage Storage;
340  Storage u = storage_cast<typename Storage::element_type>(o);
341  Object_var ret;
342  if (u.use_count()>0) ret = makeServant <Object_var> (s, new ServantType (s, u));
343  return ret;
344  }
345  };
346 
347  template <typename ServantBaseType>
348  std::vector< ServantFactoryBase<ServantBaseType>* >& objectDowncasts ();
349 
350  template <typename ServantBaseType>
352  {
353  typedef std::vector< ServantFactoryBase<ServantBaseType>* > vector_t;
354  typedef typename vector_t::iterator iterator;
355 
356  vector_t& vec = objectDowncasts<ServantBaseType>();
357  size_type d = object->depth();
358  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
359  if (d >= (*_obj)->depth()) {
360  vec.insert(_obj, object);
361  return;
362  }
363  }
364  vec.push_back(object);
365  }
366 
369  template <typename ServantBaseType, typename ReturnType>
370  typename ReturnType::Object_var makeServantDownCast (Server* server, const typename ServantBaseType::Storage& t)
371  {
372  typedef typename ServantBaseType::Object_var BaseObject_var;
373  typedef typename ReturnType::Object_var Object_var;
374  BaseObject_var servant;
375  assert (CORBA::Object_Helper::is_nil(servant.in()));
376 
377  typedef std::vector< ServantFactoryBase<ServantBaseType>* > vector_t;
378  typedef typename vector_t::iterator iterator;
379 
380  vector_t& vec = objectDowncasts<ServantBaseType>();
381  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
382  servant = (*_obj)->servant(server, t);
383  if (!CORBA::Object_Helper::is_nil(servant.in())) {
384  // Cast to child type.
385  return Object_var (ReturnType::Object::_narrow (servant._retn()));
386  }
387  }
388  return Object_var();
389  }
390 
391  template <typename ServantBaseType>
392  typename ServantBaseType::Object_var makeServantDownCast (Server* server, const typename ServantBaseType::Storage& t)
393  {
394  //TODO
395  //return makeServantDownCast <ServantBaseType, ServantBaseType> (server, t);
396  typedef typename ServantBaseType::Object_var Object_var;
397  Object_var servant;
398  assert (CORBA::Object_Helper::is_nil(servant.in()));
399 
400  typedef std::vector< ServantFactoryBase<ServantBaseType>* > vector_t;
401  typedef typename vector_t::iterator iterator;
402 
403  vector_t& vec = objectDowncasts<ServantBaseType>();
404  for (iterator _obj = vec.begin(); _obj != vec.end(); ++_obj) {
405  servant = (*_obj)->servant(server, t);
406  if (!CORBA::Object_Helper::is_nil(servant.in())) break;
407  }
408 
409  return servant;
410  }
411 
412  template <typename OutType, typename InnerBaseType, typename InnerType = InnerBaseType>
414  {
416 
417  vectorToSeqServant (Server* _s) : s (_s) {}
418 
419  template <typename InContainer>
420  inline OutType* operator() (const InContainer& input)
421  {
422  std::size_t len = std::distance (input.begin(), input.end());
423  OutType* seq = new OutType ();
424  seq->length ((CORBA::ULong) len);
425 
426  std::size_t i = 0;
427  typename InContainer::const_iterator it = input.begin();
428  while (it != input.end()) {
429  (*seq)[(CORBA::ULong)i] = makeServantDownCast<InnerBaseType,
430  InnerType> (s, *it)._retn();
431  ++it;
432  ++i;
433  }
434  return seq;
435  }
436  };
437 
439  } // end of namespace corbaServer.
440 } // end of namespace hpp.
441 
450 #define HPP_CORBASERVER_ADD_DOWNCAST_OBJECT(ServantType, BaseServantType, depth) \
451  struct HPP_CORE_DLLAPI __InitializerClass_##ServantType { \
452  __InitializerClass_##ServantType () { \
453  ::hpp::corbaServer::addDowncastObjects<BaseServantType> \
454  ( new ::hpp::corbaServer::ServantFactory<BaseServantType, ServantType> (depth)); \
455  } \
456  }; \
457  HPP_CORBASERVER_DLLLOCAL __InitializerClass_##ServantType __instance_##ServantType;
458 
459 #endif // HPP_CORBASERVER_SERVANT_BASE_HH
Definition: servant-base.hh:100
PortableServer::Servant_var< PortableServer::ServantBase > ServantBase_var
Definition: servant-base.hh:223
boost::shared_ptr< T > TShPtr_t
Definition: servant-base.hh:84
std::vector< ServantFactoryBase< ServantBaseType > *> & objectDowncasts()
ServantFactory(const size_type &depth)
Definition: servant-base.hh:334
boost::shared_ptr< typename Storage::element_type > StorageElementShPtr_t
Definition: servant-base.hh:107
Definition: servant-base.hh:329
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:311
Implement CORBA interface ``Obstacle&#39;&#39;.
Definition: basic-server.hh:27
AbstractServantBase(Server *server)
Definition: servant-base.hh:95
AbstractServantBase< T > * reference_to_servant_base(Server *server, const P &p)
Definition: servant-base.hh:234
boost::weak_ptr< T > ptr_t
Definition: servant-base.hh:209
T element_type
Definition: servant-base.hh:219
ptr_t element
Definition: servant-base.hh:211
size_type depth() const
Definition: servant-base.hh:320
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
void addServantKeyAndServant(ServantKey servantKey, PortableServer::Servant servant)
boost::weak_ptr< typename Storage::element_type > StorageElementWkPtr_t
Definition: servant-base.hh:106
Server * server_
Definition: servant-base.hh:97
Corba exception travelling through the Corba channel.
Definition: common.idl:24
Definition: servant-base.hh:206
bool persistantStorage() const
See persistantStorage(bool)
Definition: servant-base.hh:144
Definition: servant-base.hh:307
void addDowncastObjects(ServantFactoryBase< ServantBaseType > *const object)
Definition: servant-base.hh:351
virtual Server::ServantKey getServantKey() const =0
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:370
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
Storage s
Definition: servant-base.hh:171
AbstractStorage(const ptr_t &_element)
Definition: servant-base.hh:213
ServantBaseType::Object_var Object_var
Definition: servant-base.hh:331
virtual ~ServantBase()
Definition: servant-base.hh:109
vectorToSeqServant(Server *_s)
Definition: servant-base.hh:417
Definition: servant-base.hh:413
virtual Object_var servant(Server *s, const StorageBase &o)
Definition: servant-base.hh:337
ServantBaseType::Storage StorageBase
Definition: servant-base.hh:332
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
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
boost::weak_ptr< T > TWkPtr_t
Definition: servant-base.hh:85
_Storage Storage
Definition: servant-base.hh:103
Server * s
Definition: servant-base.hh:415
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
ServantBaseType::Storage Storage
Definition: servant-base.hh:310
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:313