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>
114 -> decltype(std::declval<F>()(std::forward<Args>(args)...))
116 auto s = _wptr.lock();
118 return _f(std::forward<Args>(args)...);
129 template <
typename T,
bool IsActor>
132 template <
typename T>
135 template <
typename F>
137 template <
typename F>
140 return std::forward<F>(func);
144 template <
typename T>
147 static const bool is_async =
true;
148 template <
typename F>
150 std::declval<T>()->strandedUnwrapped(std::declval<
typename std::decay<F>::type>()));
151 template <
typename F>
154 return arg->strandedUnwrapped(std::forward<F>(func), std::move(onFail));
164 template <
typename T>
165 static decltype(T::is_async)
f(
int);
166 template <typename T>
171 template <typename T>
175 std::false_type>::type
179 template <
typename T,
bool IsTrackable>
186 template <
typename F>
188 template <
typename F>
191 return std::forward<F>(func);
195 template <
typename T>
199 template <
typename F>
207 template <
typename F>
208 static wrap_type<F>
wrap(T* arg, F&& func, boost::function<
void()> onFail)
210 return ObjectWrapType::wrap(arg, std::forward<F>(func), onFail);
214 template <
typename T>
217 template <
typename F>
226 template <
typename F>
227 static wrap_type<F>
wrap(T* arg, F&& func, boost::function<
void()> onFail)
231 std::forward<F>(func),
236 template <
typename T>
237 struct BindTransformImpl<boost::weak_ptr<T>, false>
239 template <
typename F>
240 using wrap_type = LockAndCall<boost::weak_ptr<T>,
typename std::decay<F>::type>;
242 static T* transform(
const boost::weak_ptr<T>& arg)
246 return arg.lock().get();
249 template <
typename F>
250 static wrap_type<F> wrap(
const boost::weak_ptr<T>& arg, F&& func, boost::function<
void()> onFail)
252 return LockAndCall<boost::weak_ptr<T>,
typename std::decay<F>::type>(
254 std::forward<F>(func),
259 template <
typename T>
260 struct BindTransformImpl<boost::shared_ptr<T>, false>
262 using ObjectWrapType = ObjectWrap<boost::shared_ptr<T>, std::is_base_of<Actor, T>::value>;
263 template <
typename F>
264 using wrap_type =
typename ObjectWrapType::template wrap_type<F>;
266 static boost::shared_ptr<T> transform(boost::shared_ptr<T> arg)
268 return std::move(arg);
271 template <
typename F>
272 static wrap_type<F> wrap(
const boost::shared_ptr<T>& arg, F&& func, boost::function<
void()> onFail)
274 return ObjectWrapType::wrap(arg, std::forward<F>(func), onFail);
278 template <
typename T>
288 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
290 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
294 auto transformed = Transform::transform(arg0);
295 boost::function<RF> f =
boost::bind(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...);
296 return Transform::wrap(arg0, std::move(f), std::move(onFail));
298 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
300 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
bindSilent(AF&& fun,
304 return bindWithFallback<RF, AF>({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
306 template <
typename RF,
typename AF,
typename Arg0,
typename... Args>
308 typename std::enable_if<std::is_function<RF>::value, boost::function<RF>>::type
bind(AF&& fun,
313 std::forward<Args>(args)...);
318 template<
typename AF,
typename Arg0,
typename... Args>
324 std::declval<Args>()...));
328 template <
typename AF,
typename Arg0,
typename... Args>
329 auto bindWithFallback(boost::function<
void()> onFail, AF&& fun, Arg0&& arg0, Args&&... args)
335 auto transformed = Transform::transform(arg0);
336 return Transform::wrap(arg0,
337 boost::bind(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...),
340 template <
typename AF,
typename Arg0,
typename... Args>
342 -> decltype(
bindWithFallback({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...))
344 return bindWithFallback({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
346 template <
typename AF,
typename Arg0,
typename... Args>
347 auto bind(AF&& fun, Arg0&& arg0, Args&&... args)
349 std::forward<AF>(fun),
350 std::forward<Arg0>(arg0),
351 std::forward<Args>(args)...))
354 std::forward<AF>(fun),
355 std::forward<Arg0>(arg0),
356 std::forward<Args>(args)...);
359 template <
typename R,
typename T,
typename Instance,
typename... Args0,
typename... Args1>
360 auto bind(R(T::*fun)(Args0...), Instance&& instance, Args1&&... args1)
363 std::forward<Instance>(instance),
364 std::forward<Args1>(args1)...))
368 std::forward<Instance>(instance),
369 std::forward<Args1>(args1)...);
373 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
374 auto bindWithFallback(boost::function<
void()> onFail, AF&& fun, Arg0&& arg0, Args&&... args)
375 ->
typename std::enable_if<!std::is_function<R>::value,
377 decltype(boost::bind<R>(std::forward<AF>(fun),
379 std::forward<Args>(args)...))>>::type
382 auto transformed = Transform::transform(arg0);
383 return Transform::wrap(arg0,
384 boost::bind<R>(std::forward<AF>(fun), std::move(transformed), std::forward<Args>(args)...),
387 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
389 ->
typename std::enable_if<!std::is_function<R>::value,
390 decltype(bindWithFallback<R>({},
391 std::forward<AF>(fun),
392 std::forward<Arg0>(arg0),
393 std::forward<Args>(args)...))>::type
395 return bindWithFallback<R>({}, std::forward<AF>(fun), std::forward<Arg0>(arg0), std::forward<Args>(args)...);
398 template <
typename R,
typename AF,
typename Arg0,
typename... Args>
399 auto bind(AF&& fun, Arg0&& arg0, Args&&... args)
400 ->
typename std::enable_if<!std::is_function<R>::value,
402 std::forward<AF>(fun),
403 std::forward<Arg0>(arg0),
404 std::forward<Args>(args)...))>::type
407 std::forward<AF>(fun),
408 std::forward<Arg0>(arg0),
409 std::forward<Args>(args)...);
412 template <
typename F,
typename T>
419 template <
typename F,
typename T>
426 template <
typename F,
typename T>
433 template<
typename F,
typename T>
435 boost::function<
void()> onFail, boost::function<F> f,
const T& toTrack)
439 template<
typename F,
typename T>
440 boost::function<F>
trackSilent(boost::function<F> f,
const T& toTrack)
442 return trackWithFallback<F, T>({}, std::move(f), toTrack);
444 template<
typename F,
typename T>
445 boost::function<F>
track(boost::function<F> f,
const T& toTrack)
451 #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.
auto trackWithFallback(boost::function< void()> onFail, F &&f, T &&toTrack) -> decltype(detail::BindTransform< T >::wrap(std::forward< T >(toTrack), std::forward< F >(f), std::move(onFail)))
static wrap_type< F > wrap(const T &arg, F &&func, boost::function< void()> onFail)
auto track(F &&f, T &&toTrack) -> decltype(trackWithFallback(detail::throwPointerLockException, std::forward< F >(f), std::forward< T >(toTrack)))
decltype(std::declval< T >() ->strandedUnwrapped(std::declval< typename std::decay< F >::type >())) wrap_type
static decltype(T::is_async) f(int)
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bindWithFallback(boost::function< void()> onFail, AF &&fun, Arg0 &&arg0, Args &&...args)
void defaultConstruct< void >()
typename std::decay< F >::type wrap_type
BindTransformImpl< typename std::decay< T >::type, std::is_base_of< TrackableBase, typename std::remove_pointer< typename std::decay< T >::type >::type >::value > BindTransform
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)
boost::weak_ptr< T > weakPtr() const
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 trackSilent(F &&f, T &&toTrack) -> decltype(trackWithFallback(
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
decltype(boost::bind(std::declval< AF >(), detail::BindTransform< Arg0 >::transform(std::declval< Arg0 >()), std::declval< Args >()...)) type
Trackable()
Default constructor.