Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2005-09-23 21:21:56


On Sep 23, 2005, at 7:43 PM, Jason Hise wrote:

> I am relatively new to threading, so forgive me if my question is
> naive,
> but what is the formal definition of a condition variable? If a
> condition variable is capable of making a thread that has been
> explicitly told to sleep until a certain time wake up early, can you
> show me an example of its use?

On Sep 23, 2005, at 8:52 PM, Peter Petrov wrote:

> Instead of sleeping, use timed_wait on a condition variable. Upon
> awakening, check the cause (which could be timeout, valid signal, or
> spurious wakeup).

<nod> I remember well my first introduction to condition variables.
At first they seemed rather strange. But I view them now as
fundamental as a mutex (from a client's point of view). You just can't
live without them.

I could've sworn boost had a good example or two of condition usage,
but I'm not finding one tonight. So here's a bounded_queue demo I
wrote some time ago. It's a copy/paste from example code and it uses
Metrowerks::condition and such. You can just substitute "boost" for
"Metrowerks" and you ought to be pretty close with it. The basic idea
is that a thread can lock a mutex, then go to sleep on a condition
variable, passing it the locked mutex. The condition variable
atomically unlocks the mutex, allows another thread to make the
condition true (probably needing to lock the mutex), and relocks the
mutex, awaking the original thread. The original thread awakes with
whatever condition it needs magically satisfied (by another thread),
and it's mutex locked and ready to rock & roll (but beware of spurious
wake ups).

There are really few libraries that are worth a full-stop and a
deep-dive learning experience for a day or two. boost::condition is
one of those libraries (or equivalently pthread_cond_init,
pthread_cond_destroy, pthread_cond_signal, pthread_cond_broadcast,
pthread_cond_wait, pthread_cond_timedwait).

#include <iostream>
#include <bind>
#include <cdeque>
#include <msl_thread>

class bounded_queue
{
public:
     typedef Metrowerks::mutex Mutex;
     typedef Mutex::scoped_lock lock;

     bounded_queue(int max) {the_queue_.reserve((unsigned)max);}

     void send (int m);
     int receive();

private:
     Metrowerks::cdeque<int> the_queue_;
     Metrowerks::condition queue_is_empty_so_;
     Metrowerks::condition queue_is_full_so_;
     Mutex mut_;
};

template <class C>
struct container_not_full
{
     container_not_full(const C& c) : c_(c) {}
     bool operator()() const {return c_.size() != c_.capacity();}
private:
     const C& c_;
};

template <class C>
struct container_not_empty
{
     container_not_empty(const C& c) : c_(c) {}
     bool operator()() const {return !c_.empty();}
private:
     const C& c_;
};

void
bounded_queue::send (int m)
{
     lock lk(mut_);
     queue_is_full_so_.wait(lk,
container_not_full<Metrowerks::cdeque<int> >(the_queue_));
     the_queue_.push_back(m);
     std::cout << "sent: " << m << '\n';
     if (the_queue_.size() == 1)
         queue_is_empty_so_.notify_one();
}

int
bounded_queue::receive()
{
     lock lk(mut_);
     queue_is_empty_so_.wait(lk,
container_not_empty<Metrowerks::cdeque<int> >(the_queue_));
     int i = the_queue_.front();
     std::cout << "received: " << i << '\n';
     if (the_queue_.size() == the_queue_.capacity())
         queue_is_full_so_.notify_one();
     the_queue_.pop_front();
     return i;
}

bounded_queue buf(20);

void sender(volatile bool& cancel)
{
     int n = 0;
     while (!cancel)
     {
         buf.send(n);
         ++n;
     }
     buf.send(-1);
}

void receiver()
{
     int n;
     do
     {
         n = buf.receive();
     } while (n >= 0);
}

int main()
{
     volatile bool cancel = false;
     Metrowerks::thread send(std::tr1::bind(sender,
std::tr1::ref(cancel)));
     Metrowerks::thread receive(receiver);
     Metrowerks::thread::sleep(Metrowerks::elapsed_time(1));
     cancel = true;
     send.join();
     receive.join();
}

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk