- Aldebaran documentation |
- C++ Libraries |
- index

libqi-api 2.8.7.4

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
genericobject.hpp
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 _QI_TYPE_DETAIL_GENERIC_OBJECT_HPP_
8 #define _QI_TYPE_DETAIL_GENERIC_OBJECT_HPP_
9
10 #include <map>
11 #include <string>
12 #include <sstream>
13
14 #include <boost/smart_ptr/enable_shared_from_this.hpp>
15
16 #include <qi/api.hpp>
17 #include <qi/type/detail/futureadapter.hpp>
18 #include <qi/type/detail/manageable.hpp>
19 #include <qi/future.hpp>
20 #include <qi/signal.hpp>
21 #include <qi/type/typeobject.hpp>
22 #include <qi/objectuid.hpp>
23
24 #ifdef _MSC_VER
25 # pragma warning( push )
26 # pragma warning( disable: 4251 )
27 #endif
28
29 namespace qi
30 {
31
32 /* ObjectValue
33 * static version wrapping class C: Type<C>
34 * dynamic version: Type<DynamicObject>
35 *
36 * All the methods are convenience wrappers that bounce to the ObjectTypeInterface,
37 * except Event Loop management
38 * This class has pointer semantic. Do not use directly, use AnyObject,
39 * obtained through Session, DynamicObjectBuilder or ObjectTypeBuilder.
40 */
41 class QI_API GenericObject
42 : public Manageable
43 , public boost::enable_shared_from_this<GenericObject>
44 {
45 public:
46 GenericObject(ObjectTypeInterface *type, void *value, const boost::optional<ObjectUid>& maybeUid = boost::none);
47 ~GenericObject();
48 const MetaObject &metaObject();
49
50 // Help doxygen and the header reader a bit.
51 template <typename R, typename... Args>
52 R call(const std::string& methodName, Args&&... args);
53
54 template <typename R, typename... Args>
55 qi::Future<R> async(const std::string& methodName, Args&&... args);
56
72 qi::Future<AnyReference> metaCall(const std::string &nameWithOptionalSignature, const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto, Signature returnSignature = Signature());
73
81 qi::Future<AnyReference> metaCall(unsigned int method, const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto, Signature returnSignature = Signature());
83
85 int findMethod(const std::string& name, const GenericFunctionParameters& parameters);
86
87 void post(const std::string& eventName,
88 qi::AutoAnyReference p1 = qi::AutoAnyReference(),
89 qi::AutoAnyReference p2 = qi::AutoAnyReference(),
90 qi::AutoAnyReference p3 = qi::AutoAnyReference(),
91 qi::AutoAnyReference p4 = qi::AutoAnyReference(),
92 qi::AutoAnyReference p5 = qi::AutoAnyReference(),
93 qi::AutoAnyReference p6 = qi::AutoAnyReference(),
94 qi::AutoAnyReference p7 = qi::AutoAnyReference(),
95 qi::AutoAnyReference p8 = qi::AutoAnyReference());
96
97 void metaPost(unsigned int event, const GenericFunctionParameters& params);
98 void metaPost(const std::string &nameWithOptionalSignature, const GenericFunctionParameters &in);
99
105 template <typename FUNCTOR_TYPE>
106 qi::FutureSync<SignalLink> connect(const std::string& eventName, FUNCTOR_TYPE callback,
107 MetaCallType threadingModel = MetaCallType_Direct);
108
109
110 qi::FutureSync<SignalLink> connect(const std::string &name, const SignalSubscriber& functor);
111
113 qi::FutureSync<SignalLink> connect(unsigned int signal, const SignalSubscriber& subscriber);
114
122 qi::FutureSync<SignalLink> connect(unsigned int signal, AnyObject target, unsigned int slot);
123
125 qi::FutureSync<void> disconnect(SignalLink linkId);
126
127 template<typename T>
128 qi::FutureSync<T> property(const std::string& name);
129
130 template<typename T>
131 qi::FutureSync<void> setProperty(const std::string& name, const T& val);
132
133 //Low Level Properties
134 qi::FutureSync<AnyValue> property(unsigned int id);
135 qi::FutureSync<void> setProperty(unsigned int id, const AnyValue &val);
136
137
138 bool isValid() { return type && value;}
139 ObjectTypeInterface* type;
140 void* value;
141 ObjectUid uid;
142
143 private:
145 Future<AnyReference> metaCallNoUnwrap(
146 unsigned int method,
147 const GenericFunctionParameters& params,
148 const MetaCallType callType,
149 const Signature& returnSignature);
150
152 std::string makeFindMethodErrorMessage(
153 const std::string& nameWithOptionalSignature,
154 const GenericFunctionParameters& args,
155 const int errorNo);
156 };
157
158 namespace detail
159 {
160
161 // Storage type used by Object<T>, and Proxy.
162 using ManagedObjectPtr = boost::shared_ptr<GenericObject>;
163
164 }
165
166 // C4251
167 template <typename FUNCTION_TYPE>
168 qi::FutureSync<SignalLink> GenericObject::connect(const std::string& eventName,
169 FUNCTION_TYPE callback,
170 MetaCallType model)
171 {
172 return connect(eventName,
173 SignalSubscriber(AnyFunction::from(callback), model));
174 }
175
176 namespace detail
177 {
178
179 template <typename T>
180 struct isFuture : boost::false_type {};
181 template <typename T>
182 struct isFuture<qi::Future<T> > : boost::true_type {};
183 template <typename T>
184 struct isFuture<qi::FutureSync<T> > : boost::true_type {};
185
186 }
187
188 /* Generate R GenericObject::call(methodname, args...)
189 * for all argument counts
190 * The function packs arguments in a vector<AnyReference>, computes the
191 * signature and bounce those to metaCall.
192 */
193
194 template <typename R, typename... Args>
195 R GenericObject::call(const std::string& methodName, Args&&... args)
196 {
197 static_assert(!detail::isFuture<R>::value, "return type of call must not be a Future");
198 if (!value || !type)
199 throw std::runtime_error("Invalid GenericObject");
200 std::vector<qi::AnyReference> params = {qi::AnyReference::from(args)...};
201 qi::Future<AnyReference> fmeta = metaCall(methodName, params, MetaCallType_Direct, typeOf<R>()->signature());
202 return detail::extractFuture<R>(fmeta);
203 }
204
208 template <typename R, typename... Args>
209 qi::Future<R> GenericObject::async(const std::string& methodName, Args&&... args)
210 {
211 std::vector<qi::AnyReference> anyArgs = {qi::AnyReference::from(args)...};
212 int methodId = findMethod(methodName, anyArgs);
213 if (methodId < 0) // in that case, the method ID is an error number
214 return makeFutureError<R>(makeFindMethodErrorMessage(methodName, anyArgs, methodId));
215 auto futureMeta = metaCallNoUnwrap(methodId, anyArgs, MetaCallType_Queued, typeOf<R>()->signature());
216 qi::Promise<R> result;
217 qi::adaptFutureUnwrap(futureMeta, result);
218 return result.future();
219 }
220
221 template<typename T>
222 qi::FutureSync<T> GenericObject::property(const std::string& name)
223 {
224 int pid = metaObject().propertyId(name);
225 if (pid < 0)
226 {
227 std::ostringstream ss;
228 ss << "property \"" << name << "\" was not found";
229 return makeFutureError<T>(ss.str());
230 }
231 qi::Future<AnyValue> f = property(pid);
232 qi::Promise<T> p;
233 f.connect(boost::bind(&detail::futureAdapterVal<T>,_1, p),
234 FutureCallbackType_Sync);
235 return p.future();
236 }
237
238 template<typename T>
239 qi::FutureSync<void> GenericObject::setProperty(const std::string& name, const T& val)
240 {
241 int pid = metaObject().propertyId(name);
242 if (pid < 0)
243 {
244 std::ostringstream ss;
245 ss << "property \"" << name << "\" was not found";
246 return makeFutureError<void>(ss.str());
247 }
248 return setProperty(pid, AnyValue::from(val));
249 }
250
251 /* An AnyObject is actually of a Dynamic type: The underlying TypeInterface*
252 * is not allways the same.
253 * Override backend shared_ptr<GenericObject>
254 */
255 template<>
256 class QI_API TypeImpl<boost::shared_ptr<GenericObject>> :
257 public DynamicTypeInterface
258 {
259 public:
260 AnyReference get(void* storage) override
261 {
262 detail::ManagedObjectPtr* val = (detail::ManagedObjectPtr*)ptrFromStorage(&storage);
263 AnyReference result;
264 if (!*val)
265 {
266 return AnyReference();
267 }
268 return AnyReference((*val)->type, (*val)->value);
269 }
270
271 void set(void** storage, AnyReference source) override
272 {
273 qiLogCategory("qitype.object");
274 detail::ManagedObjectPtr* val = (detail::ManagedObjectPtr*)ptrFromStorage(storage);
275
276 if (!source.type())
277 throw std::runtime_error("cannot set object from an invalid value");
278
279 if (source.type()->info() == info())
280 { // source is objectptr
281 detail::ManagedObjectPtr* src = source.ptr<detail::ManagedObjectPtr>(false);
282 if (!*src)
283 qiLogWarning() << "NULL Object";
284 *val = *src;
285 }
286 else if (source.kind() == TypeKind_Dynamic)
287 { // try to dereference dynamic type in case it contains an object
288 auto content = source.content();
289 if (!content.isValid())
290 throw std::runtime_error("cannot set object from an invalid dynamic value");
291 set(storage, source.content());
292 }
293 else if (source.kind() == TypeKind_Object)
294 { // wrap object in objectptr: we do not keep it alive,
295 // but source type offers no tracking capability
296 detail::ManagedObjectPtr op(new GenericObject(static_cast<ObjectTypeInterface*>(source.type()), source.rawValue()));
297 *val = op;
298 }
299 else if (source.kind() == TypeKind_Pointer)
300 {
301 PointerTypeInterface* ptype = static_cast<PointerTypeInterface*>(source.type());
302 // FIXME: find a way!
303 if (ptype->pointerKind() == PointerTypeInterface::Shared)
304 qiLogInfo() << "Object will *not* track original shared pointer";
305 set(storage, *source);
306 }
307 else if (source.kind() == TypeKind_Optional)
308 {
309 set(storage, source.content());
310 }
311 else
312 throw std::runtime_error((std::string)"Cannot assign non-object " + source.type()->infoString() + " to Object");
313 }
314
315 using Methods = DefaultTypeImplMethods<detail::ManagedObjectPtr, TypeByPointerPOD<detail::ManagedObjectPtr>>;
316 _QI_BOUNCE_TYPE_METHODS(Methods);
317 };
318
319 }
320
321 #ifdef _MSC_VER
322 # pragma warning( pop )
323 #endif
324
325 #endif
qi::detail::ManagedObjectPtr
boost::shared_ptr< GenericObject > ManagedObjectPtr
Definition: genericobject.hpp:162
qi::TypeImpl
Definition: typeimpl.hxx:300
qi::GenericObject::async
qi::Future< R > async(const std::string &methodName, Args &&...args)
Definition: genericobject.hpp:209
qi::AnyValue
Definition: anyvalue.hpp:19
qi::GenericObject::uid
ObjectUid uid
Uid of "value".
Definition: genericobject.hpp:141
qi::GenericFunctionParameters
Definition: anyfunction.hpp:266
qi::Future::connect
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:545
QI_API
#define QI_API
Definition: api.hpp:33
qi::GenericObject::connect
qi::FutureSync< SignalLink > connect(const std::string &eventName, FUNCTOR_TYPE callback, MetaCallType threadingModel=MetaCallType_Direct)
objectuid.hpp
qi::metaCall
qi::Future< AnyReference > metaCall(ExecutionContext *ec, ObjectThreadingModel objectThreadingModel, MetaCallType methodThreadingModel, MetaCallType callType, AnyObject manageable, unsigned int methodId, AnyFunction func, const GenericFunctionParameters &params, bool noCloneFirst=false, unsigned int callerId=0, qi::os::timeval postTimestamp=qi::os::timeval())
qi::Future
Definition: executioncontext.hpp:20
qiLogCategory
#define qiLogCategory(Cat)
Definition: log.hpp:53
qi::GenericObject::isValid
bool isValid()
Definition: genericobject.hpp:138
qi::TypeKind_Dynamic
Definition: fwd.hpp:66
qi::MetaObject::propertyId
int propertyId(const std::string &name) const
qi::AnyReference
Definition: anyreference.hpp:360
qi::Signature
Definition: signature.hpp:66
qi::AnyValue::from
static AnyValue from(const T &r)
Definition: anyvalue.hpp:94
qi::Manageable
Definition: manageable.hpp:123
qi::MetaCallType_Auto
Honor the default behavior.
Definition: typeobject.hpp:26
api.hpp
dll import/export and compiler message
qi::TypeKind_Optional
Definition: fwd.hpp:73
qi::GenericObject::findMethod
int findMethod(const std::string &name, const GenericFunctionParameters &parameters)
Find method named name callable with arguments parameters.
qiLogWarning
#define qiLogWarning(...)
Log in warning mode.
Definition: log.hpp:109
futureadapter.hpp
qi::detail::isFuture
Definition: genericobject.hpp:180
qi::Promise::future
Future< T > future() const
Get a future linked to this promise. Can be called multiple times.
Definition: future_fwd.hpp:881
qi::GenericObject::call
R call(const std::string &methodName, Args &&...args)
Definition: genericobject.hpp:195
qi::GenericObject
Definition: genericobject.hpp:41
qi::TypeKind_Object
Definition: fwd.hpp:63
qi::MetaCallType_Direct
Force a synchronous call.
Definition: typeobject.hpp:28
qi::TypeKind_Pointer
Definition: fwd.hpp:64
qiLogInfo
#define qiLogInfo(...)
Log in info mode.
Definition: log.hpp:98
_QI_BOUNCE_TYPE_METHODS
#define _QI_BOUNCE_TYPE_METHODS(Bounce)
Implement all methods of Type as bouncers to Bouncer.
Definition: typeimpl.hxx:273
qi::GenericObject::setProperty
qi::FutureSync< void > setProperty(const std::string &name, const T &val)
Definition: genericobject.hpp:239
qi::async
auto async(F &&callback) -> decltype(asyncDelay(std::forward< F >(callback), qi::Duration(0)))
Definition: async.hpp:53
qi::FutureCallbackType_Sync
Definition: future_fwd.hpp:105
qi::GenericObject::type
ObjectTypeInterface * type
Definition: genericobject.hpp:139
future.hpp
qi::ObjectTypeInterface
Definition: typeobject.hpp:48
signal.hpp
qi::GenericObject::property
qi::FutureSync< T > property(const std::string &name)
Definition: genericobject.hpp:222
qi::MetaCallType
MetaCallType
Definition: typeobject.hpp:24
typeobject.hpp
manageable.hpp
qi::PointerTypeInterface::Shared
Definition: typeinterface.hpp:143
qi::log::env::QI_DEFAULT_LOGHANDLER::value::none
char const *const none
qi::Object< Empty >
qi::GenericObject::metaObject
const MetaObject & metaObject()
qi::src
T src(const std::atomic< T > &x)
Definition: atomic.hpp:318
qi::log::env::QI_DEFAULT_LOGHANDLER::name
char const *const name
qi::FutureSync
Definition: future_fwd.hpp:70
qi::DynamicTypeInterface
Definition: typeinterface.hpp:310
qi::AnyFunction::from
static AnyFunction from(F &&func)
qi::AutoAnyReference
Definition: anyreference.hpp:409
qi::detail::AnyReferenceBase::from
static AnyReference from(const T &ref)
Definition: anyreference.hxx:64
qi::SignalLink
qi::uint64_t SignalLink
Definition: signal.hpp:36
qi::Promise
Definition: future_fwd.hpp:71
qi::GenericObject::metaCall
qi::Future< AnyReference > metaCall(const std::string &nameWithOptionalSignature, const GenericFunctionParameters &params, MetaCallType callType=MetaCallType_Auto, Signature returnSignature=Signature())
qi::MetaCallType_Queued
Force an asynchronous call in an other thread.
Definition: typeobject.hpp:30
qi::GenericObject::value
void * value
Definition: genericobject.hpp:140
qi::bind
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
qi::PtrUid
Definition: ptruid.hpp:33
qi::MetaObject
Description of the signals and methods accessible on an ObjectTypeInterface.
Definition: metaobject.hpp:25
qi::adaptFutureUnwrap
void adaptFutureUnwrap(Future< AnyReference > &f, Promise< R > &p)
Feed a promise from a generic future which may be unwrapped if it contains itself a future...
Definition: future.hxx:528