4

I originally tried this answer, but got compilation errors when about assigning the value of 'bind' to 'int' (the return type of my function, in this case). I'm reasonably unfamiliar with boost, but trying to improve. Any suggestions on how to make the below compile and work correctly on VC10?

template <class T, class F>
void ExecuteWithReturn(const F &_bind, long sleep, T & ret)
{
    ret = _bind();
}

template <class T, class F>
bool TryExecuteFor(const F &_bind, long sleep, T & ret) {
    boost::thread thrd(ExecuteWithReturn<T, F>, _bind, boost::ref(ret));
    return thrd.timed_join(boost::posix_time::milliseconds(sleep));
}

The result of this is is a compilation error:

error C2198: 'void (__cdecl *)(const boost::_bi::bind_t &,long,T &)' : too few arguments for call with 1> [ 1>
R=long, 1> F=long (__cdecl *)(const wchar_t *,const wchar_t *,wchar_t **), 1>
L=boost::_bi::list3,boost::_bi::value,boost::_bi::value>, 1> T=int 1> ]

and the usage of this function is expected to be:

int ret;
if(!TryExecuteFor(boost::bind(g_pMyFunc, someParam, anotherParam), 10000, ret))
{
   ...
}

Edit: Thanks to Fraser for pointing out the glaring issue with ExecuteWithReturn; that combined with another fix made the code work. After running, I realized a very likely problem that the variables passed in (including the return value) may go out of scope before the function returns if the thread is orphaned. I can't do much about the bound functor's parameters, but to mitigate the potential issue, I changed the return value to be a shared_ptr. Current working implementation is as follows:

template <class F>
void ExecuteWithReturn(const F &_bind, boost::shared_ptr<decltype(_bind())> _ret)
{
    *_ret = _bind();
}

template <class F>
bool TryExecuteFor(const F &_bind, long _timeout, boost::shared_ptr<decltype(_bind())> _ret) {
    boost::thread thrd(ExecuteWithReturn<F>, boost::ref(_bind), _ret);
    return thrd.timed_join(boost::posix_time::milliseconds(_timeout));
}

nice easy TODO would be an overload for functions that don't return a value, but after basic testing it works as expected.

Community
  • 1
  • 1
Rollie
  • 4,391
  • 3
  • 33
  • 55

1 Answers1

4

You simply have an extra argument in ExecuteWithReturn

The function should probably be changed to

void ExecuteWithReturn(const F &_bind, T & ret)

or else you need to pass the sleep parameter where you call ExecuteWithReturn:

boost::thread thrd(ExecuteWithReturn<T, F>, _bind, sleep, boost::ref(ret));
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • Hmmm. I feel kinda silly for not noticing that. It didn't actually fix the problem; I was left with 'cannot convert parameter 1 from long to funcType', which went away when I replaced the `_bind' in `boost::thread thrd(ExecuteWithReturn, _bind, boost::ref(ret));` with `boost::ref(_bind)`. – Rollie Mar 19 '13 at 16:44