7 #ifndef _QI_STRAND_HPP_
8 #define _QI_STRAND_HPP_
14 #include <boost/enable_shared_from_this.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <boost/function.hpp>
17 #include <boost/noncopyable.hpp>
18 #include <boost/type_traits/function_traits.hpp>
21 # pragma warning( push )
22 # pragma warning( disable: 4996 ) // TODO: Reactivate this warning once msvc stop triggerring a warning on overloading a deprecated function
45 using Queue = std::deque<boost::shared_ptr<Callback>>;
62 boost::shared_ptr<Callback>
createCallback(boost::function<
void()> cb);
63 void enqueue(boost::shared_ptr<Callback> cbStruct);
66 void cancel(boost::shared_ptr<Callback> cbStruct);
77 void stopProcess(boost::mutex::scoped_lock& lock,
82 : _eventLoop(eventLoop)
86 , _processingThread(0)
129 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
130 template <typename T, typename F, typename ARG0 comma ATYPEDECL> \
131 QI_API_DEPRECATED_MSG(Use generic 'schedulerFor' overload instead) boost::function<T> schedulerFor( \
132 const F& func, const ARG0& arg0 comma ADECL, \
133 const boost::function<void()>& fallbackCb = boost::function<void()>()) \
135 boost::function<T> funcbind = qi::bind<T>(func, arg0 comma AUSE); \
136 return qi::trackWithFallback( \
138 SchedulerHelper<boost::function_traits<T>::arity, T>::_scheduler( \
150 bool isInThisContext()
override;
152 template <
typename F>
162 boost::shared_ptr<StrandPrivate> _p;
164 void postImpl(boost::function<
void()> callback)
override;
170 template <
int N,
typename T>
171 struct SchedulerHelper;
172 #define typedefi(z, n, _) \
173 typedef typename boost::function_traits<T>::BOOST_PP_CAT( \
174 BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type) BOOST_PP_CAT(P, n);
175 #define placeholders(z, n, __) , BOOST_PP_CAT(_, BOOST_PP_INC(n))
176 #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
177 template <typename T> \
178 struct SchedulerHelper<n, T> \
180 BOOST_PP_REPEAT(n, typedefi, _); \
181 typedef typename boost::function_traits<T>::result_type R; \
182 static boost::function<T> _scheduler(const boost::function<T>& f, \
185 return qi::bind<T>(&_asyncCall, strand, \
186 f BOOST_PP_REPEAT(n, placeholders, _)); \
188 static qi::Future<R> _asyncCall(Strand* strand, \
189 const boost::function<T>& func comma \
193 return ((qi::ExecutionContext*)strand) \
194 ->async(qi::bind<R()>(func comma AUSE)); \
206 template <
typename F,
typename... Args>
207 static auto callInStrand(
209 const boost::function<
void()>& onFail,
210 boost::weak_ptr<StrandPrivate> weakStrand,
214 if (
auto strand = weakStrand.lock())
215 return strand->async(
std::bind(func, std::forward<Args>(args)...));
221 typename std::decay<decltype(func(std::forward<Args>(args)...))>::type>(
"strand is dead");
225 template <
typename F>
234 WrapInStrand(F f, boost::weak_ptr<StrandPrivate> strand, boost::function<
void()> onFail)
235 :
_func(std::move(f))
241 template <
typename... Args>
245 return callInStrand(_func, _onFail, _strand, std::forward<Args>(args)...);
248 template <
typename... Args>
259 # pragma warning( pop )
262 #endif // _QI_STRAND_HPP_
std::atomic< unsigned int > _aliveCount
std::atomic< unsigned int > _curId
boost::shared_ptr< Callback > createCallback(boost::function< void()> cb)
auto schedulerFor(F &&func, boost::function< void()> onFail={}) -> detail::WrapInStrand< typename std::decay< F >::type >
qi::Future< void > async(const boost::function< void()> &callback, qi::SteadyClockTimePoint tp) override
boost::function< void()> _onFail
SteadyClock::time_point SteadyClockTimePoint
Steady clock time point.
Future< void > asyncAtImpl(boost::function< void()> cb, qi::SteadyClockTimePoint tp) override
std::deque< boost::shared_ptr< Callback >> Queue
virtual qi::Future< void > async(const boost::function< void()> &callback, qi::SteadyClockTimePoint tp)=0
auto operator()(Args &&...args) -> decltype(callInStrand(_func, _onFail, _strand, std::forward< Args >(args)...))
boost::condition_variable _processFinished
#define QI_ASSERT(expr__)
boost::weak_ptr< StrandPrivate > _strand
void cancel(boost::shared_ptr< Callback > cbStruct)
qi::Future< T > makeFutureError(const std::string &error)
Helper function to return a future with the error set.
WrapInStrand(F f, boost::weak_ptr< StrandPrivate > strand, boost::function< void()> onFail)
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
bool isInThisContext() override
return true if the current thread is in this context
qi::ExecutionContext & _eventLoop
void postImpl(boost::function< void()> callback) override
static const bool is_async
auto operator()(Args &&...args) const -> decltype(callInStrand(_func, _onFail, _strand, std::forward< Args >(args)...))
Future< R > async(boost::function< R()> callback, uint64_t usDelay)
StrandPrivate(qi::ExecutionContext &eventLoop)
#define QI_API_DEPRECATED_MSG(msg__)
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
qi::Future< void > async(const boost::function< void()> &callback, qi::Duration delay) override
std::atomic< int > _processingThread
Future< void > asyncDelayImpl(boost::function< void()> cb, qi::Duration delay) override
void enqueue(boost::shared_ptr< Callback > cbStruct)
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)