libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objecttypebuilder.hxx
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
8 #define _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
9 
10 #include <boost/function_types/is_member_function_pointer.hpp>
11 #include <boost/mpl/front.hpp>
13 #include <qi/type/metamethod.hpp>
14 #include <qi/actor.hpp>
15 
16 namespace qi {
17 
18  namespace detail {
19  template <typename T>
20  qi::Strand* callWithVoid(qi::Strand* (T::*member)() const, void* instance)
21  {
22  return (static_cast<T*>(instance)->*member)();
23  }
24 
25  template <typename T>
26  typename boost::enable_if<boost::is_base_of<Actor, T>, AnyFunction>::type
28  {
29  return AnyFunction::from(boost::function<qi::Strand*(void*)>(
30  boost::bind(&callWithVoid<T>, &T::strand, _1)));
31  }
32  template <typename T>
33  typename boost::disable_if<boost::is_base_of<Actor, T>, AnyFunction>::type
35  {
36  return AnyFunction();
37  }
38  }
39 
40  template<typename T> void ObjectTypeBuilderBase::buildFor(bool autoRegister)
41  {
42  // We are erasing T here: we must pass everything the builder need to know about t:
43  // - typeid
44  // - cloner/deleter
45  // - serializer, ...
46  // => wee need all TypeInterface* methods, but we do not want another TypeInterface*
47  // to anwser to typeOf<T>
48  xBuildFor(new DefaultTypeImpl<T>(), autoRegister, detail::getStrandAccessor<T>());
49 
50  if (std::is_base_of<Actor, T>::value)
52  else
54  }
55 
56  template <typename FUNCTION_TYPE>
57  unsigned int ObjectTypeBuilderBase::advertiseMethod(const std::string& name,
58  FUNCTION_TYPE function,
59  MetaCallType threadingModel,
60  int id)
61  {
62  MetaMethodBuilder builder;
63  AnyFunction f = AnyFunction::from(function);
64  builder.setName(name);
65  builder.setSignature(f);
66 
67  // throw on error
68  return xAdvertiseMethod(builder, f, threadingModel, id);
69  }
70 
71  template <typename FUNCTION_TYPE>
73  FUNCTION_TYPE function,
74  MetaCallType threadingModel,
75  int id)
76  {
77  AnyFunction f = AnyFunction::from(function);
78  builder.setSignature(f);
79 
80  // throw on error
81  return xAdvertiseMethod(builder, f, threadingModel, id);
82  }
83 
84  template<typename U>
85  void ObjectTypeBuilderBase::inherits(std::ptrdiff_t offset)
86  {
87  return inherits(typeOf<
88  typename boost::remove_reference<U>::type>(), offset);
89  }
90 
91  template<typename T>
92  template<typename U>
94  {
95  qiLogCategory("qitype.objectbuilder");
96  // Compute the offset between T and U
97  T* ptr = reinterpret_cast<T*>(0x10000);
98  U* pptr = ptr;
99  std::ptrdiff_t offset = reinterpret_cast<intptr_t>(pptr) - reinterpret_cast<intptr_t>(ptr);
100  qiLogDebug() << "Offset check T(" << qi::typeIdRuntime(ptr).name() << ")= " << ptr
101  << ", U(" << qi::typeIdRuntime(pptr).name() << ")= " << pptr << ", T-U= " << offset;
102  return ObjectTypeBuilderBase::inherits<U>(offset);
103  }
104 
105  namespace detail
106  {
107  template<typename F, typename T> void checkRegisterParent(
108  ObjectTypeBuilder<T>& , boost::false_type) {}
109  template<typename F, typename T> void checkRegisterParent(
110  ObjectTypeBuilder<T>& builder, boost::true_type)
111  {
112  using ArgsType = typename boost::function_types::parameter_types<F>::type;
113  using DecoratedClassType = typename boost::mpl::front<ArgsType>::type;
114  using ClassType = typename boost::remove_reference<DecoratedClassType>::type;
115  builder.template inherits<ClassType>();
116  }
117  };
118 
119  template <typename T>
120  template <typename FUNCTION_TYPE>
121  unsigned int ObjectTypeBuilder<T>::advertiseMethod(const std::string& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
122  {
123  // Intercept advertise to auto-register parent type if this is a parent method
124  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
125  // as a child
126  detail::checkRegisterParent<FUNCTION_TYPE>(
127  *this,
128  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
129 
130  // throw on error
131  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
132  }
133 
134  template <typename T>
135  template <typename FUNCTION_TYPE>
136  unsigned int ObjectTypeBuilder<T>::advertiseMethod(MetaMethodBuilder& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
137  {
138  // Intercept advertise to auto-register parent type if this is a parent method
139  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
140  // as a child
141  detail::checkRegisterParent<FUNCTION_TYPE>(
142  *this,
143  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
144 
145  // throw on error
146  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
147  }
148 
149  template <typename T>
150  AnyObject ObjectTypeBuilder<T>::object(T* ptr, boost::function<void (GenericObject*)> onDestroy)
151  {
152  return ObjectTypeBuilderBase::object(static_cast<void*>(ptr), onDestroy);
153  }
154 
155 
156  template<typename T>
158  {
159  ::qi::registerType(qi::typeId<T>(), type());
160  }
161 
162  template<typename A>
163  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, SignalBase*>::type
164  signalAccess(A acc, void* instance)
165  {
166  using class_type = typename detail::Accessor<A>::class_type;
167  return &detail::Accessor<A>::access((class_type*)instance, acc);
168  }
169 
170  template<typename A>
171  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, PropertyBase*>::type
172  propertyAccess(A acc, void* instance)
173  {
174  using class_type = typename detail::Accessor<A>::class_type;
175  return &detail::Accessor<A>::access((class_type*)instance, acc);
176  }
177 
178  template<typename A>
179  unsigned int
180  ObjectTypeBuilderBase::advertiseSignal(const std::string& eventName, A accessor, int id, bool isSignalProperty)
181  {
182  SignalMemberGetter fun = boost::bind(&signalAccess<A>, accessor, _1);
183  using FunctionType = typename detail::Accessor<A>::value_type::FunctionType;
184  return xAdvertiseSignal(eventName,
185  detail::FunctionSignature<FunctionType>::signature(), fun, id, isSignalProperty);
186  }
187 
188  template <typename A>
189  unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& name, A accessor)
190  {
191  unsigned int id = advertiseSignal(name, accessor, -1, true);
192  PropertyMemberGetter pg = boost::bind(&propertyAccess<A>, accessor, _1);
193  using PropertyType = typename detail::Accessor<A>::value_type::PropertyType;
194  return xAdvertiseProperty(name, typeOf<PropertyType>()->signature(), pg, id);
195  }
196 
197  template <typename T> unsigned int ObjectTypeBuilderBase::advertiseSignal(const std::string& name, SignalMemberGetter getter, int id, bool isSignalProperty)
198  {
199  return xAdvertiseSignal(name, detail::FunctionSignature<T>::signature(), getter, id, isSignalProperty);
200  }
201 
202  template<typename T>
203  inline unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& eventName, PropertyMemberGetter getter)
204  {
205  return xAdvertiseProperty(eventName, typeOf<T>()->signature(), getter);
206  }
207 
208 
209  namespace detail
210  {
211  static const char* interfaceMarker = "_interface_";
212  static const auto interfaceMarkerLength = strlen(interfaceMarker);
213 
214  // Trait that detect inheritance from PropertyBase SignalBase or none of the above.
215 
216  template<typename T, bool b> struct SigPropInheritsSignal
217  {};
218  template<typename T, bool b> struct SigPropInheritsProperty
219  {};
220 
221  template<typename T> struct SigProp : public
222  SigPropInheritsProperty<T, boost::is_base_of<PropertyBase, T>::value> {};
223 
224  template<typename T> struct SigPropInheritsProperty<T, true>
225  {
226  static const unsigned value = 2;
227  };
228  template<typename T> struct SigPropInheritsProperty<T, false>
229  : public SigPropInheritsSignal<T, boost::is_base_of<SignalBase, T>::value> {};
230 
231  template<typename T> struct SigPropInheritsSignal<T, true>
232  {
233  static const unsigned value = 1;
234  };
235  template<typename T> struct SigPropInheritsSignal<T, false>
236  {
237  static const unsigned value = 0;
238  };
239 
240  template<unsigned> struct Dummy {};
241  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<0>)
242  {
243  return builder->advertiseMethod(name, accessor);
244  }
245  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<1>)
246  {
247  std::string n = name;
248  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
249  n = name.substr(interfaceMarkerLength);
250  return builder->advertiseSignal(n, accessor);
251  }
252  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<2>)
253  {
254  std::string n = name;
255  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
256  n = name.substr(interfaceMarkerLength);
257  return builder->advertiseProperty(n, accessor);
258  }
259  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::true_type)
260  {
261  return advertise(builder, name, accessor,
262  Dummy<detail::SigProp<typename detail::Accessor<A>::value_type>::value>());
263  }
264  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::false_type)
265  {
266  return builder->advertiseMethod(name, accessor);
267  }
268  }
269  template<typename T>
270  unsigned int
271  ObjectTypeBuilderBase::advertiseId(const std::string& name, T element)
272  {
273  return detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
274  }
275  template<typename T>
277  ObjectTypeBuilderBase::advertise(const std::string& name, T element)
278  {
279  detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
280  return *this;
281  }
282 
283 }
284 
285 
286 #endif // _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
unsigned int xAdvertiseProperty(const std::string &name, const qi::Signature &signature, PropertyMemberGetter getter, int id=-1)
void buildFor(bool autoRegister=true)
Declare the class type for which this StaticBuilder is.
qi::Strand * callWithVoid(qi::Strand *(T::*member)() const, void *instance)
bool registerType(const TypeIndex &typeId, TypeInterface *type)
Runtime Type factory setter.
#define qiLogCategory(Cat)
Definition: log.hpp:53
void xBuildFor(TypeInterface *type, bool autoRegister, qi::AnyFunction strandAccessor)
#define qiLogDebug(...)
Definition: log.hpp:76
boost::function< SignalBase *(void *)> SignalMemberGetter
AnyObject object(T *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
virtual void registerType()
Register type to typeOf<T>, to avoid both TypeImpl<T> and type() being present.
ObjectTypeBuilderBase & advertise(const std::string &name, T element)
unsigned int advertiseId(const std::string &name, T element)
Object is thread safe, multiple calls can occur in different threads in parallel. ...
Definition: manageable.hpp:38
void setName(const std::string &name)
AnyObject object(void *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
TypeIndex typeIdRuntime(const T &val)
void checkRegisterParent(ObjectTypeBuilder< T > &, boost::false_type)
boost::function< PropertyBase *(void *)> PropertyMemberGetter
void inherits(std::ptrdiff_t offset)
unsigned int advertiseSignal(const std::string &eventName, A accessor, int id=-1, bool isSignalProperty=false)
MetaCallType
Definition: typeobject.hpp:24
void setThreadingModel(ObjectThreadingModel model)
TypeInterface * typeOf()
Definition: type.hxx:94
boost::enable_if< typename detail::Accessor< A >::is_accessor, SignalBase * >::type signalAccess(A acc, void *instance)
unsigned int xAdvertiseSignal(const std::string &name, const qi::Signature &signature, SignalMemberGetter getter, int id=-1, bool isSignalProperty=false)
static AnyFunction from(F &&func)
Object is not thread safe, all method calls must occur in the same thread.
Definition: manageable.hpp:36
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
unsigned int advertiseProperty(const std::string &propertyName, A accessor)
unsigned int advertiseBounce(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, boost::true_type)
unsigned int advertise(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, Dummy< 0 >)
boost::enable_if< boost::is_base_of< Actor, T >, AnyFunction >::type getStrandAccessor()
void setSignature(const AnyFunction &f)
boost::enable_if< typename detail::Accessor< A >::is_accessor, PropertyBase * >::type propertyAccess(A acc, void *instance)
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
unsigned int xAdvertiseMethod(MetaMethodBuilder &builder, AnyFunction func, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)