7 #ifndef QI_TYPE_DETAIL_FUTURE_ADAPTER_HXX_
8 #define QI_TYPE_DETAIL_FUTURE_ADAPTER_HXX_
17 static const char* InvalidValueError =
"value is invalid";
18 static const char* InvalidFutureError =
"function returned an invalid future";
30 qiLogDebug(
"qi.adapter") <<
"converting value";
36 catch(
const std::exception& e)
38 qiLogError(
"qi.adapter") <<
"future to promise forwarding error: " << e.what();
60 boost::shared_ptr<GenericObject> ao)
69 qiLogDebug(
"qi.adapter") <<
"futureAdapter trigger";
79 if (gfut.
call<
bool>(
"hasError", 0))
81 qiLogDebug(
"qi.adapter") <<
"futureAdapter: future in error";
82 std::string s = gfut.
call<std::string>(
"error", 0);
83 qiLogDebug(
"qi.adapter") <<
"futureAdapter: got error: " << s;
87 if (gfut.
call<
bool>(
"isCanceled"))
89 qiLogDebug(
"qi.adapter") <<
"futureAdapter: future canceled";
93 qiLogDebug(
"qi.adapter") <<
"futureAdapter: future has value";
109 qiLogDebug(
"qi.adapter") <<
"getGenericFuture: Invalid value.";
110 return boost::shared_ptr<GenericObject>();
120 *kind = ft1->templateArgument()->kind();
126 *kind = ft2->templateArgument()->kind();
130 return boost::shared_ptr<GenericObject>();
131 return boost::make_shared<GenericObject>(onext, val.
rawValue());
137 template <
typename T>
146 if (!ao->call<
bool>(
"isValid"))
148 promise.
setError(InvalidFutureError);
155 auto spVal = std::make_shared<UniqueAnyReference>(std::move(uval));
156 boost::function<void()> cb = [=]()
mutable {
157 if (!spVal || !(*spVal)->isValid() || !ao)
158 throw std::logic_error{
"Future is either invalid or has already been adapted."};
162 auto localRef = ka::exchange(spVal,
nullptr);
163 futureAdapterGeneric<T>(**localRef, promise, ka::exchange(ao,
nullptr));
172 ao->call<
void>(
"_connect", cb);
176 &GenericObject::call<void>),
177 boost::weak_ptr<GenericObject>(ao),
180 catch (std::exception& e)
182 qiLogError(
"qi.object") <<
"future connect error " << e.what();
183 promise.
setError(
"internal error: cannot connect returned future");
188 template <
typename T>
193 throw std::runtime_error(InvalidValueError);
199 if (!ao->call<
bool>(
"isValid"))
200 throw std::runtime_error(InvalidFutureError);
207 QI_ONCE(targetType = typeOf<T>());
210 auto conv = val->convert(targetType);
212 throw std::runtime_error(std::string(
"Unable to convert call result to target type: from ") +
213 val->signature(
true).toPrettySignature() +
" to " +
215 return std::move(*conv->ptr<T>(
false));
217 catch(
const std::exception& e)
219 throw std::runtime_error(std::string(
"Return argument conversion error: ") + e.what());
228 throw std::runtime_error(InvalidValueError);
232 if (!ao->call<
bool>(
"isValid"))
233 throw std::runtime_error(InvalidFutureError);
241 template <
typename T>
246 promise.
setError(InvalidValueError);
251 QI_ONCE(targetType = typeOf<T>());
254 auto conv = ref->
convert(targetType);
256 promise.
setError(std::string(
"Unable to convert call result to target type: from ")
260 promise.
setValue(*conv->ptr<T>(
false));
263 catch(
const std::exception& e)
265 promise.
setError(std::string(
"Return argument conversion error: ") + e.what());
276 promise.setError(InvalidValueError);
280 promise.setValue(
nullptr);
290 promise.setError(InvalidValueError);
296 promise.setValue(ref->clone());
298 catch(
const std::exception& e)
300 promise.setError(std::string(
"Return argument conversion error: ") + e.what());
304 template <
typename T>
317 auto val = metaFut.
value();
323 template <
typename T>
338 promise.
setError(InvalidValueError);
346 catch (
const std::exception& e)
348 promise.
setError(std::string(
"Return argument conversion error: ") + e.what());
std::string toPrettySignature() const
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bindSilent(AF &&fun, Arg0 &&arg0, Args &&...args)
void futureAdapter(const Future< FT > &f, Promise< PT > p, CONV converter)
void setPromise(qi::Promise< T > &promise, const AnyValue &v)
UniqueAnyReference convert(TypeInterface *targetType) const
void setError(const std::string &msg)
void setAdaptedResult< void >(Promise< void > &promise, UniqueAnyReference ref)
#define QI_ASSERT(expr__)
void futureAdapterGeneric(AnyReference val, qi::Promise< T > promise, boost::shared_ptr< GenericObject > ao)
T extractFuture(const qi::Future< qi::AnyReference > &metaFut)
qi::Signature signature(void *storage=nullptr, bool resolveDynamic=false)
void setAdaptedResult< AnyReference >(Promise< AnyReference > &promise, UniqueAnyReference ref)
void setAdaptedResult(Promise< T > &promise, UniqueAnyReference ref)
R call(const std::string &methodName, Args &&...args)
#define qiLogError(...)
Log in error mode.
T to() const
Convert to anything or throw trying.
qi::Signature signature(bool resolveDynamic=false) const
TypeInterface * type() const
void futureAdapterVal(const qi::Future< qi::AnyValue > &metaFut, qi::Promise< T > promise)
#define QI_TEMPLATE_TYPE_GET(typeInst, templateName)
#define QI_ONCE(code)
Execute code once, parallel calls are blocked until code finishes.
boost::shared_ptr< GenericObject > getGenericFuture(AnyReference val, TypeKind *kind=0)
AnyReference asReference() const
const char * infoString()
void setOnCancel(boost::function< void(qi::Promise< T > &)> cancelCallback)
AnyReference clone() const
const std::string & error(int msecs=FutureTimeout_Infinite) const
const ValueType & value(int msecs=FutureTimeout_Infinite) const
Return the value associated to a Future.
void setValue(const ValueType &value)
bool handleFuture(AnyReference val, Promise< T > promise)
void extractFuture< void >(const qi::Future< qi::AnyReference > &metaFut)
bool hasError(int msecs=FutureTimeout_Infinite) const