Parallelism with std::async launch not happening , same thread is executing - multithreading

I am trying to exploit the std::async functionality to do parallelism. But if i print the thread id, it's always returning the same value. Semms like it's running this code sequentially. Am i missing something?
Code :
int main()
{
bool check = false;
auto func = [&](int i)
{
std::cout<<" i : "<<i<<" thread_id : "<<std::this_thread::get_id()<<" ";
check = true;
}
for(int j=0;j<10;j++)
{
std::async(std::async::launch, func, j);
}
std::cout<<" check : "<<check<<" ";
return 0;
}
Result :
i : 0 thread_id : 47263726
i : 1 thread_id : 47263726
i : 2 thread_id : 47263726
i : 3 thread_id : 47263726
i : 4 thread_id : 47263726
.
.
.

As per note here:
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code [...] synchronous
This is exactly your case. You need to take care of the async return.
#include <vector>
#include <future>
#include <iostream>
#include <chrono>
#include <mutex>
int main()
{
auto func = [](int i) {
std::cout<<" i : "<<i<<" thread_id : "<<std::this_thread::get_id()<<"\n";
};
using Handle = std::future<void>; // pretty hard to be figured out automatically
// from lambda, but your function "returns" void
std::vector<Handle> handles;
for(int j=0;j<10;j++)
{
handles.push_back(std::async(std::launch::async, func, j));
//result of std::async is implicitly moved onto the vector
}
return 0;
}
Output:
i : 6 thread_id : 47713265002240
i : 7 thread_id : 47713267103488
i : 8 thread_id : 47713269204736
i : 9 thread_id : 47713271305984
i : 5 thread_id : 47713262900992
i : 4 thread_id : 47713260799744
i : 3 thread_id : 47713258698496
i : 2 thread_id : 47713256597248
i : 1 thread_id : 47713254496000
i : 0 thread_id : 47713252394752

std::async returns a temporary future object, which is then immediately destroyed. std::future destructor is allowed to block in this specific case, waiting for the asynchronous operation to complete. This is likely what you observe - func calls do run sequentially, and just happen to get assigned to the same worker thread.

Related

How should you use C++14 shared mutex with lambda captures and multiple threads?

I have some very simple code which is supposed to test a multi-threaded logger by starting 10 threads at the same time which will all write to the logger at once.
I expect to see all 10 messages, not in any order; However, I randomly get 5,6,7,8,9, and sometimes 10 output messages.
Here is the code:
//*.cxx
#include <iostream>
#include <mutex>
#include <shared_mutex> // requires c++14
#include <string>
#include <thread>
#include <vector>
namespace {
std::mutex g_msgLock;
std::shared_timed_mutex g_testingLock;
}
void info(const char * msg) {
std::unique_lock<std::mutex> lock(g_msgLock);
std::cout << msg << '\n'; // don't flush
}
int main(int argc, char** argv) {
info("Start message..");
std::vector<std::thread> threads;
unsigned int threadCount = 10;
threads.reserve(threadCount);
{ // Scope for locking all threads
std::lock_guard<std::shared_timed_mutex> lockAllThreads(g_testingLock); // RAII (scoped) lock
for (unsigned int i = 0; i < threadCount; i++) {
// Here we start the threads using lambdas
threads.push_back(std::thread([&, i](){
// Here we block and wait on lockAllThreads
std::shared_lock<std::shared_timed_mutex> threadLock(g_testingLock);
std::string msg = std::string("THREADED_TEST_INFO_MESSAGE: ") + std::to_string(i);
info(msg.c_str());
}));
}
} // End of scope, lock is released, all threads continue now
for(auto& thread : threads){
thread.join();
}
}
The output is generally something of the form:
Start message..
THREADED_TEST_INFO_MESSAGE: 9
THREADED_TEST_INFO_MESSAGE: 5
THREADED_TEST_INFO_MESSAGE: 3
THREADED_TEST_INFO_MESSAGE: 1
THREADED_TEST_INFO_MESSAGE: 4
THREADED_TEST_INFO_MESSAGE: 0
THREADED_TEST_INFO_MESSAGE: 8
THREADED_TEST_INFO_MESSAGE: 7
Notice that there are only 8 outputs for this run.
Interestingly enough, this problem was associated with my build system which was dropping messages. The executable is always producing the outputs as expected.

threads programming exercise - reading and writing . Mutex not needed?

I am trying thread programming exercise (from HERE) with some tweaks. I want to try 2 (or more) threads which read from a string one word at a time and then write to a buffer. Finally main thread will print the buffer written by threads.
I was surprised that my code works even if I don't use mutex lock to protect the write buffer ? in its current state - is this correct way to do things ? it produces correct output though.
Specifically the while loop in 'Hello' function: would it have been more efficient if mutex was used ? how to write code in that case ?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int threadCount = 3;
int finish = 0;
int turn = 0;
void *Hello(void *rank);
char *str = "This is a really long string.. such a long string this really is... !";
char buff[512];
int index = 0;
int main() {
long thread;
pthread_t *hThread;
hThread = (pthread_t *)malloc(threadCount*sizeof(pthread_t));
if(hThread == NULL) {
printf("\nERROR: malloc failed");
}
for(thread = 0; thread < threadCount; thread++) {
pthread_create(&hThread[thread], NULL, Hello, (void *)thread);
}
printf("Hello from main thread !\n");
for(thread = 0; thread < threadCount; thread++) {
pthread_join(hThread[thread], NULL);
}
printf("All threads finished !\n");
printf("%s\n", buff);
free(hThread);
return 0;
}
void printMsg(void) {
if(finish)
return;
while(*str != '\0' && *str != ' ') {
buff[index++] = *str;
printf("%c",*str++);
}
printf("\n");
if(*str == ' ') {
buff[index++] = ' ';
str++;
}
if(*str == '\0') {
buff[index++] = '\0';
finish = 1;
}
turn = (turn +1)%threadCount;
}
void *Hello(void *rank) {
long id = (long)rank;
while(!finish) {
if(turn == (int)id) {
printf("%ld : ", id);
printMsg();
}
}
return NULL;
}
I can see output produced as:
0 : This
Hello from main thread !
1 : is
2 : a
0 : really
1 : long
2 : string..
0 : such
1 : a
2 : long
0 : string
1 : this
2 : really
0 : is...
1 : !
All threads finished !
This is a really long string.. such a long string this really is... !

Issue in predicate function in wait in thread C++

I am trying to put the condition inside a function but it is throwing confusing compile time error . While if I write it in lambda function like this []{ retur i == k;} it is showing k is unidentified . Can anybody tell How to solve this problem .
#include <iostream>
#include <mutex>
#include <sstream>
#include <thread>
#include <chrono>
#include <condition_variable>
using namespace std;
condition_variable cv;
mutex m;
int i;
bool check_func(int i,int k)
{
return i == k;
}
void print(int k)
{
unique_lock<mutex> lk(m);
cv.wait(lk,check_func(i,k)); // Line 33
cout<<"Thread no. "<<this_thread::get_id()<<" parameter "<<k<<"\n";
i++;
return;
}
int main()
{
thread threads[10];
for(int i = 0; i < 10; i++)
threads[i] = thread(print,i);
for(auto &t : threads)
t.join();
return 0;
}
Compiler Error:
In file included from 6:0:
/usr/include/c++/4.9/condition_variable: In instantiation of 'void std::condition_variable::wait(std::unique_lock<std::mutex>&, _Predicate) [with _Predicate = bool]':
33:30: required from here
/usr/include/c++/4.9/condition_variable:97:14: error: '__p' cannot be used as a function
while (!__p())
^
wait() takes a predicate, which is a callable unary function returning bool. wait() uses that predicate like so:
while (!pred()) {
wait(lock);
}
check_func(i,k) is a bool. It's not callable and it's a constant - which defeats the purpose. You're waiting on something that can change. You need to wrap it in something that can be repeatedly callable - like a lambda:
cv.wait(lk, [&]{ return check_func(i,k); });

Readers / writer implementation using std::atomic (mutex free)

Below is an attempt at a multiple reader / writer shared data which uses std::atomics and busy waits instead of mutex and condition variables to synchronize between readers and writers. I am puzzled as to why the asserts in there are being hit. I'm sure there's a bug somewhere in the logic, but I'm not certain where it is.
The idea behind the implementation is that threads that read are spinning until the writer is done writing. As they enter the read function they increase m_numReaders count and as they are waiting for the writer they increase the m_numWaiting count.
The idea is that the m_numWaiting should then always be smaller or equal to m_numReaders, provided m_numWaiting is always incremented after m_numReaders and decremented before m_numReaders.
There shouldn't be a case where m_numWaiting is bigger than m_numReaders (or I'm not seeing it) since a reader always increments the reader counter first and only sometimes increments the waiting counter and the waiting counter is always decremented first.
Yet, this seems to be whats happening because the asserts are being hit.
Can someone point out the logic error, if you see it?
Thanks!
#include <iostream>
#include <thread>
#include <assert.h>
template<typename T>
class ReadWrite
{
public:
ReadWrite() : m_numReaders(0), m_numWaiting(0), m_writing(false)
{
m_writeFlag.clear();
}
template<typename functor>
void read(functor& readFunc)
{
m_numReaders++;
std::atomic<bool>waiting(false);
while (m_writing)
{
if(!waiting)
{
m_numWaiting++; // m_numWaiting should always be increased after m_numReaders
waiting = true;
}
}
assert(m_numWaiting <= m_numReaders);
readFunc(&m_data);
assert(m_numWaiting <= m_numReaders); // <-- These asserts get hit ?
if(waiting)
{
m_numWaiting--; // m_numWaiting should always be decreased before m_numReaders
}
m_numReaders--;
assert(m_numWaiting <= m_numReaders); // <-- These asserts get hit ?
}
//
// Only a single writer can operate on this at any given time.
//
template<typename functor>
void write(functor& writeFunc)
{
while (m_writeFlag.test_and_set());
// Ensure no readers present
while (m_numReaders);
// At this point m_numReaders may have been increased !
m_writing = true;
// If a reader entered before the writing flag was set, wait for
// it to finish
while (m_numReaders > m_numWaiting);
writeFunc(&m_data);
m_writeFlag.clear();
m_writing = false;
}
private:
T m_data;
std::atomic<int64_t> m_numReaders;
std::atomic<int64_t> m_numWaiting;
std::atomic<bool> m_writing;
std::atomic_flag m_writeFlag;
};
int main(int argc, const char * argv[])
{
const size_t numReaders = 2;
const size_t numWriters = 1;
const size_t numReadWrites = 10000000;
std::thread readThreads[numReaders];
std::thread writeThreads[numWriters];
ReadWrite<int> dummyData;
auto writeFunc = [&](int* pData) { return; }; // intentionally empty
auto readFunc = [&](int* pData) { return; }; // intentionally empty
auto readThreadProc = [&]()
{
size_t numReads = numReadWrites;
while (numReads--)
{
dummyData.read(readFunc);
}
};
auto writeThreadProc = [&]()
{
size_t numWrites = numReadWrites;
while (numWrites--)
{
dummyData.write(writeFunc);
}
};
for (std::thread& thread : writeThreads) { thread = std::thread(writeThreadProc);}
for (std::thread& thread : readThreads) { thread = std::thread(readThreadProc);}
for (std::thread& thread : writeThreads) { thread.join();}
for (std::thread& thread : readThreads) { thread.join();}
}

thread::join() blocks when it shouldn't

To understand how to use atomics in C++11, I tried to following code snippet:
#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
struct solution {
atomic<bool> alive_;
thread thread_;
solution() : thread_([this] {
alive_ = true;
while (alive_);
}) { }
~solution() {
alive_ = false;
thread_.join();
}
};
int main() {
constexpr int N = 1; // or 2
for (int i = 0; i < N; ++i) {
solution s;
}
cout << "done" << endl;
}
If N equals 1, the output is done. However, if I set it to 2, the main thread blocks at thread::join(). Why do you think we don't see done when N > 1?
Note: If I use the following constructor:
solution() : alive_(true), thread_([this] {
while (alive_);
}) { }
it prints done for any value of N.
If you don't initialise alive_ and only set it once the thread starts, the following interleaving of execution is possible:
MAIN: s::solution()
MAIN: s.thread_(/*your args*/)
MAIN: schedule(s.thread_) to run
thread: waiting to start
MAIN: s::~solution()
MAIN: s.alive_ = false
thread: alive_ = true
MAIN: s.thread_.join()
thread: while(alive_) {}
atomic<bool> is, by default, initialized with false on Visual Studio (its initial value is undefined by standard).
So, the following sequence of events might happen:
A solution object is created, alive_ is initialized to false and thread_ is created (but not run).
The solution object is destroyed, the destructor runs and sets alive_ to false, then waits for thread_ to end (thread has not done anything)
thread_ runs, sets alive_ to true, and then loops forever (because the main thread is waiting for it to terminate).

Resources