Pointing to thread object from another object: dangerous? - c++

Suppose there are two objects both inherit from a thread parent class "utility thread that uses pthreads".
class Othread1: public thread
{
public:
start() { /* launch thread at 10 Hz */ };
end();
void setvar(float vr) {var2= vr } ;
protected :
float var1;
}
and
class Othread2: public thread
{
start() { /* launch the thread at 1000 Hz */ } ;
end();
float getvar() { return var2 } ;
protected :
float var2;
}
Is there a such thing where we can do this?
void threadManager(thread *th1, thread *th2)
{
float vtemp = th2->getvar();
th1->setvar(vtemp);
}
int main ()
{
thread th1;
thread th2;
threadManager(&th1,&th2);
return 0;
}
Is such interthread data use a safe thing to do? Or do I have to do queues with producer/consumer pattern to exchange the data?

I'm still not entirely sure what you are trying to do but here is an example that will hopefully help you.
If you want to read data in one thread that is concurrently written in another thread you need synchronization or you'll invoke undefined behavior. Whether there is much or little time between the “writing event” and the “reading event” is not important. As far as the language rules are concerned, everything that happens between two synchronization points is “simultaneous”.
The definitive rules for this can be found in § 1.10 [intro.multithreaded] of N4140, the final draft for the C++14 standard. But the language used there can be hard to decipher.
A more informal explanation can be found in § 41.2.4 of The C++ Programming Language (4th edition) by Bjarne Stroustrup.
Two threads have a data race if both can access a memory location simultaneously and at least one of their accesses is a write. Note that defining “simultaneously” precisely is not trivial. If two threads have a data race, no language guarantees hold: the behavior is undefined.
As far as I am concerned, I think that the “can” in the first sentence is bogus and should not be there but I'm quoting the book as-is.
The classic way of protecting mutual access is using mutices and locks. Since C++11 (and only since C++11, C++ has a definition of concurrency at all), the standard library provides std::mutex and std::lock_guard (both defined in the <mutex> header) for this purpose.
If you have simple types like integers, using locks is overkill, however. Modern hardware supports atomic operations on such simple types. The standard library provides the std::atomic class template for this (defined in the <atomic> header). You can use it on any trivially copyable types.
Here is a rather useless example where we have two threads that execute a function writer and reader respectively. The writer has a pseudo-random number generator and periodically asks it to produce a new random integer that it stores atomically in the global variable value. The reader periodically loads the value of value atomically and advances its own pseudo-random number generator until it catches up. A second global atomic variable done is used by the main thread to signal to the two threads when they should stop. Note that I have replaced your hertz with kilohertz so it is less boring to wait for the program to execute.
#include <atomic>
#include <chrono>
#include <random>
#include <thread>
namespace /* anonymous */
{
std::atomic<bool> done {};
std::atomic<int> value {};
void
writer(const std::chrono::microseconds period)
{
auto rndeng = std::default_random_engine {};
auto rnddst = std::uniform_int_distribution<int> {};
while (!done.load())
{
const auto next = rnddst(rndeng);
value.store(next);
std::this_thread::sleep_for(period);
}
}
void
reader(const std::chrono::microseconds period)
{
auto rndeng = std::default_random_engine {};
auto rnddst = std::uniform_int_distribution<int> {};
auto last = 0;
while (!done.load())
{
const auto next = value.load();
while (last != next)
last = rnddst(rndeng);
std::this_thread::sleep_for(period);
}
}
}
int
main()
{
using namespace std::chrono_literals;
std::thread writer_thread {writer, 100us}; // 10 kHz
std::thread reader_thread {reader, 10us}; // 100 kHz
std::this_thread::sleep_for(3s);
done.store(true);
writer_thread.join();
reader_thread.join();
}
If you have a modern GCC or Clang, you can (and probably should) compile your debug builds with the -fsanitize=thread switch. If you run a thusly compiled binary and it executes a data race, the special instrumentations added by the compiler will output a helpful error message. Try replacing the std::atomic<int> value in the above program with an ordinary int value and see what the tool will report.
If you don't have C++14 yet, you cannot use the literal suffixes but have to spell out std::chrono::microseconds {10} and so forth.

Related

Updating two atomic variables under a condition in C++

I want to update two atomic variables under an if condition and the if condition uses one of the atomic variable. I am not sure if both these atomic variables will be updated together or not.
I have a multithreaded code below. In "if(local > a1)" a1 is an atomic variable so will reading it in if condition be atomic across threads, In other words if thread t1 is at the if condition, will thread t2 wait for a1 to be updated by thread t1? Is it possible that a2 is updated by one thread and a1 is updated by another thread?
// constructing atomics
#include <iostream> // std::cout
#include <atomic> // std::atomic
#include <thread> // std::thread
#include <vector> // std::vector
std::atomic<int> a1{0};
std::atomic<int> a2{0};
void count1m (int id) {
double local = id;
double local2 = id*3;
*if(local > a1) {* // a1 is an atomic variable so will reading it in if condition be atomic across threads or not?
a1 = local;
a2 = local2;
}
};
int main ()
{
std::vector<std::thread> threads;
std::cout << "spawning 20 threads that count to 1 million...\n";
for (int i=20; i>=0; --i) {
threads.push_back(std::thread(count1m,i));
}
for (auto& th : threads) th.join();
cout << "a1 = " << a1 << endl;
}
I am not sure if both these atomic variables will be updated together or not.
Not.
Atomic means indivisible, in that writes to an atomic can't be read half-done, in an intermediate or incomplete state.
However, updates to one atomic aren't somehow batched with updates to another atomic. How could the compiler tell which updates were supposed to be batched like this?
If you have two atomic variables, you have two independent objects neither of which can individually be observed to have a part-written state. You can still read them both and see a state where another thread has updated one but not the other, even if the stores are adjacent in the code.
Possibilities are:
Just use a mutex.
You ruled this out in a comment, but I'm going to mention it for completeness and because it's by far the easiest way.
Pack both objects into a single atomic.
Note that a 128-bit object (large enough for two binary64 doubles) may have to use a mutex or similar synchronization primitive internally, if your platform doesn't have native 128-bit atomics. You can check with std::atomic<DoublePair>::is_lock_free() to find out (for a suitable struct DoublePair containing a pair of doubles).
Whether a non-lock-free atomic is acceptable under your mutex prohibition I cannot guess.
Concoct an elaborate lock-free synchronization protocol, such as:
storing the index into a circular array of DoublePair objects and atomically updating that (there are various schemes for this with multiple producers, but single producer is definitely simpler - and don't forget A-B-A protection)
using a raw futex, or a semaphore, or some other technically-not-a-mutex synchronization primitive that already exists
using atomics to write a spinlock (again not technically a mutex, but again I can't guess whether it's actually suitable for you)
The main issue is that you've said you're not allowed to use a mutex, but haven't said why. Does the code have to be lock-free? Wait-free? Does someone just really hate std::mutex but will accept any other synchronization primitive?
There are basically two ways to do this and they are different.
The first way is to create an atomic struct that will be updated at once. Note that with this approach there is a race condition where the comparison between local and aip.a1 might change before aip is updated.
struct IntPair {
int a1;
int a2;
};
std::atomic<IntPair> aip = IntPair{0,0};
void count1m (int id) {
double local = id;
double local2 = id*3;
if(local > aip.load().a1) {
aip = IntPair{int(local),int(local2)};
}
};
The second approach is to use a mutex to synchronize the entire section, like below. This will guarantee that no race condition occurs and everything is done atomically. We used a std::lock_guard for better safety rather than calling m.lock() and m.unlock() manually.
IntPair ip{0,0};
std::mutex m;
void count1m (int id) {
double local = id;
double local2 = id*3;
std::lock_guard<std::mutex> g(m);
if(local > ip.a1) {
ip = IntPair{int(local),int(local2)};
}
};

Is this a valid binary mutex implementation?

I'm not really sure if this types of questions are frowned upon here, but it is the first place I come for when I have a question in mind, so, here we go.
I have a std::vector<T> v that I use to store data. In thread t1, there is a data generator and data insertion can happen at any time. On the other hand, in thread t2, at arbitrary times, I need to search v and access and return an element from it. Deletions, swaps etc. are guaranteed to not happen on v until both t1 and t2 join on main thread.
Without any thread-safety measures, code exits with SIGABRT. I first used std::mutex and std::lock_guard and succeeded, however the number of lock/unlocks are in millions and I wish to speed things up a bit. So I tried to implement the following system:
#include <atomic>
#include <cassert>
#include <thread>
// Mutex-like thingy begin
class MyMutex
{
private:
std::atomic<bool> modifyLockRequest;
std::atomic<bool> accessLockRequest;
std::atomic<bool> accessLock;
public:
MyMutex() :
modifyLockRequest(false),
accessLockRequest(false),
accessLock(false) {}
void acquireModifyLock() {
assert(!modifyLockRequest);
modifyLockRequest = true;
while( accessLockRequest && accessLock ) {
std::this_thread::yield();
}
}
void releaseModifyLock() {
assert(modifyLockRequest);
modifyLockRequest = false;
}
void acquireAccessLock() {
assert(!accessLockRequest);
accessLockRequest = true;
while (modifyLockRequest) {
std::this_thread::yield();
}
accessLock = true;
}
void releaseAccessLock() {
assert(accessLockRequest);
accessLock = false;
accessLockRequest = false;
}
};
MyMutex myMutex;
Then I use this by
myMutex.acquireModifyLock();
// Do insertion/deletion etc. on `v`
myMutex.releaseModifyLock();
and
myMutex.acquireAccessLock();
// Do stuff with `v[i]`
myMutex.releaseAccessLock();
My rationale was to have 2 Boolean flags to alert whichever thread is trying to get a lock, and to have a third flag to break off cases where the two threads try to acquire a lock at the same time.
This code seems to work well in about 1/8th time of std::mutex and std::lock_guard duo, however, my question is, is this solution guaranteed to always work in my case where there is only 2 threads?
Using std::atomic_flag to implement a spin lock worked well for the last 3 months. Also, since my implementation didn't have an atomic test-and-set mechanism, I'd say, NO, it's not a valid (thread-safe) implementation. Thanks to Igor Tandetnik for his suggestion.

Why the following program does not mix the output when mutex is not used?

I have made multiple runs of the program. I do not see that the output is incorrect, even though I do not use the mutex. My goal is to demonstrate the need of a mutex. My thinking is that different threads with different "num" values will be mixed.
Is it because the objects are different?
using VecI = std::vector<int>;
class UseMutexInClassMethod {
mutex m;
public:
VecI compute(int num, VecI veci)
{
VecI v;
num = 2 * num -1;
for (auto &x:veci) {
v.emplace_back(pow(x,num));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return v;
}
};
void TestUseMutexInClassMethodUsingAsync()
{
const int nthreads = 5;
UseMutexInClassMethod useMutexInClassMethod;
VecI vec{ 1,2,3,4,5 };
std::vector<std::future<VecI>> futures(nthreads);
std::vector<VecI> outputs(nthreads);
for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
futures[i] = std::async(&UseMutexInClassMethod::compute,
&useMutexInClassMethod,
i,vec
);
}
for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
outputs[i] = futures[i].get();
for (auto& x : outputs[i])
cout << x << " ";
cout << endl;
}
}
If you want an example that does fail with a high degree of certainty you can look at the below. It sets up a variable called accumulator to be shared by reference to all the futures. This is what is missing in your example. You are not actually sharing any memory. Make sure you understand the difference between passing by reference and passing by value.
#include <vector>
#include <memory>
#include <thread>
#include <future>
#include <iostream>
#include <cmath>
#include <mutex>
struct UseMutex{
int compute(std::mutex & m, int & num)
{
for(size_t j = 0;j<1000;j++)
{
///////////////////////
// CRITICAL SECTIION //
///////////////////////
// this code currently doesn't trigger the exception
// because of the lock on the mutex. If you comment
// out the single line below then the exception *may*
// get called.
std::scoped_lock lock{m};
num++;
std::this_thread::sleep_for(std::chrono::nanoseconds(1));
num++;
if(num%2!=0)
throw std::runtime_error("bad things happened");
}
return 0;
}
};
template <typename T> struct F;
void TestUseMutexInClassMethodUsingAsync()
{
const int nthreads = 16;
int accumulator=0;
std::mutex m;
std::vector<UseMutex> vs{nthreads};
std::vector<std::future<int>> futures(nthreads);
for (auto i = 0; i < nthreads; ++i) {
futures[i]= std::async([&,i](){return vs[i].compute(m,accumulator);});
}
for(auto i = 0; i < nthreads; ++i){
futures[i].get();
}
}
int main(){
TestUseMutexInClassMethodUsingAsync();
}
You can comment / uncomment the line
std::scoped_lock lock{m};
which protects the increment of the shared variable num. The rule for this mini program is that at the line
if(num%2!=0)
throw std::runtime_error("bad things happened");
num should be a multiple of two. But as multiple threads are accessing this variable without a lock you can't guarantee this. However if you add a lock around the double increment and test then you can be sure no other thread is accessing this memory during the duration of the increment and test.
Failing
https://godbolt.org/z/sojcs1WK9
Passing
https://godbolt.org/z/sGdx3x3q3
Of course the failing one is not guaranteed to fail but I've set it up so that it has a high probability of failing.
Notes
[&,i](){return vs[i].compute(m,accumulator);};
is a lambda or inline function. The notation [&,i] means it captures everything by reference except i which it captures by value. This is important because i changes on each loop iteration and we want each future to get a unique value of i
Is it because the objects are different?
Yes.
Your code is actually perfectly thread safe, no need for mutex here. You never share any state between threads except for copying vec from TestUseMutexInClassMethodUsingAsync to compute by std::async (and copying is thread-safe) and moving computation result from compute's return value to futures[i].get()'s return value. .get() is also thread-safe: it blocks until the compute() method terminates and then returns its computation result.
It's actually nice to see that even a deliberate attempt to get a race condition failed :)
You probably have to fully redo your example to demonstrate is how simultaneous* access to a shared object breaks things. Get rid of std::async and std::future, use simple std::thread with capture-by-reference, remove sleep_for (so both threads do a lot of operations instead of one per second), significantly increase number of operations and you will get a visible race. It may look like a crash, though.
* - yes, I'm aware that "wall-clock simulateneous access" does not exist in multithreaded systems, strictly speaking. However, it helps getting a rough idea of where to look for visible race conditions for demonstration purposes.
Comments have called out the fact that just not protecting a critical section does not guarantee that the risked behavior actually occurs.
That also applies for multiple runs, because while you are not allowed to test a few times and then rely on the repeatedly observed behavior, it is likely that optimization mechanisms cause a likely enough reoccurring observation as to be perceived has reproducible.
If you intend to demonstrate the need for synchronization you need to employ synchronization to poise things to a near guaranteed misbehavior of observable lack of protection.
Allow me to only outline a sequence for that, with a few assumptions on scheduling mechanisms (this is based on a rather simple, single core, priority based scheduling environment I have encountered in an embedded environment I was using professionally), just to give an insight with a simplified example:
start a lower priority context.
optionally set up proper protection before entering the critical section
start critical section, e.g. by outputting the first half of to-be-continuous output
asynchronously trigger a higher priority context, which is doing that which can violate your critical section, e.g. outputs something which should not be in the middle of the two-part output of the critical section
(in protected case the other context is not executed, in spite of being higher priority)
(in unprotected case the other context is now executed, because of being higher priority)
end critical section, e.g. by outputting the second half of the to-be-continuous output
optionally remove the protection after leaving the critical section
(in protected case the other context is now executed, now that it is allowed)
(in unprotected case the other context was already executed)
Note:
I am using the term "critical section" with the meaning of a piece of code which is vulnerable to being interrupted/preempted/descheduled by another piece of code or another execution of the same code. Specifically for me a critical section can exist without applied protection, though that is not a good thing. I state this explicitly because I am aware of the term being used with the meaning "piece of code inside applied protection/synchronization". I disagree but I accept that the term is used differently and requires clarification in case of potential conflicts.

C++ constexpr thread_local id

Is there any way to get a different value in a constexpr thread_local variable for every thread?
constexpr thread_local someType someVar = ......;
It seems like constexpr thread_local is supported but the thread_local indicator doesnt seem to do anything in this case.
If you think about your question, you yourself can see why this is not possible.
What is constexpr?
According to the informal standard site cppreference:
The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.
The compiler has to resolve the value at compile time and this value should not change throughout the execution of the program.
Thread-local storage
A thread, on the contrary, is a run-time concept. C++11 introduced the thread concept into the language, and thus you could say that a compiler can be "aware" of the thread concept.
But, the compiler can't always predict if a thread is going to be executed (Maybe you run the thread only upon specific configuration), or how many instances are going to be spawn, etc.
Possible implementation
Instead of trying to enforce access to a specific module/method to a single thread using hacks and tricks, why not use a very primitive feature of the language?
You could just as well implement this using simple encapsulation. Just make sure that the only object that "sees" this method you are trying to protect is the thread object itself, for example:
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
class SpecialWorker
{
public:
void start()
{
m_thread = std::move(std::thread(&SpecialWorker::run, this));
}
void join()
{
m_thread.join();
}
protected:
virtual void run() { protectedTask(); }
private:
void protectedTask()
{
cout << "PROTECT ME!" << endl;
}
std::thread m_thread;
};
int main(int argc, char ** argv)
{
SpecialWorker a;
a.start();
a.join();
return 0;
}
Please note that this example is lacking in error handling and is not production grade code! Make sure to refine it if you intend to use it.

Atomic Operations in C++

I have a set of C++ functions:
funcB(){};
funcC(){};
funcA()
{
funcB();
funcC();
}
Now I want to make funcA atomic, ie funcB and funcC calls inside funcA should be executed atomically. Is there any way to achieve this?
One way you can accomplish this is to use the new (C++11) features std::mutex and std::lock_guard.
For each protected resource, you instantiate a single global std::mutex; each thread then locks that mutex, as it requires, by the creation of a std::lock_guard:
#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
// A single mutex, shared by all threads. It is initialized
// into the "unlocked" state
std::mutex m;
void funcB() {
std::cout << "Hello ";
}
void funcC() {
std::cout << "World." << std::endl;
}
void funcA(int i) {
// The creation of lock_guard locks the mutex
// for the lifetime of the lock_guard
std::lock_guard<std::mutex> l(m);
// Now only a single thread can run this code
std::cout << i << ": ";
funcB();
funcC();
// As we exit this scope, the lock_guard is destroyed,
// the mutex is unlocked, and another thread is allowed to run
}
int main () {
std::vector<std::thread> vt;
// Create and launch a bunch of threads
for(int i =0; i < 10; i++)
vt.push_back(std::thread(funcA, i));
// Wait for all of them to complete
for(auto& t : vt)
t.join();
}
Notes:
In your example some code unrelated to funcA could invoke either funcB or funcC without honoring the lock that funcA set.
Depending upon how your program is structured, you may want to manage the lifetime of the mutex differently. As an example, it might want to be a class member of the class that includes funcA.
In general, NO. Atomic operations are very precisely defined. What you want is a semaphore or a mutex.
If you are using GCC 4.7 than you can use the new Transactional Memory feature to do the following:
Transactional memory is intended to make programming with threads simpler, in particular synchronizing access to data shared between several threads using transactions. As with databases, a transaction is a unit of work that either completes in its entirety or has no effect at all (i.e., transactions execute atomically). Further, transactions are isolated from each other such that each transaction sees a consistent view of memory.
Currently, transactions are only supported in C++ and C in the form of transaction statements, transaction expressions, and function transactions. In the following example, both a and b will be read and the difference will be written to c, all atomically and isolated from other transactions:
__transaction_atomic { c = a - b; }
Therefore, another thread can use the following code to concurrently update b without ever causing c to hold a negative value (and without having to use other synchronization constructs such as locks or C++11 atomics):
__transaction_atomic { if (a > b) b++; }
The precise semantics of transactions are defined in terms of the C++11/C1X memory model (see below for a link to the specification). Roughly, transactions provide synchronization guarantees that are similar to what would be guaranteed when using a single global lock as a guard for all transactions. Note that like other synchronization constructs in C/C++, transactions rely on a data-race-free program (e.g., a nontransactional write that is concurrent with a transactional read to the same memory location is a data race).
More info: http://gcc.gnu.org/wiki/TransactionalMemory