Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of elements containing std::threads

I've got a class Tester containing an std:thread object, and an std::vector of Tester. I understand that I can't copy threads, so the push_back is out of the question, but why emplace_back is not working? Where is the copy in my code?

#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <unistd.h>

class Tester
{
public:
    Tester(std::function<void(void)> func) : 
        th(func)
    {
    }

    ~Tester()
    {
        th.join()
    }

private:
    std::thread th;
};

std::vector<Tester> testers;

void InnerHelloWorld()
{
    std::cout << "Hello from the inner word!\n";
}

int main() {
    std::cout << "Hello World!\n";

    for(size_t i = 0 ; i < 4 ; i++)
    {
        testers.emplace_back(InnerHelloWorld);
    }

    sleep(1);

    return 0;
}
like image 495
ErniBrown Avatar asked Jul 27 '18 08:07

ErniBrown


People also ask

Are STD vectors thread safe?

const and Thread Safety Therefore all classes available from the standard, e.g. std::vector<>, can safely be accessed from multiple threads in the same manner.

Is std:: thread copyable?

std::thread::operator= thread objects cannot be copied (2).

How do you create a vector thread in C++?

Changing contents of vector of threadvecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4);

How do you find all the elements in a vector?

A simple solution to check if all elements of a vector are equal is using the std::adjacent_find function. It returns the first occurrence of adjacent elements that satisfies a binary predicate, or end of the range if no such pair is found.


1 Answers

Theres a couple of minor issues in your code

You missed the trailing semi-colon off of:

th.join()

But importantly, you need to give your class a move constructor - the default one is fine:

Tester(Tester&&) = default;

This is needed as when vectors resize themselves they need to move or copy their elements. A move constructor will generally be created for you but in your case having a custom destructor supresses it. See here.

This will let your code compile, but then it'll throw an exception at runtime. This is because you sometimes destruct from moved-from Testers which will call join on a moved from thread. Fortunately this is an easy fix:

~Tester()
 {
   if(th.joinable())
       th.join();
 }

Full working code:

#include <iostream>
#include <thread>
#include <vector>
#include <functional>

#include <unistd.h>

class Tester
{
  public:
  Tester(std::function<void(void)> func) : 
    th(func)
  {
  }

  ~Tester()
  {
    if(th.joinable())
        th.join();
  }

  Tester(Tester&&) = default;

  private:
  std::thread th;
};

std::vector<Tester> testers;

void InnerHelloWorld()
{
  std::cout << "Hello from the inner word!\n";
}

int main() {
  std::cout << "Hello World!\n";

  for(size_t i = 0 ; i < 4 ; i++)
  {
    testers.emplace_back(InnerHelloWorld);
  }

  sleep(1);

  return 0;
}
like image 67
Mike Vine Avatar answered Sep 18 '22 17:09

Mike Vine