8 #ifndef _QI_DETAIL_TRACKABLE_HXX_
9 #define _QI_DETAIL_TRACKABLE_HXX_
11 #include <type_traits>
12 #include <boost/function.hpp>
13 #include <boost/bind.hpp>
14 #include <boost/weak_ptr.hpp>
15 #include <boost/function_types/result_type.hpp>
23 : _wasDestroyed(false)
25 T* thisAsT =
static_cast<T*
>(
this);
26 _ptr = boost::shared_ptr<T>(thisAsT,
boost::bind(&Trackable::_destroyed, _1));
31 : _wasDestroyed(false)
33 _ptr = boost::shared_ptr<T>(ptr,
boost::bind(&Trackable::_destroyed, _1));
46 boost::mutex::scoped_lock lock(_mutex);
47 while (!_wasDestroyed)
57 boost::mutex::scoped_lock lock(_mutex);
69 qiLogError(
"qi.Trackable") <<
"Trackable destroyed without calling destroy()";
78 return boost::weak_ptr<T>(_ptr);
97 template <
typename WT,
typename F>
102 boost::function<void()> _onFail;
106 : _wptr(std::move(arg))
107 , _f(std::move(func))
108 , _onFail(std::move(onFail))
111 template <
typename... Args>
113 auto operator()(Args&&... args) -> decltype(std::declval<F>()(std::forward<Args>(args)...))
115 auto s = _wptr.lock();
117 return _f(std::forward<Args>(args)...);
128 template <
typename T,
bool IsActor>
131 template <
typename T>
134 template <
typename F>
136 template <
typename F>
139 return std::forward<F>(func);
143 template <
typename T>
146 static const bool is_async =
true;
147 template <
typename F>
149 std::declval<T>()->stranded(std::declval<
typename std::decay<F>::type>()));
150 template <
typename F>
153 return arg->stranded(std::forward<F>(func), std::move(onFail));
163 template <
typename T>
164 static decltype(T::is_async)
f(
int);
165 template <typename T>
170 template <typename T>
174 std::false_type>::type
178 template <
bool IsAsync,
typename F,
typename... Args>
181 template <
typename F,
typename... Args>
184 using type = decltype(std::declval<F>()(std::declval<Args>()...));
187 template <
typename F,
typename... Args>
192 using type =
typename std::result_of<F(Args...)>::type::TemplateValue;
195 template <
typename T,
typename... Args>
198 template <
typename T,
bool IsTrackable>
205 template <
typename F>
207 template <
typename F>
210 return std::forward<F>(func);
214 template <
typename T>
218 template <
typename F>
226 template <
typename F>
227 static wrap_type<F>
wrap(T* arg, F&& func, boost::function<
void()> onFail)
229 return ObjectWrapType::wrap(arg, std::forward<F>(func), onFail);
233 template <
typename T>
236 template <
typename F>
245 template <
typename F>
246 static wrap_type<F>
wrap(T* arg, F&& func, boost::function<
void()> onFail)
250 std::forward<F>(func),
255 template <
typename T>
256 struct BindTransformImpl<boost::weak_ptr<T>, false>
258 template <
typename F>
259 using wrap_type = LockAndCall<boost::weak_ptr<T>,
typename std::decay<F>::type>;
261 static T* transform(
const boost::weak_ptr<T>& arg)
265 return arg.lock().get();
268 template <
typename F>
269 static wrap_type<F> wrap(
const boost::weak_ptr<T>& arg, F&& func, boost::function<
void()> onFail)
271 return LockAndCall<boost::weak_ptr<T>,
typename std::decay<F>::type>(
273 std::forward<F>(func),
278 template <
typename T>
279 struct BindTransformImpl<boost::shared_ptr<T>, false>
281 using ObjectWrapType = ObjectWrap<boost::shared_ptr<T>, std::is_base_of<Actor, T>::value>;
282 template <
typename F>
283 using wrap_type =
typename ObjectWrapType::template wrap_type<F>;
285 static boost::shared_ptr<T> transform(boost::shared_ptr<T> arg)
287 return std::move(arg);
290 template <
typename F>
291 static wrap_type<F> wrap(
const boost::shared_ptr<T>& arg, F&& func, boost::function<
void()> onFail)
293 return ObjectWrapType::wrap(arg, std::forward<F>(func), onFail);
297 template <typename T, typename K = typename std::decay<T>::type>
307 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
309 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
313 auto transformed = Transform::transform(arg0);
314 boost::function<RF> f =
boost::bind(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...);
315 return Transform::wrap(arg0, std::move(f), std::move(onFail));
317 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
319 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
bindSilent(AF&& fun,
323 return bindWithFallback<RF, AF>({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
325 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
327 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
bind(AF&& fun,
332 std::forward<Args>(args)...);
335 template <
typename AF,
typename Arg0,
typename... Args>
336 auto bindWithFallback(boost::function<
void()> onFail, AF&& fun, Arg0&& arg0, Args&&... args) ->
340 std::forward<Args>(args)...))>
343 auto transformed = Transform::transform(arg0);
344 return Transform::wrap(arg0,
345 boost::bind(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...),
348 template <
typename AF,
typename Arg0,
typename... Args>
350 -> decltype(
bindWithFallback({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...))
352 return bindWithFallback({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
354 template <
typename AF,
typename Arg0,
typename... Args>
356 std::forward<AF>(fun),
357 std::forward<Arg0>(arg0),
358 std::forward<Args>(args)...))
361 std::forward<AF>(fun),
362 std::forward<Arg0>(arg0),
363 std::forward<Args>(args)...);
367 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
368 auto bindWithFallback(boost::function<
void()> onFail, AF&& fun, Arg0&& arg0, Args&&... args) ->
369 typename std::enable_if<!std::is_function<R>::value,
371 decltype(boost::bind<R>(std::forward<AF>(fun),
373 std::forward<Args>(args)...))>>::type
376 auto transformed = Transform::transform(arg0);
377 return Transform::wrap(arg0,
378 boost::bind<R>(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...),
381 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
382 auto bindSilent(AF&& fun, Arg0&& arg0, Args&&... args) ->
typename std::enable_if<
383 !std::is_function<R>::value,
385 bindWithFallback<R>({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...))>::type
387 return bindWithFallback<R>({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
389 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
390 auto bind(AF&& fun, Arg0&& arg0, Args&&... args) ->
391 typename std::enable_if<!std::is_function<R>::value,
393 std::forward<AF>(fun),
394 std::forward<Arg0>(arg0),
395 std::forward<Args>(args)...))>::type
398 std::forward<AF>(fun),
399 std::forward<Arg0>(arg0),
400 std::forward<Args>(args)...);
403 template <
typename F,
typename Arg0>
409 template <
typename F,
typename Arg0>
415 template <
typename F,
typename Arg0>
421 template<
typename F,
typename Arg0>
423 boost::function<F> f,
const Arg0& arg0)
427 template<
typename F,
typename Arg0>
428 boost::function<F>
trackSilent(boost::function<F> f,
const Arg0& arg0)
430 return trackWithFallback<F, Arg0>({}, std::move(f), arg0);
432 template<
typename F,
typename Arg0>
433 boost::function<F>
track(boost::function<F> f,
const Arg0& arg0)
439 #endif // _QI_DETAIL_TRACKABLE_HXX_
auto operator()(Args &&...args) -> decltype(std::declval< F >()(std::forward< Args >(args)...))
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bindSilent(AF &&fun, Arg0 &&arg0, Args &&...args)
void destroy()
Stop and flush the logging system.
static wrap_type< F > wrap(const T &arg, F &&func, boost::function< void()> onFail)
decltype(std::declval< T >() ->stranded(std::declval< typename std::decay< F >::type >())) wrap_type
static decltype(T::is_async) f(int)
auto trackSilent(F &&f, Arg0 &&arg0) -> decltype(trackWithFallback(
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bindWithFallback(boost::function< void()> onFail, AF &&fun, Arg0 &&arg0, Args &&...args)
decltype(std::declval< F >()(std::declval< Args >()...)) type
typename std::result_of< F(Args...)>::type::TemplateValue type
void defaultConstruct< void >()
typename std::decay< F >::type wrap_type
void throwPointerLockException()
#define qiLogError(...)
Log in error mode.
LockAndCall(WT arg, F func, boost::function< void()> onFail)
auto bind(AF &&fun, Arg0 &&arg0, Args &&...args) -> typename std::enable_if<!std::is_function< R >::value, decltype(bindWithFallback< R >(detail::throwPointerLockException, std::forward< AF >(fun), std::forward< Arg0 >(arg0), std::forward< Args >(args)...))>::type
static wrap_type< F > wrap(const T &arg, F &&func, boost::function< void()> onFail)
BindTransformImpl< K, std::is_base_of< TrackableBase, typename std::remove_pointer< K >::type >::value > BindTransform
auto track(F &&f, Arg0 &&arg0) -> decltype(trackWithFallback(detail::throwPointerLockException, std::forward< F >(f), std::forward< Arg0 >(arg0)))
struct QI_API_DEPRECATED_MSG(Use 'QI_TYPE_ENUM'instead) QI_TYPE_ENUM_REGISTER_
Object tracking by blocking destruction while shared pointers are present.
auto trackWithFallback(boost::function< void()> onFail, F &&f, Arg0 &&arg0) -> decltype(detail::BindTransform< Arg0 >::wrap(std::forward< Arg0 >(arg0), std::forward< F >(f), std::move(onFail)))
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Trackable()
Default constructor.
boost::weak_ptr< T > weakPtr()