5 Aralık 2019 Perşembe

std::thread Constructor Metodu ve Arg Parametresi

constructor - f parametresi + Arg parametresi
f parametresi yani functor için açıklama şöyle.
all state in the thread before the new thread is spawned is visible to the spawned thread.
f parametresinin overload halini seçmek
Örnek
Elimizde overload edilmiş iki metod olsun.
int do_calculation(int x)    
{    
  std::cout<<x;    
}    

float do_calculation(float x)    
{    
  std::cout<<x;    
}    
Overload için şöyle yaparız.
std::thread t1(static_cast<int(*)(int)>(do_calculation),20);    
std::thread t2(static_cast<float(*)(float)>(do_calculation),200.0f);  
Arg Parametresi İçin Kurallar

Açıklaması şöyle.
The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).
Bu constructor'ın imzası variadic arguments alacak şekilde tanımlı. Dolayısıyla içeride muhtemelen şöyle kullanılıyor.
template <typename Function, typename... Arg>
void call_with_any(Function f, Arg&&... args) {
    f(std::forward<Arg>(args)...);
}
Ya da şöyle.
template <typename Function, typename... Arg>
void call_with_any(Function&& f, Arg&&... args) {
    std::forward<Function>(f)(std::forward<Arg>(args)...);
}
Argument'ın copy constructor metodu yoksa
Açıklaması şöyle.
The constructor of std::thread first creates a copy of its first argument (by decay_copy) — that is where copy constructor is called. (Note that in case of an rvalue argument, such as thread t1{std::move(t)}; or thread t1{tFunc{}};, move constructor would be called instead.)

The result of decay_copy is a temporary that resides on the stack. However, since decay_copy is performed by a calling thread, this temporary resides on its stack and is destroyed at the end of std::thread::thread constructor. Consequently, the temporary itself cannot be used by a new created thread directly.
Örnek
Elimizde şöyle bir kod olsun.
class tFunc{
  
public:
  tFunc(){
    cout<<"Constructed : "<<this<<endl;
  }
  ~tFunc(){
    cout<<"Destroyed : "<<this<<endl;
  }
  void operator()(){
    cout<<"Thread running at : "<<x<<endl;
  }
};

int main()
{
  tFunc t;
  thread t1(t);
  if(t1.joinable())
  {
    cout<<"Thread is joining..."<<endl;
    t1.join();
  }
  return 0;
}
Çıktı olarak şunu alırız. Copy constructor olmadığı için temporary nesnenin yaratıldığın görmeyiz ancak yok olduğunu görürüz.
Constructed : 0x7ffe27d1b0a4 //main thread
Destroyed : 0x7ffe27d1b06c //Temporary
Thread is joining...
Thread running at : 11
Destroyed : 0x2029c28  //thread
x : 1
Destroyed : 0x7ffe27d1b0a4 //main thread
Argument'ın copy constructor metodu varsa
Örnek
Çıktı olarak şunu alırız.
Constructed : 0x104055020 //main thread
Copy constructed : 0x104055160 (source=0x104055020) //temporary on main thread
Copy constructed : 0x602000008a38 (source=0x104055160) //copy on thread
Destroyed : 0x104055160 //temporary on main thread destroyed
Thread running at : 11
Destroyed : 0x602000008a38 //thread object is destroyed
Thread is joining...
x : 1
Destroyed : 0x104055020 //main thread object is destroyed
Argument'ın copy ve move constructor metodları varsa
Örnek
Çıktı olarak şunu alırız.
Constructed : 0x104057020 /main thread
Copy constructed : 0x104057160 (source=0x104057020) //temporary on main thread
Move constructed : 0x602000008a38 (source=0x104057160) //move on thread
Destroyed : 0x104057160 //temporay on main thread destroyed
Thread running at : 11
Destroyed : 0x602000008a38 //thread object is destroyed
Thread is joining...
x : 1
Destroyed : 0x104057020 //main thread object is destroyed
Argument'ı std::ref ile geçersek
Örnek
Çıktı olarak şunu alırız.
Constructed : 0x104057020 //main therad
Thread is joining...
Thread running at : 11
x : 11
Destroyed : 0x104057020 //main thread object is destroyed
Örnek
Foo tipinden olan a nesnesinin bar metodunu işletmek ve m parametresini ref. olarak geçmek için C++17 ile şöyle yaparız.
class foo
{
public:
  void bar( std::mutex &m )
  {
    std::lock_guard<std::mutex> lock( m );
    std::cout << "Threading this function works!" << std::endl;
  }
};


int main()
{
  foo a;
  std::mutex m;
  std::thread bar_thread( &foo::bar, std::ref( a ), std::ref( m ) );
  bar_thread.join();
  return 0;
}
Örnek
std::ref çalışmıyorsa C++11 ile şöyle yaparız.
std::thread bar_thread( &foo::bar, std::addressof( a ), std::ref( m ) );
Argument'ı rvalue kullanırsak
Örnek
Çıktı olarak şunu alırız.
Constructed : 0x104055040 //rvalue
Move constructed : 0x104055160 (source=0x104055040) //temporary on main thread
Move constructed : 0x602000008a38 (source=0x104055160) //move on thread
Destroyed : 0x104055160 //temporary on main thread destroyed
Destroyed : 0x104055040 //rvalue is destroyed
Thread is joining...
Thread running at : 11
Destroyed : 0x602000008a38 //thread object is destroyed

Hiç yorum yok:

Yorum Gönder