CPP2019SSF28: Unterschied zwischen den Versionen

Aus Verteilte Systeme - Wiki
Zur Navigation springen Zur Suche springen
 
(6 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 5: Zeile 5:
   
 
=== Syntax ===
 
=== Syntax ===
 
<code>thread_local varType varName;</code>
 
<source lang="cpp">
 
<source lang="cpp">
thread_local varType varName;
 
 
thread_local unsigned int counter;
 
thread_local unsigned int counter;
 
thread_local std::string s = "getting schwifty";
 
thread_local std::string s = "getting schwifty";
Zeile 23: Zeile 23:
   
 
=== Vorherige Lösungsansätze ===
 
=== Vorherige Lösungsansätze ===
  +
C++98 does not have support for concurrency. However, there are some very useful APIs that enable threading in c++98 and the use of <code>thread_local</code>.<br /> For example: [https://www.boost.org/doc/libs/1_35_0/doc/html/thread/thread_local_storage.html boost c++ Libraries]
   
 
=== Warnhinweise ===
 
=== Warnhinweise ===
 
*Thead Local variables can't be acceded by other threads, UNLESS the programmer gives a pointer to the thread local variable.
 
*Thead Local variables can't be acceded by other threads, UNLESS the programmer gives a pointer to the thread local variable.
*Thread local cannot be used on function declarations or definitions.
 
   
 
=== Code-Beispiele ===
 
=== Code-Beispiele ===
  +
<source lang="cpp">
  +
#include <iostream>
  +
#include <thread>
  +
#include <string>
  +
#include <mutex>
  +
  +
static std::mutex m;
  +
std::string g_error_log = "Error : ";
  +
thread_local std::string tl_error_log = "Error: ";
  +
  +
void globalErrorLog(std::string const &s2)
  +
{
  +
g_error_log += s2;
  +
std::unique_lock<std::mutex> lock(m); //protect std::cout
  +
std::cout << g_error_log << std::endl;
  +
}
  +
  +
void threadLocalErrorLog(std::string const &s2)
  +
{
  +
tl_error_log += s2;
  +
std::unique_lock<std::mutex> lock(m); //protect std::cout
  +
std::cout << tl_error_log << std::endl;
  +
}
  +
  +
int main()
  +
{
  +
std::thread t1(globalErrorLog, "t1");
  +
std::thread t2(globalErrorLog, "t2");
  +
std::thread t3(globalErrorLog, "t3");
  +
  +
t1.join();
  +
t2.join();
  +
t3.join();
  +
  +
return 0;
  +
}
  +
  +
</source>
  +
Posible output: <br />
  +
Error : t1 <br />
  +
Error : t1t2t3 <br />
  +
Error : t1t2t3 <br />
  +
  +
  +
Now we pass to the threads the function that uses the <code>thread_local</code> variable to store the errors logs:
  +
<source lang="cpp">
  +
...
  +
std::thread t1(threadLocalErrorLog, "t1");
  +
std::thread t2(threadLocalErrorLog, "t2");
  +
std::thread t3(threadLocalErrorLog, "t3");
  +
...
  +
</source>
  +
Posible output: <br />
  +
Error : t1 <br />
  +
Error : t2 <br />
  +
Error : t3 <br />
  +
Note that the use of <code>thread_local</code> only avoid data races, if we want synchronization then we should use Locks and/or Condition Variables.

Aktuelle Version vom 20. August 2019, 18:04 Uhr

Feature: thread_local

  • Eingeführt in: C++11

Syntax

thread_local varType varName;

thread_local unsigned int counter;
thread_local std::string s = "getting schwifty";
...

Use Cases

thread_local Entities have thread storage duration. This mean that every single thread in a program has its own copy of its thread_local Entity. thread_local Entities are implicit static and get destroyed upon thread exit.

The best way to avoid data races is not sharing the data between threads. By using thread_local variables, each thread will have its own copy of the data, and this data can only be written or reading by its own thread.

Motivation für die Einführung

Implementing the thread local storage method in c++ 98 is only possible by using third party libraries. With C++11 and std::thread we don't have to rely on third parties libraries, this make our code more portable.

Vorherige Lösungsansätze

C++98 does not have support for concurrency. However, there are some very useful APIs that enable threading in c++98 and the use of thread_local.
For example: boost c++ Libraries

Warnhinweise

  • Thead Local variables can't be acceded by other threads, UNLESS the programmer gives a pointer to the thread local variable.

Code-Beispiele

#include <iostream>
#include <thread>
#include <string>
#include <mutex>

static std::mutex m;
std::string g_error_log = "Error : ";
thread_local std::string tl_error_log = "Error: ";

void globalErrorLog(std::string const &s2)
{
    g_error_log += s2;
    std::unique_lock<std::mutex> lock(m); //protect std::cout
    std::cout << g_error_log << std::endl;
}

void threadLocalErrorLog(std::string const &s2)
{
    tl_error_log += s2;
    std::unique_lock<std::mutex> lock(m); //protect std::cout
    std::cout << tl_error_log << std::endl;
}

int main()
{
    std::thread t1(globalErrorLog, "t1");
    std::thread t2(globalErrorLog, "t2");
    std::thread t3(globalErrorLog, "t3");
    
    t1.join();
    t2.join();
    t3.join();

    return 0;
}

Posible output:
Error : t1
Error : t1t2t3
Error : t1t2t3


Now we pass to the threads the function that uses the thread_local variable to store the errors logs:

...
    std::thread t1(threadLocalErrorLog, "t1");
    std::thread t2(threadLocalErrorLog, "t2");
    std::thread t3(threadLocalErrorLog, "t3");
...

Posible output:
Error : t1
Error : t2
Error : t3
Note that the use of thread_local only avoid data races, if we want synchronization then we should use Locks and/or Condition Variables.