I want to know how to run a thread to sleep some time every time I press a key. For example, if I press the same key twice, it should have two threads to sleep for a while.
I MUST use pthreads and C++.
Honestly I have tried many ways but I still do not know how to solve it.
Sorry if my english is not very good :)
UPDATE
This is my code:
#include <pthread.h>
#include <iostream>
#include <unistd.h>
using namespace std;
pthread_mutex_t mutex;
pthread_cond_t cond;
int a;
void* executer2(void*)
{
pthread_mutex_lock(&mutex);
while (a > 0) {
pthread_cond_wait(&cond, &mutex);
}
cout << "Thread: " << pthread_self() << endl;
sleep(a);
pthread_mutex_unlock(&mutex);
}
void* executer(void*)
{
int key;
while (1) {
pthread_mutex_lock(&mutex);
key = cin.get();
if (key == 'a') {
cout << "Sleep for 4 seconds" << endl;
a = 4;
} else if (key == 'b') {
cout << "Sleep for 8 seconds" << endl;
a = 8;
} else {
cout << "Sleep for 2 seconds" << endl;
a = 2;
}
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t tr, t;
pthread_attr_t attr;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&tr, &attr, executer, NULL);
pthread_create(&t, &attr, executer2, NULL);
pthread_join(tr, NULL);
pthread_join(t, NULL);
}
since you want to create a thread each time you press a key, and that the keypress handler is in executer, you should move the code to create executer2 in executer.
executer is made to sleep 1 sec. after reading a key press, but it seems that's not what you want. Just remove that call to sleep(1) to get an immediate response
the code of executer seems to indicate that you wish to modulate the time spent sleeping by the thread depending on the input key. You can pass the sleep time as a parameter to executer2, as indicated by the void * parameter of that function. The idea is to cast the time value to a void *, pass it at thread creation time, and cast it back to int within executer2:
// executer2 thread creation
pthread_create(&t, &attr, executer2,(void *)a);
and in executer2:
void *executer2(void *arg){
int a = (int)arg;
// ...
The thread creation code should go after the switch in executer2, and you should not need the global a variable anymore.
you are currently using a mutex to lock the code of executer2. This will prevent all the sleeping threads to sleep together at the same time. You will have to remove the lock to allow them to sleep concurrently (but leave the lock around the text output).
you say that you wish a C++ solution. You could benefit from using the thread library from the stl, which wraps the OS thread primitives (pthreads in your case) with higher level constructs and are easier to manipulate, especially for parameters. It would be a good exercise to convert your programme to use this library once you have the current code working.
Related
I am trying to learn multithreading in C++. I am trying to pass elements of a vector as arguments to pthread_create. However, it is not working as expected.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <vector>
using namespace std;
void *count(void *arg)
{
int threadId = *((int *)arg);
cout << "Currently thread with id " << threadId << " is executing " << endl;
pthread_exit(NULL);
}
int main()
{
pthread_t thread1;
vector<int> threadId(2);
threadId[0] = 99;
threadId[1] = 100;
int retVal = pthread_create(&thread1, NULL, count, (void *)&threadId[0]);
if (retVal)
{
cout << "Error in creating thread with Id: " << threadId[0] << endl;
exit(-1);
}
pthread_t thread2;
retVal = pthread_create(&thread2, NULL, count, (void *)&threadId[1]);
if (retVal)
{
cout << "Error in creating thread with Id: " << threadId[1] << endl;
exit(-1);
}
pthread_exit(NULL);
}
The output which I get is:
Currently thread with id 99 is executing.
Currently thread with id 0 is executing
However, according to me, it should be:
Currently thread with id 99 is executing.
Currently thread with id 100 is executing.
What am I missing here ?
int retVal = pthread_create(&thread1, NULL, count, (void *)&threadId[0]);
You have no guarantee, whatsoever, that the new execution thread is now running, right this very instant, without any delay.
All that pthread_create guarantees you is that the thread function, thread1, will begin executing at some point. It might be before pthread_create() itself returns. Or it might be at some point after. It's really a big mystery when the new thread function will start executing, but you can take it to the bank that the new execution thread will begin. Eventually.
The same thing goes for your 2nd execution thread.
So, both execution thread could very well get in gear after your main() returns, and after your vector gets destroyed. There's nothing in the shown code that guarantees that the execution threads will execute before the vector (whose contents get passed into them, in the manner shown) gets destroyed. And this leads to undefined behavior.
You will need to use other thread-related facilities that must be employed in order to synchronize multiple execution threads correctly. Additionally, you're using older POSIX threads. Modern C++ uses std::threads which offer many advantages over their predecessor, is completely type-safe (no ugly casts) and have numerous attributes that prevent common programming errors (however, in this instance std::threads also have no synchronization guarantee, this is usually the case with all typical execution thread implementations).
I have used mutex in inherited classes but seems it does not work as I expected with threads. Please have a look at below code:
#include <iostream>
#include <cstdlib>
#include <pthread.h>
// mutex::lock/unlock
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono> // std::thread
#include <mutex> // std::mutex
typedef unsigned int UINT32t;
typedef int INT32t;
using namespace std;
class Abstract {
protected:
std::mutex mtx;
};
class Derived: public Abstract
{
public:
void* write( void* result)
{
UINT32t error[1];
UINT32t data = 34;
INT32t length = 0;
static INT32t counter = 0;
cout << "\t before Locking ..." << " in thread" << endl;
mtx.lock();
//critical section
cout << "\t After Create " << ++ counter << " device in thread" << endl;
std::this_thread::sleep_for(1s);
mtx.unlock();
cout << "\t deallocated " << counter << " device in thread" << endl;
pthread_exit(result);
}
};
void* threadTest1( void* result)
{
Derived dev;
dev.write(nullptr);
}
int main()
{
unsigned char byData[1024] = {0};
ssize_t len;
void *status = 0, *status2 = 0;
int result = 0, result2 = 0;
pthread_t pth, pth2;
pthread_create(&pth, NULL, threadTest1, &result);
pthread_create(&pth2, NULL, threadTest1, &result2);
//wait for all kids to complete
pthread_join(pth, &status);
pthread_join(pth2, &status2);
if (status != 0) {
printf("result : %d\n",result);
} else {
printf("thread failed\n");
}
if (status2 != 0) {
printf("result2 : %d\n",result2);
} else {
printf("thread2 failed\n");
}
return -1;
}
so the result is:
*Four or five arguments expected.
before Locking ... in thread
After Create 1 device in thread
before Locking ... in thread
After Create 2 device in thread
deallocated 2 device in thread
deallocated 2 device in thread
thread failed
thread2 failed
*
So here we can see that second thread comes to critical section before mutex was deallocated.
The string "After Create 2 device in thread" says about that.
If it comes to critical section before mutex is deallocated it means mutex works wrong.
If you have any thoughts please share.
thanks
The mutex itself is (probably) working fine (I'd recommend you to use std::lock_guard though), but both threads create their own Derived object, hence, they don't use the same mutex.
Edit: tkausl's answer is correct -- however, even if you switch to using a global mutex, the output may not change because of the detail in my answer so I'm leaving it here. In other words, there are two reasons why the output may not be what you expect, and you need to fix both.
Note in particular these two lines:
mtx.unlock();
cout << "\t deallocated " << counter << " device in thread" << endl;
You seem to be under the impression that these two lines will be run one right after the other, but there is no guarantee that this will happen in a preemptive multithreading environment. What can happen instead is that right after mtx.unlock() there could be a context switch to the other thread.
In other words, the second thread is waiting for the mutex to unlock, but the first thread isn't printing the "deallocated" message before the second thread preempts it.
The simplest way to get the output you expect would be to swap the order of these two lines.
You shall declare your mutex as a global variable and initiate it before calling pthread_create. You created two threads using pthread_create and both of them create their own mutex so there is absolutely no synchronization between them.
This is my code:
void* task1(void* unused)
{
try {
cout << "Run Thread" << endl;
}catch (const char* msg) {
cout << msg << endl;
}
}
int main(int argc, char *argv[])
{
try {
pthread_t thread_id;
int res = pthread_create(&thread_id, NULL, &task1, NULL);
cout << res << std::endl;
exit(EXIT_SUCCESS);
}catch (const char* msg) {
cout << msg << endl;
}
}
In Ubuntu Code RUN.
In CentOS Code NOT RUN, if my use pthread_join(thread_id, NULL); code is run but can waiting pthread complete. I try pthread_tryjoin_np but code not run.
Please help me run code in centos is no wating
If the program main() exits before the thread actually starts (and runs to the point cout << ...), the thread will be terminated and not continue to run.
I.e. you need to wait with pthread_join() before the main() exits.
The case in Ubuntu is a pure coincidence, that the thread manages to print the line before it is terminated by the C++ runtime after the main() exits.
If you do not want to wait because you want to start multiple threads, you can use thread pool (array of threads). First you start all of them, and then you pthread_join() wait for all of them to finish.
Also, if the pthread_join() blocks although the thread terminated, make sure you created the thread as joinable. That is the default, so make sure that you do not explicitly set the thread attributes to PTHREAD_CREATE_DETACHED.
To be absolutely sure, you can provide thread create attributes explicitly and ensure that the thread is created as joinable:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&thread_id, &attr, &task1, NULL);
pthread_attr_destroy(&attr);
pthread_join(thread_id, NULL);
(error handling not included)
Why you do not use C ++ 11? Standard library (STL) have the opportunity to develop crossplatform applications with threads. You can test on cpp.sh
#include <iostream>
#include <thread>
void task1(int used)
{
std::cout << "Run Thread " << used << std::endl;
}
int main()
{
std::thread thr(task1,1);
thr.join();
return 0;
}
OR
#include <iostream>
#include <thread>
#include <chrono>
bool bThread = false;
void task1(int used)
{
std::cout << "Run Thread " << used << std::endl;
bThread = true;
}
int main()
{
std::thread thr(task1,1);
try
{
thr.detach();
while (!bThread) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
catch(...) { return 1; }
return 0;
}
everyone.
I am new to semaphore and recently I am learning to implement a simple problem using binary semaphores and i have some questions.
So there is a visiting room, at one time only one person can go in. In my design there are three queues of people (which are all the threads i created). For example, after the person in the second queue visited that room, the next person who is going to enter the room is the top one waiting in third queue, rather the first queue's person. The number of total people is given. and after leaving, just simply terminate the thread.
I am trying to create three semaphores to handle this, i.e, after one person in second queue enters, then block the second queue and ONLY "signal" the third queue to continue. and so on so forth. However, the code has some problems. here I just show some semaphore part of code.
int the main:
sem_init(&mutex, 0, 1);
sem_init(&s0, 0, 1);
sem_init(&s1, 0, 1);
sem_init(&s2, 0, 1);
// create 100 pthread and randomly put into queue0 or queue1 or queue2
for(int i = 0; i<num_thread; i++){
pthread_t curr_thread;
if(queueId == 0){
queue0.push(curr_thread);
}else if(queueId == 1){
queue1.push(curr_thread);
}else if(queueId == 2){
queue2.push(curr_thread);
}
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&curr_thread, &attr, &thread_function, &queue_Num);
pthread_attr_destroy (&attr);
}
in the thread function:
void* thread_function (void* arg){
sem_wait(&mutex);
int n = *((int*) arg);
if(n==0){
sem_wait(&s0);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue0.empty()){
queue0.pop();
}else{
n++;
}
sem_post(&s1);
}else if(n==1){
sem_wait(&s1);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue1.empty()){
queue1.pop();
}else{
n++;
}
sem_post(&s2);
}else if(n==2){
sem_wait(&s2);
cout << "person in queue" << n << " is visiting" << endl;
sleep(1);
if(!queue2.empty()){
queue2.pop();
}else{
n++;
}
sem_post(&s0);
}
sem_post(&mutex);
return NULL;
}
Actually when I run it, seems like I met "deadlock", the main finished with showing only 2 threads every time. I thought there must be some problems in the designing of the thread_function. Is there anybody can help point it out and tell me how to fix it? Thanks advance.
When you pass your queueId to the threads, you don't want to pass it a pointer to one of your local variables, because you are going to be changing that very quickly. You should instead just be passing in the integer itself to your threads:
pthread_create(&curr_thread, &attr, &thread_function, (void*)queueId);
// Pass queueId the int, not a pointer
Then, when you need to read the value in your threads, just cast the void* back to an integer:
void* thread_function (void* arg){
...
int n = (long)arg;
..
}
After this, your code works great, for me.
Hey - I'm having an odd problem with a little toy program I've written, to try out threads.
This is my code:
#include <pthread.h>
#include <iostream>
using std::cout;
using std::endl;
void *threadFunc(void *arg) {
cout << "I am a thread. Hear me roar." << endl;
pthread_exit(NULL);
}
int main() {
cout << "Hello there." << endl;
int returnValue;
pthread_t myThread;
returnValue = pthread_create(&myThread, NULL, threadFunc, NULL);
if (returnValue != 0) {
cout << "Couldn't create thread! Whoops." << endl;
return -1;
}
return 0;
}
With the first cout in main not commented out, the thread prints fine.
However, without it, the thread doesn't print anything at all.
Any help?
Try this:
#include <pthread.h>
#include <iostream>
using std::cout;
using std::endl;
void *threadFunc(void *arg) {
cout << "I am a thread. Hear me roar." << endl;
pthread_exit(NULL);
}
int main() {
//cout << "Hello there." << endl;
int returnValue;
pthread_t myThread;
returnValue = pthread_create(&myThread, NULL, threadFunc, NULL);
if (returnValue != 0) {
cout << "Couldn't create thread! Whoops." << endl;
return -1;
}
pthread_join( myThread, NULL);
return 0;
}
The difference between my code and yours is one line - pthread join. This suspends the main thread until the sub-thread has had chance to complete its actions.
In your code, execution reaches the first cout and it's processed. Then, you split off another thread and the main thread carries on until the end, which may or may not be reached before the secondary thread is tidied up. That's where the odd behaviour comes in - what you are experiencing is the case where the main program finishes before the sub-thread has had a chance to, so the program has "returned" and the whole lot is cleaned up by the kernel.
It's a race condition that allows the program to work when the main loop takes a little while to run. Your program is exiting before the thread even has a chance to run.
You should wait for the thread to complete (see pthread_join) before returning from main().
The fact that it works in one case is pure luck. You have a timing issue, which is your program is exiting before your thread does it's work.
When main() exits all your threads will die. You need some sort of waiting in place to give the other thread time to run before main() exits. Try adding a cin in main() after you create the worker thread and see what happens.
Ultimately you'll want some sort of run-loop and messaging/eventing to communicate between threads.
-jeff
Try adding a pthread_exit(NULL); at the end of main, before the return 0. I suspect that the problem is your main returns and the process exits before the thread has a chance to print. Printing from main might be somehow modifying the timing such that the thread does get a chance to print -- but that's is just sheer luck. You need to ensure that main doesn't return until all of your threads are finished doing their work. Calling pthread_exit from main allows other threads to continue running until they too have called pthread_exit.