Thread Arguments

Contents[Show]

A thread gets its data by copy or by reference. By default, you should use by copy. Why? In case your thread gets its data by reference, you have to be extremely careful about the lifetime of the arguments.

 

Thread arguments

A thread is a variadic template. So it can get an arbitrary number of arguments.

But now to the difference between getting the argument by copy or by reference.

 

std::string s{"C++11"}

std::thread t([=]{ std::cout << s << std::endl;});
t.join();

std::thread t2([&]{ std::cout << s << std::endl;});
t2.detach()

 

Precisely said, it is not the thread that gets the arguments in this example, but the lambda function. But that makes no difference for my argumentation. So the first thread t1 gets its data per copy ([=]), and the second thread t2 gets its data by reference ([&]).

What dangers are hidden in these lines? Thread t2 gets its string s by reference and is afterward detached from the lifetime of its creator. On the one hand, the lifetime of the string is bound to the lifetime of the invocation context, and on the other hand, the lifetime of the global object std::cout is bound to the lifetime of the main thread. So it may happen that the lifetime of the string s or the lifetime of std::cout is shorter than the lifetime of the thread t2. Now we are deep in the area of undefined behavior.

 

Rainer D 6 P2 540x540Modernes C++ Mentoring

Be part of my mentoring programs:

 

 

 

 

Do you want to stay informed about my mentoring programs: Subscribe via E-Mail.

Not convinced? Let's have a closer look, what undefined behavior may look like.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// threadArguments.cpp

#include <chrono>
#include <iostream>
#include <thread>

class Sleeper{
  public:
    Sleeper(int& i_):i{i_}{};
    void operator() (int k){
      for (unsigned int j= 0; j <= 5; ++j){
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        i += k;
      }
      std::cout << std::this_thread::get_id() << std::endl;
    }
  private:
    int& i;
};


int main(){

  std::cout << std::endl;

  int valSleeper= 1000;
  std::thread t(Sleeper(valSleeper),5);
  t.detach();
  std::cout << "valSleeper = " << valSleeper << std::endl;

  std::cout << std::endl;

}

 

The question is, which value valSleeper has in line 26 valSleeper as a global variable? The thread t gets as a work package a function object of type Sleeper, the variable valSleeper, and the number 5 (line 27). The crucial observation is that the thread gets valSleeper by reference (line 9) and will be detached from the lifetime of the main thread (line 28). Then it will execute the call operator of the function object (lines 10 - 16). This method counts from 0 to 5, sleeps in each iteration 1/10 of a second, and increments i by k. In the end, it displays its ID on the screen. Following Adam Riese (a German proverb), the result must be 1000 +  6 * 5 = 1030.

But what happened? Something is going wrong. 

Sleeper

There are two issues. On the one hand, valSleeper is 1000; on the other hand, the ID is missing on the console. So, that is undefined behavior. The reason is that the lifetime of the main thread ends before the child thread has performed its calculation or written its ID to std::cout.

In case the main thread waits via t.join() until this child thread is done with its work, we get the expected result.

 

int main(){

  std::cout << std::endl;

  int valSleeper= 1000;
  std::thread t(Sleeper(valSleeper),5);
  t.join();
  std::cout << "valSleeper = " << valSleeper << std::endl;

  std::cout << std::endl;

}

 

Sleeper2

What's next?

Thinking about the lifetime of the threads is by far not the only issue with threads. Both threads, the main thread and the child thread, share two objects. That is std::cout and the variable valSleeper. Now, I described the classical recipe for a data race or - to say it differently - for undefined behavior. In the next post, I will deal with shared variables between threads. (Proofreader Arne Mertz, Alexey Elymanov)

 

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, and Rob North.

 

Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, and Slavko Radman.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

My special thanks to PVS-Studio PVC Logo

 

My special thanks to Tipi.build tipi.build logo

 

My special thanks to Take Up Code TakeUpCode 450 60

 

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ - The Core Language
  • C++ - The Standard Library
  • C++ - Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++

New

  • Clean Code with Modern C++
  • C++20

Contact Me

Modernes C++,

RainerGrimmDunkelBlauSmall

Comments   

0 #1 Text Your Ex Back 2016-10-30 23:23
This information is worth everyone's attention. When can I find
out more?
Quote
0 #2 شركة تداول سعودية 2018-05-30 03:41
I'd like to thank you for the efforts you have put in writing this website.
I'm hoping to view the same high-grade content by you
later on as well. In fact, your creative writing abilities has motivated me to get my own website now ;)
Quote

Stay Informed about my Mentoring

 

Mentoring

English Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Course: The All-in-One Guide to C++20

Course: Master Software Design Patterns and Architecture in C++

Subscribe to the newsletter (+ pdf bundle)

All tags

Blog archive

Source Code

Visitors

Today 3646

Yesterday 5555

Week 33854

Month 55528

All 12133737

Currently are 187 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments