Reputation: 577
void wait(int timeInMs)
{
struct timespec timeToWait;
timeToWait.tv_sec = 5;
timeToWait.tv_nsec = timeInMs*1000;
int rt;
pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
}
I'm using this code to try to get a thread to wait around for a bit, but it doesn't work at all. No errors, it just doesn't make the program execute any slower.
I was thinking maybe each thread needs to have it's own condition and mutex, but that really doesn't make sense to me.
Upvotes: 7
Views: 72753
Reputation: 121
pthread_cond_timedwait uses absolute time, so need to:
timeInMs is millisecond: 1 millisecond = 1000 microseconds = 1000 * 1000 nanoseconds.
void wait(int timeInMs)
{
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
ts.tv_sec = time(NULL) + timeInMs / 1000;
ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeInMs % 1000);
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec %= (1000 * 1000 * 1000);
int n = pthread_cond_timedwait(&condition, &mutex, &ts);
if (n == 0)
// TODO: singaled
else if (n == ETIMEDOUT)
// TODO: Time out.
}
Upvotes: 10
Reputation: 226
Main reference: http://pubs.opengroup.org/onlinepubs/009695299/functions/pthread_cond_timedwait.html
FIX of the code of andrewrk above
I can confirm Adrian May that gettimeofday doesn't function correctly! The code behavior of andrewrk inside an infinite thread like this
static void * thread_infinite(void * unused) {
while (1) {
// compute stuff
mywait(5);
}
is unpredictable: it runs approximate 700 times more until it blocks!
The correct version of the code of andrewrk is:
pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
void mywait(int timeInS)
{
struct timespec ts;
struct timeval now;
int rt = 0;
// gettimeofday(&now,NULL); // DOES NOT FUNCTION CORRECTLY
// timeToWait.tv_sec = now.tv_sec+5;
// timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += timeInS;
pthread_mutex_lock(&fakeMutex);
do {
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &ts);
}
while (rt == 0);
pthread_mutex_unlock(&fakeMutex);
}
Upvotes: 4
Reputation: 678
Using any variant of sleep, the behavior is not guaranteed. All the threads can also sleep since the kernel is not aware of the different threads.
A safer and cleaner solution to use is pthread_cond_timedwait
. You used the API incorrectly. Here is a better example:
pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
void mywait(int timeInMs)
{
struct timespec timeToWait;
struct timeval now;
int rt;
gettimeofday(&now,NULL);
timeToWait.tv_sec = now.tv_sec+5;
timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
printf("\nDone\n");
}
void* fun(void* arg)
{
printf("\nIn thread\n");
mywait(1000);
}
int main()
{
pthread_t thread;
void *ret;
pthread_create(&thread, NULL, fun, NULL);
pthread_join(thread,&ret);
}
You need to specify how much time to wait from current time. Since you were only telling 5 sec and some nano-seconds it found that the time had already passed and did not wait...Please let me know if any more doubts.
Upvotes: 19
Reputation: 1296
Here is an example where I have created a thread from main loop which does a scan of a directory and have a timeout of 5 sec. And signalling from the thread happens using a conditional variable which is a global. We keep checking for this signal from thread:
pthread_cond_t C_KISU_SwagntUtilityBase::m_cond; /*Global variable*/
/*Inside main function*/
/*Local variables*/
pthread_condattr_t l_attr;
pthread_condattr_init(&l_attr);
pthread_condattr_setclock(&l_attr, CLOCK_MONOTONIC);
pthread_cond_init(&C_KISU_SwagntUtilityBase::m_cond, &l_attr);
Int32 l_threadid = pthread_create(&l_updatethread,NULL,C_KISU_SwagntUtilityBase::ThreadScanDirectoryByFilter,&l_filer);
if(CMP_ZERO == l_threadid)
{
pthread_mutex_t l_mutex = PTHREAD_MUTEX_INITIALIZER;
struct timespec l_ts;
if (clock_gettime(CLOCK_MONOTONIC, &l_ts) == INIT_NEGONE)
{
/* Handle error */
}
printf("\n Setting max time to run ThreadScanDirectoryByFilter as 5 second"));
l_ts.tv_sec += l_filer.m_max_scan_time;
if(l_filer.m_scan_status == 0)
{
pthread_mutex_lock(&l_mutex);
int l_rt = pthread_cond_timedwait(&C_KISU_SwagntUtilityBase::m_cond, &l_mutex, &l_ts);
if (ETIMEDOUT == l_rt)
{
printf("\n timeout has happened before scan routine could finish"));
}
else if (EOK == l_rt)
{
printf("\n Scan successful"));
}
else
{
printf("\n Unknown error while timeout condition check"));
}
pthread_mutex_unlock(&l_mutex);
}
}
else
{
printf("\n Error while creating thread\n");
}
Upvotes: 1
Reputation: 182753
The pthread_cond_timedwait
function takes an absolute time, not a relative time. It takes the time you want to stop waiting, not how long you want to wait.
Upvotes: 22
Reputation: 31
Considering you are using timespec, and your goal isn't to synchronize but to wait I'd suggest nanosleep.
#include <time.h>
.
.
.
struct timespec remain;
remain.tv_sec = 5;
remain.tv_nsec = timeInMs * 1000;
do {
if ( nanosleep( &remain, &remain ) == 0 || errno != EINTR ) {
break;
}
} while ( 1 );
.
.
.
Upvotes: 3
Reputation: 23168
That code doesn't sleep, it checks a condition for a while. As you are not probably setting cond ok it just returns immediately.
If you are not willing to synchronize threads around a signal then pthread_cond _wait is not what you need. Check here how condition variables work.
if you want to sleep with seconds precision use sleep
If you want to sleep with microseconds precision use select with timevals.
Upvotes: 2