This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Re: pthread_cond_timedwait vs pthread_mutex_timedlock
- From: Borislav Trifonov <bdt at shaw dot ca>
- To: libc-help at sourceware dot org
- Date: Mon, 04 May 2009 12:26:06 -0700
- Subject: Re: pthread_cond_timedwait vs pthread_mutex_timedlock
- References: <12734907-1241464459-cardhu_decombobulator_blackberry.rim.net-1831994935-@bxe1305.bisx.prod.on.blackberry>
But if the thread can just be woken when a condition occurs, then why is a mutex even needed?
Here is the relevant code:
shared_ptr<pthread_t> Log::TimerOn(int const sec)
{
if (Acquire(_delay)) return _thread;
Release(_delay, sec);
pthread_mutex_lock(_timeout.get());
_thread.reset(new pthread_t);
if (!_thread || pthread_create(_thread.get(), 0, Timer, this)) Release(_delay, 0);
return _thread;
}
bool Log::TimerOff(void)
{
// TODO: check for values of thread, timeout, etc.
if (!Acquire(_delay)) return true;
Release(_delay, 0); // Timer() loop condition is _delay != 0
timespec tDelay;
tDelay.tv_sec = 0;
tDelay.tv_nsec = 200000000;
for (int i = 0; Acquire(_cycle) && i < 10; ++i) // Timer() is currently executing a Flush() while _cycle is set; give it more time
{
pthread_mutex_unlock(_timeout.get());
pthread_delay_np(&tDelay);
}
if (Acquire(_cycle)) // Timer() thread still hasn't quit; terminate it
{
pthread_cancel(*_thread);
return false;
}
pthread_mutex_unlock(_timeout.get());
return true;
}
void *Log::Timer(void *obj)
{
SetThreadName("Log timer"); // For Windows debugger
Log *log(static_cast<Log *>(obj));
timespec tDelay;
tDelay.tv_nsec = 0;
while (Acquire(log->_delay))
{
Release(log->_cycle, true);
// TODO: Use relative time when pthread_mutex_timedlock_np() available
tDelay.tv_sec = static_cast<long>(time(0)) + log->_delay;
pthread_mutex_timedlock(log->_timeout.get(), &tDelay);
if (log->_ind >= 0) log->Flush();
Release(log->_cycle, false);
}
return 0;
}
Timer() is a static member; Acquire() and Release() just wrap volatile access and memory barriers; _thread, _lock, and _timeout are shared_ptr holding the corresponding pthread types.
> ------Original Message------
> From: Carlos O'Donell
> Sender: libc-help-owner@sourceware.org
> To: Borislav Trifonov
> Cc: libc-help@sourceware.org
> Subject: Re: pthread_cond_timedwait vs pthread_mutex_timedlock
> Sent: May 4, 2009 09:14
>
> On Mon, May 4, 2009 at 2:15 AM, Borislav Trifonov
> <trifonov@cs.ubc.ca> wrote:
> > It's not clear to me which one I should use. ?I have a log-
> flushing thread
> > that I need to wake every X seconds and flush the log (and
> also wake when
> > signaled by a full log buffer or log destructor--by unlocking
> the mutex if I
> > had used a mutex, or signaling the condition if I had used that).
> >
> > What is most important to me is to guarantee that no busy wait
> will occur.
> >
> > A possible complication is that I need my code to build on
> both Linux and
> > Windows, so I'm using pthreads for Win32/64 in the latter case.
>
> You will have to determine the intersection of supported functions
> between pthreads and glibc's pthreads, and choose from that.
>
> I would recommend pthread_cond_timedwait and pthread_cond_signal,
> since it was designed for this type of work, and it's easy to loop
> e.g. take the mutex, wait on the condition, do work, repeat, with
> another thread signaling.
>
> I know nothing about the pthreads for Win32/64 implemenation. POSIX
> does not guarantee that an implementation will not use busy
> waits, you
> will have to read the source code.
>
> Any linux glibc port using NPTL (not Linuxthreads) is certainly free
> of busy waits since the primitives use kernel futexes which are
> busy-wait free.
>
> Cheers,
> Carlos.
>
>