I'm making my first multithreaded program and having some issues. I based the code on an example I found online, which worked fine until I made my changes. The main function below makes several threads which run another function. That function runs instances of another c++ program that I wrote which works fine. The issue is that after the program creates all the threads, it stops running. The other threads continue to run and work fine, but the main thread stops, not even printing out a cout statement I gave it. For example, if I run it the output is:
Enter the number of threads:
// I enter '3'
main() : creating thread, 0
this line prints every time
main() : creating thread, 1
this line prints every time
main() : creating thread, 2
this line prints every time
this is followed by all the output from my other program, which is running 3 times. But the main function never prints out "This line is never printed out". I'm sure there is some fundamental misunderstanding I have of how threads work.
#include <iostream>
#include <stdlib.h>
#include <cstdlib>
#include <pthread.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <unistd.h>
using namespace std;
struct thread_data{
int thread_id;
};
void *PrintHello(void *threadarg)
{
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
stringstream convert;
convert << "./a.out " << my_data->thread_id << " " << (my_data->thread_id+1) << " " << my_data->thread_id;
string sout = convert.str();
system(sout.c_str());
pthread_exit(NULL);
}
int main ()
{
int NUM_THREADS;
cout << "Enter the number of threads:\n";
cin >> NUM_THREADS;
pthread_t threads[NUM_THREADS];
struct thread_data td[NUM_THREADS];
int i;
for( i=0; i < NUM_THREADS; i++ ){
cout <<"main() : creating thread, " << i << endl;
td[i].thread_id = i;
pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
cout << endl << "this line prints every time" << endl;
}
cout << endl << "This line is never printed out";
pthread_exit(NULL);
}
It's because you're not using pthread_join(threads[i],NULL). pthread_join() prevents the main from ending before the threads finish executing
Related
How can i make a small program that prints something endlessly, but I can still use the standard input to write and display something whenever I want?
I found this example, but it terminates after just 2 inputs (and I want to input something multiple times, not just 2).
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
using std::cout;
using std::cin;
using std::thread;
using std::string;
using std::endl;
int stopflag = 0;
void input_func()
{
while (true && !stopflag)
{
string input;
cin >> input;
cout << "Input: " << input << endl;
}
}
void output_func()
{
while (true && !stopflag)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
cout << "Output thread\n";
}
}
int main()
{
while (1)
{
thread inp(input_func);
thread outp(output_func);
std::this_thread::sleep_for(std::chrono::seconds(5));
stopflag = 1;
outp.join();
cout << "Joined output thread\n";
inp.join();
}
cout << "End of main, all threads joined.\n";
return 0;
}
Just remove the line stopflag = 1. But also, if you want to print the lines you need to add synchronization to modify flag and also printing. Because only one thread should write to console and one time. Don't forget to add flush, as it will not print all text always.
I am trying to wrap my head around std::async and std::futures introduced in C++11.
#include <iostream>
#include <list>
#include <functional>
#include <vector>
#include <algorithm>
#include <thread>
#include <unistd.h>
#include <string>
#include <future>
using namespace std;
int hog_cpu()
{
cout << "hog_cpu" << endl;
volatile unsigned long long i = 0;
for(i = 0; i < 1000000000ULL ; i++);
return 50;
}
int hog_cpu_ex()
{
cout << "hog_cpu_ex" << endl;
volatile unsigned long long i = 0;
for(i = 0; i < 1000000000ULL ; i++);
return 500;
}
int main()
{
cout << "start threads asynchronously" << endl;
std::future<int> f1 = std::async(std::launch::async, hog_cpu);
std::future<int> f2 = std::async(std::launch::async, hog_cpu_ex);
cout << "Get the Results" << endl;
int r1 = f1.get();
int r2 = f2.get();
cout << "result 1: " << r1 << endl;
cout << "result 2: " << r2 << endl;
return 0;
}
The output of the above program that I get is shown below.
start threads asynchronously
Get the Results
hog_cpu_ex
hog_cpu
result 1: 50
result 2: 500
Process finished with exit code 0
My question is since I use std::launch::async the execution should start immideately using another thread. Where as the output tells me that it prints the line Get the results and then only the execution starts. (As evident from the logs above). Also hog_cpu_ex starts before hog_cpu. Can someone explain why this might be happening.
When you do
std::future<int> f1 = std::async(std::launch::async, hog_cpu);
std::future<int> f2 = std::async(std::launch::async, hog_cpu_ex);
You spin up two more threads of execution. Then the main thread keeps going after it calls each line and won't stop until it hits
int r1 = f1.get();
if f1 hasn't finished yet. Since the main thread keeps going and spinning up a thread takes some time it is pretty reasonable to see Get the Results print before the threads even start.
As for why do you see
hog_cpu_ex
hog_cpu
instead of the opposite is due to your operating system. It has control over which threads run and when so it is quite possible that it puts f1 to sleep, has space for f2 so it starts it running, and then starts f1 sometime after that.
I am learning C++ [Java background fwiw] and trying to write a UNIX shell as a project. I am running into a funny little problem with tokenizing the input for execution. The tok function is getting called twice and I'm not sure why. My current test code is the following:
#include <iostream>
#include <vector>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;
void tok(string, char**);
int main(){
const char* EXIT = "exit";
string input;
cout << "shell>> ";
getline(cin, input);
pid_t pid = fork();
char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
tok(input, args);
return 0;
}
//copied from http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
void tok(string inStr, char** args){
int last = 0, next = 0, i = 0;
while( (next = inStr.find(' ', last)) != -1){
cout << i++ << ": " << inStr.substr(last, next-last) << endl;
*args++ = strdup(inStr.substr(last, next-last).c_str());
last = next + 1;
}
cout << i++ << ": " << inStr.substr(last) << endl;
*args++ = strdup(inStr.substr(last).c_str());
*args = '\0';
cout << "done tokenizing..." << endl;
}
My output when I actually run the program is:
$ ./a.out
shell>> ls -l
0: ls
1: -l
done tokenizing...
0: ls
1: -l
done tokenizing...
I'm not sure why it would do that. Can anyone guide me in the right direction please? Thank you
The fork function returns twice, once in the original process and once in the newly-created, forked process. Both of those processes then call tok.
There doesn't seem to be any clear reason why you called fork. So the fix may be as simple as eliminating the call to fork.
When you call fork, you create two processes. Each process has nearly the exact same state except for the respective pid_t you receive. If that value is greater than 0, then you are in the parent process (main), and otherwise you are in the child (or fork failed).
Without performing a check on the returned pid_t, both processes will call tok, resulting in the double call behavior you witnessed.
Hide the call behind a check on pid like so:
pid_t pid = fork();
if (pid > 0) // have parent process call tok
{
char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
tok(input, args);
}
To see what else parent and child processes have in common (or not): check the docs
following code may work fine
#include <iostream>
#include <vector>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;
void tok(string, char**);
int main(){
const char* EXIT = "exit";
string input;
cout << "shell>> ";
getline(cin, input);
// pid_t pid = fork();
char* args[64];
tok(input, args);
return 0;
}
void tok(string inStr, char** args){
int last = 0, next = 0, i = 0;
while( (next = inStr.find(' ', last)) != -1){
cout << i++ << ": " << inStr.substr(last, next-last) << endl;
*args++ = strdup(inStr.substr(last, next-last).c_str());
last = next + 1;
}
cout << i++ << ": " << inStr.substr(last) << endl;
*args++ = strdup(inStr.substr(last).c_str());
*args = '\0';
cout << "done tokenizing..." << endl;
}
im trying to communicate a pthread with a process, using pipes, for a college proyect. i make a struct with the pipes and i pass that structure to the pthread so it can listen on the pipe[0], and on the rest of the code i try to send a string to that running pthread.
Here is my code:
#include <unistd.h>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <pthread.h>
using namespace std;
struct Pipefd{
int pipe[2];
string name;
};
void* listenProcess(void* x){
Pipefd* pf = reinterpret_cast<Pipefd*>(x);
close(0);
dup(pf->pipe[0]);
//here i try to see if the struct i send is ok, but this is not printed.
cout << "pf.name: " << pf->name << endl;
string recive;
while(getline(cin,recive)){
cout << "recive: " << recive << endl;
}
cout << "Problem with getline" << endl;
}
int main(int argc, char *argv[]) {
Pipefd myPipe;
myPipe.name = "Test";
pipe(myPipe.pipe);
void* test = reinterpret_cast<void*>(&myPipe);
pthread_t tid;
pthread_create(&tid,NULL, &listenProcess,test);
close(1);
dup(myPipe.pipe[1]);
cout << "This is a message" << endl;
pthread_join(tid,NULL);
}
if someone can reply me with some ideas of how to make this work it would be awesome, if not, thank you for your time.
I am trying to make use of boost::thread to perform "n" similar jobs. Of course, "n" in general could be exorbitantly high and so I want to restrict the number of simultaneously running threads to some small number m (say 8). I wrote something like the following, where I open 11 text files, four at a time using four threads.
I have a small class parallel (which upon invoking run() method would open an output file and write a line to it, taking in a int variable. The compilation goes smoothly and the program runs without any warning. The result however is not as expected. The files are created, but they are not always 11 in number. Does anyone know what's the mistake I am making?
Here's parallel.hpp:
#include <fstream>
#include <iostream>
#include <boost/thread.hpp>
class parallel{
public:
int m_start;
parallel()
{ }
// member function
void run(int start=2);
};
The parallel.cpp implementation file is
#include "parallel.hpp"
void parallel::run(int start){
m_start = start;
std::cout << "I am " << m_start << "! Thread # "
<< boost::this_thread::get_id()
<< " work started!" << std::endl;
std::string fname("test-");
std::ostringstream buffer;
buffer << m_start << ".txt";
fname.append(buffer.str());
std::fstream output;
output.open(fname.c_str(), std::ios::out);
output << "Hi, I am " << m_start << std::endl;
output.close();
std::cout << "Thread # "
<< boost::this_thread::get_id()
<< " work finished!" << std::endl;
}
And the main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include "parallel.hpp"
int main(int argc, char* argv[]){
std::cout << "main: startup!" << std::endl;
std::cout << boost::thread::hardware_concurrency() << std::endl;
parallel p;
int populationSize(11), concurrency(3);
// define concurrent thread group
std::vector<boost::shared_ptr<boost::thread> > threads;
// population one-by-one
while(populationSize >= 0) {
// concurrent threads
for(int i = 0; i < concurrency; i++){
// create a thread
boost::shared_ptr<boost::thread>
thread(new boost::thread(¶llel::run, &p, populationSize--));
threads.push_back(thread);
}
// run the threads
for(int i =0; i < concurrency; i++)
threads[i]->join();
threads.clear();
}
return 0;
}
You have a single parallel object with a single m_start member variable, which all threads access without any synchronization.
Update
This race condition seems to be a consequence of a design problem. It is unclear what an object of type parallel is meant to represent.
If it is meant to represent a thread, then one object should be allocated for each thread created. The program as posted has a single object and many threads.
If it is meant to represent a group of threads, then it should not keep data that belongs to individual threads.