tomminno
20-10-2007, 09:11
Ho provato ad emulare la WaitForSingleObject di Windows usando le pThread, ma ci sono riuscito solo in parte.
Il mio obiettivo è quello di bloccare un thread in attesa di un evento, se però la condizione di wait per un qualche motivo viene impostata dopo il signal (in debug avviene praticamente sempre) ottengo un fallimento per timeout, mentre in Windows viene riconosciuto l'evento come già settato e la WaitForSingleObject ritorna subito.
Questo è il codice che ho usato:
class Event
{
public:
Event()
{
#ifdef WIN32
event = CreateEvent(NULL,false,false,NULL);
#else
pthread_cond_init (&event, NULL);
pthread_mutex_init(&mutex, NULL);
#endif
}
~Event()
{
#ifdef WIN32
CloseHandle(event);
#else
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&event);
#endif
}
void SetEvent()
{
#ifdef WIN32
::SetEvent(event);
#else
pthread_cond_signal(&event);
#endif
}
void ResetEvent()
{
#ifdef WIN32
::ResetEvent(event);
#else
pthread_cond_signal(&event);
#endif
}
bool Wait()
{
#ifdef WIN32
return WaitForSingleObject(event,INFINITE) == WAIT_OBJECT_0;
#else
pthread_mutex_lock(&mutex);
int rc = pthread_cond_wait(&event, &mutex);
pthread_mutex_unlock(&mutex);
return rc == 0;
#endif
}
bool Wait(int milliseconds)
{
#ifdef WIN32
return WaitForSingleObject(event,milliseconds) == WAIT_OBJECT_0;
#else
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec + milliseconds/1000;
timeout.tv_nsec = now.tv_usec * 1000;
bool done = false, success = false;
int rc = pthread_mutex_lock(&mutex);
if (rc) /* an error has occurred */
return false;
while (!done)
{
rc = pthread_cond_timedwait(&event,&mutex,&timeout);
switch (rc)
{
case 0:
success = true;
done = true;
break;
default:
if (rc == ETIMEDOUT)
done = true;
break;
}
}
pthread_mutex_unlock(&mutex);
return success;
#endif
}
private:
#ifdef WIN32
HANDLE event;
#else
pthread_cond_t event;
pthread_mutex_t mutex;
#endif
};
Ok sono pronto alla fucilazione :)
Un altra domanda ma se volessi attendere sulla pthread_cond_timedwait per 1500 millisecondi devo per forza aggiungere 1 al campo tv_sec e 5e8 a tv_nsec?
Non c'è un modo per aggiungere direttamente il valore a tv_nsec?
Quando ho provato ad aggiungere 15e8 al campo tv_nsec non ho mai raggiunto il timeout.
Il mio obiettivo è quello di bloccare un thread in attesa di un evento, se però la condizione di wait per un qualche motivo viene impostata dopo il signal (in debug avviene praticamente sempre) ottengo un fallimento per timeout, mentre in Windows viene riconosciuto l'evento come già settato e la WaitForSingleObject ritorna subito.
Questo è il codice che ho usato:
class Event
{
public:
Event()
{
#ifdef WIN32
event = CreateEvent(NULL,false,false,NULL);
#else
pthread_cond_init (&event, NULL);
pthread_mutex_init(&mutex, NULL);
#endif
}
~Event()
{
#ifdef WIN32
CloseHandle(event);
#else
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&event);
#endif
}
void SetEvent()
{
#ifdef WIN32
::SetEvent(event);
#else
pthread_cond_signal(&event);
#endif
}
void ResetEvent()
{
#ifdef WIN32
::ResetEvent(event);
#else
pthread_cond_signal(&event);
#endif
}
bool Wait()
{
#ifdef WIN32
return WaitForSingleObject(event,INFINITE) == WAIT_OBJECT_0;
#else
pthread_mutex_lock(&mutex);
int rc = pthread_cond_wait(&event, &mutex);
pthread_mutex_unlock(&mutex);
return rc == 0;
#endif
}
bool Wait(int milliseconds)
{
#ifdef WIN32
return WaitForSingleObject(event,milliseconds) == WAIT_OBJECT_0;
#else
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec + milliseconds/1000;
timeout.tv_nsec = now.tv_usec * 1000;
bool done = false, success = false;
int rc = pthread_mutex_lock(&mutex);
if (rc) /* an error has occurred */
return false;
while (!done)
{
rc = pthread_cond_timedwait(&event,&mutex,&timeout);
switch (rc)
{
case 0:
success = true;
done = true;
break;
default:
if (rc == ETIMEDOUT)
done = true;
break;
}
}
pthread_mutex_unlock(&mutex);
return success;
#endif
}
private:
#ifdef WIN32
HANDLE event;
#else
pthread_cond_t event;
pthread_mutex_t mutex;
#endif
};
Ok sono pronto alla fucilazione :)
Un altra domanda ma se volessi attendere sulla pthread_cond_timedwait per 1500 millisecondi devo per forza aggiungere 1 al campo tv_sec e 5e8 a tv_nsec?
Non c'è un modo per aggiungere direttamente il valore a tv_nsec?
Quando ho provato ad aggiungere 15e8 al campo tv_nsec non ho mai raggiunto il timeout.