0

Today, I'm trying to make a task manager for a personnal project.

I wrote the following method :

template<class Callback, class... Args>
void ThreadManager::AddTaskToRun(Callback&& fun,     Args&&... args)
{
task_handle<function<void()>> task = make_task([&]()
{
    fun(forward<Args>(args)...);
});

/* Another code */
}

And I call it with the following sample :

void Test(int taskId)
{
wcout << "Hello " << taskId << endl;
}


threadManager.AddTaskToRun(Test, 1);
threadManager.AddTaskToRun(Test, 2);
threadManager.AddTaskToRun(Test, 3);

And

int x = 0;
threadManager.AddTaskToRun(Test, x);
x++;
threadManager.AddTaskToRun(Test, x);
x++;
threadManager.AddTaskToRun(Test, x);

The problem is that, in Debug mode (with Visual Studio 2013), I have the following result :

Hello 1 (first test)
Hello 2
Hello 3

And

Hello 2 (second test, with a variable in argument)
Hello 2
Hello 2

The second test has a big problem no? :-)

And if I test in Release mode :

Hello 3 Hello 3 Hello 3

And

Hello 2 Hello 2 Hello 2

Well. It's strange I think. I've search on the web but found nothing. I just seen that if I run my function outside the "make_task" or "create_task" (PPL), all results are good :

template<class Callback, class... Args>
void ThreadManager::AddTaskToRun(Callback&& fun,     Args&&... args)
{
fun(forward<Args>(args)...);

/* Another code */
}

Anyone have an idea to help me?

Thank you in advance

user2864740
  • 54,112
  • 10
  • 112
  • 187
Etienne Baudoux
  • 171
  • 2
  • 13
  • 2
    You're using a shared resource (`x`) in a multi-threaded application, without attempting to do any type of synchronization. You're running into a race condition. An easy fix would be to create a copy of `x` and pass that in, so you aren't changing the value of x while your threads are trying to use it. – Red Alert Mar 10 '14 at 22:32
  • Thank you for your answer. How can I do it? Because if I use make_task([=] (for a copy) instead of make_task([&](), it doesn't build. (Sorry, I'm beginner in C++, started to learn it 2 days ago). Thank you in advance :-) – Etienne Baudoux Mar 11 '14 at 07:48

1 Answers1

0

I've found the solution after several hours of test. I've search in thread.h file, and discover in their constructor _Decay_copy, and tried to use it in my method :

template<class Callback, class... Args>
void ThreadManager::AddTaskToRun(Callback&& fun,     Args&&... args)
{
task_handle<function<void(void)>> task = bind(_Decay_copy(forward<Callback>(fun)), _Decay_copy(forward<Args>(args))...);

/* Another code */
}

By using this task with task_group, it works fine.

Thank you :-)

Etienne Baudoux
  • 171
  • 2
  • 13