On Feb 3, 2011, at 8:14 PM, John Ky wrote:
It would be nice to have a condition_variable_any that supports any kind of lock.
It's probably okay if there were a condition_variable_* class for each lock type as well. Or did you mean something like condition_variable_any<Mutex>?
A condition_variable_any<Mutex> is counter-productive. What you really need is:
class condition_variable_any
{
public:
condition_variable_any();
~condition_variable_any();
condition_variable_any(const condition_variable_any&) = delete;
condition_variable_any& operator=(const condition_variable_any&) = delete;
void notify_one();
void notify_all();
template <class Lock>
void wait(Lock& lock);
template
void wait(Lock& lock, Predicate pred);
template
cv_status
wait_until(Lock& lock,
const chrono::time_point& abs_time);
template
bool
wait_until(Lock& lock,
const chrono::time_point& abs_time,
Predicate pred);
template
cv_status
wait_for(Lock& lock,
const chrono::duration& rel_time);
template
bool
wait_for(Lock& lock,
const chrono::duration& rel_time,
Predicate pred);
};
I.e. only the wait functions are templated on the lock. This allows one cv to be waited on by two different kinds of locks at the same time. For example one thread could wait on the thread with a shared_lock while another thread waited on the same cv with a unique_lock (but using the same underlying shared_mutex):
shared_mutex mut;
condition_variable_any cv;
void wait_in_shared_ownership_mode()
{
shared_lock shared_lk(mut);
// mut is now shared-locked
// ...
while (not_ready_for_shared_to_proceed())
cv.wait(shared_lk); // shared-lock released while waiting
// mut is now shared-locked
// ...
} // mut is now unlocked
void wait_in_unique_ownership_mode()
{
unique_lock lk(mut);
// mut is now unique-locked
// ...
while (not_ready_for_unique_to_proceed())
cv.wait(lk); // unique-lock released while waiting
// mut is now unique-locked
// ...
} // mut is now unlocked
A third thread could change either the not_ready_for_shared_to_proceed predicate, the not_ready_for_unique_to_proceed predicate, or both, and then cv.notify_all(). This is very powerful stuff when you need it (most of the time condition_variable and mutex are all you need).
In this set condition_variable_any and unique_lock are in C++0x. I hope to propose shared_lock and shared_mutex for tr2 and ultimately c++1x. Field experience here (good or bad) would help. Here is a tutorial and implementation of the shared and upgrade mutexes and locks:
http://home.roadrunner.com/~hinnant/mutexes/locking.html
Here is an implementation of condition_variable_any:
http://llvm.org/svn/llvm-project/libcxx/trunk/include/condition_variable
-Howard