Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Cannot Return Data From Task

Karim_N_
New Contributor I
656 Views

Hi,

This is a meaningless example for testing purposes.  I was just trying to figure out how to make a task populate a container passed by reference from another location.  I haven't had much luck...

#include "tbb/task.h"

#include <functional>
#include <random>

#define NUM_POINTS 100000


class TASK_generateRandomNumbers : public tbb::task
{
public:
   TASK_generateRandomNumbers(std::function<void(std::vector<double>)> fnc, std::vector<double>& numbers) : _fnc(fnc), _numbers(numbers) {}
   ~TASK_generateRandomNumbers() {};

   tbb::task* execute()
   {
      _fnc(_numbers);
      return nullptr;
   }

private:
   std::function<void(std::vector<double>)> _fnc;
   std::vector<double> _numbers;
};


class Manager
{
public:
   Manager() { _numbers.reserve(NUM_POINTS); }
   ~Manager() {}

   void GenerateNumbers()
   {
      auto fn = std::bind(&Manager::generateRandomNumbers, this, _numbers);
      TASK_generateRandomNumbers* t = new(tbb::task::allocate_root()) TASK_generateRandomNumbers(fn, _numbers);
      tbb::task::spawn_root_and_wait(*t);
   }

   auto GetNumbers() const { return _numbers; }

private:
   void generateRandomNumbers(std::vector<double>& numbers)
   {
      std::mt19937_64 gen;
      std::uniform_real_distribution<double> dis(0.0, 1000.0);

      for (size_t i = 0; i < NUM_POINTS; i++)
      {
         numbers.push_back(dis(gen));
      }
   }   
   
   std::vector<double> _numbers;
};


int main()
{
   Manager mgr;
   mgr.GenerateNumbers();
   auto numbers = mgr.GetNumbers();
}

 

I see the random numbers being generated and inserted into the vector but when the method returns, the vector in the task's execute method is empty.  

Is it possible to use tasks to populate a container that is passed around?

Thanks.

0 Kudos
1 Solution
Karim_N_
New Contributor I
656 Views

I forgot that if I want to pass a reference to std::bind, I need to use std::ref (line 35).

View solution in original post

0 Kudos
2 Replies
Karim_N_
New Contributor I
657 Views

I forgot that if I want to pass a reference to std::bind, I need to use std::ref (line 35).

0 Kudos
Alexei_K_Intel
Employee
656 Views

In addition, pay attention that TASK_generateRandomNumbers has its own copy of std::vector (it is not a reference). Moreover, any arguments passed to _fnc call are ignored because the bind does not use any placeholders. So the vector is always empty inside the task.

Regards,
Alex

0 Kudos
Reply