interprocess_condition::wait(scoped_lock<interprocess_upgradable_lock> &) missing

Hi boost users,
I've discovered that the following doesn't compile.
using namespace boost::interprocess;
interprocess_upgradable_mutex mutex;
interprocess_condition cv;
boost::posix_time::ptime deadline;
{
scoped_lock

Oops. Left some name mangling in there. Fixed now.
On 3 February 2011 12:16, John Ky
Hi boost users,
I've discovered that the following doesn't compile.
using namespace boost::interprocess; interprocess_upgradable_mutex mutex; interprocess_condition cv; boost::posix_time::ptime deadline;
{ scoped_lock
lock(mutex); sharable_lock lock2(mutex); cv.wait(lock); // doesn't compile cv.timed_wait(lock, deadline); // doesn't compile. } It is failing because boost doesn't define the following methods:
void interprocess_condition::do_wait(interprocess_upgradable_mutex &mut);
bool interprocess_condition::do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_upgradable_mutex &mut);
I was thinking of making a basic implementation like so:
Define a scoped_unlock class, which behaves just like scoped_lock except the constructor unlocks and the destructor locks.
Then define the following:
inline void interprocess_condition::do_wait(interprocess_upgradable_mutex &mut) { scoped_unlock
unlock(mut); interprocess_mutex &internal_mutex = mut.m_mut; scoped_lock internal_lock(internal_mutex); this->wait(internal_lock); } inline bool interprocess_condition::do_timed_wait (const boost::posix_time::ptime &abs_time, interprocess_upgradable_mutex &mut) { scoped_unlock
unlock(mut); interprocess_mutex &internal_mutex = mut.m_mut; scoped_lock internal_lock(internal_mutex); return this->timed_wait(internal_lock, abs_time); } These functions simply do the following:
- unlock the exclusive lock on the interprocess_upgradable_mutex (which is emulated with an internal interprocess_mutex) - then lock the internal interprocess_mutex - Call interprocess_condition::wait or interprocess_condition::time_ wait on the implementation lock which does all the work - unlock the internal interprocess_mutex - relock the exclusive lock on the interprocess_upgradable_mutex
Intuitively, this should work.
Is there anything I missed that would make this an incorrect implementation?
Cheers,
-John

El 03/02/2011 2:16, John Ky escribió:
Hi boost users,
I've discovered that the following doesn't compile.
using namespace boost::interprocess; interprocess_upgradable_mutex mutex; interprocess_condition cv; boost::posix_time::ptime deadline;
Condition variables are only compatible with interprocess_mutex. I think they have no sense with other types of locks, because a mutex and a condition variable should know each other. In POSIX, condition variables are not compatible even with POSIX recursive locks, not to mention user defined locking primitives. Best, Ion

Hi Ion,
What do you mean by "a mutex and a condition variable should know each
other".
In the proposed interprocess_upgradable_mutex implementation, the condition
variable is associated with the underlying interprocess_mutex, so it should
be fine right?
Cheers,
-John
2011/2/4 Ion Gaztañaga
El 03/02/2011 2:16, John Ky escribió:
Hi boost users,
I've discovered that the following doesn't compile.
using namespace boost::interprocess; interprocess_upgradable_mutex mutex; interprocess_condition cv; boost::posix_time::ptime deadline;
Condition variables are only compatible with interprocess_mutex. I think they have no sense with other types of locks, because a mutex and a condition variable should know each other. In POSIX, condition variables are not compatible even with POSIX recursive locks, not to mention user defined locking primitives.
Best,
Ion _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

El 04/02/2011 0:59, John Ky escribió:
Hi Ion,
What do you mean by "a mutex and a condition variable should know each other".
In the proposed interprocess_upgradable_mutex implementation, the condition variable is associated with the underlying interprocess_mutex, so it should be fine right?
But upgradable mutex could be implemented without using interprocess_mutex, that's an implementation detail. I don't see the need to use an upgradable lock. POSIX does not support condition variables with read-write locks (although I think Windows Vista does) so Interprocess does not offer any support for this. Ion

El 04/02/2011 1:20, Ion Gaztañaga escribió:
El 04/02/2011 0:59, John Ky escribió:
Hi Ion,
What do you mean by "a mutex and a condition variable should know each other".
In the proposed interprocess_upgradable_mutex implementation, the condition variable is associated with the underlying interprocess_mutex, so it should be fine right?
But upgradable mutex could be implemented without using interprocess_mutex, that's an implementation detail. I don't see the need to use an upgradable lock. POSIX does not support condition variables with read-write locks (although I think Windows Vista does) so Interprocess does not offer any support for this.
I think you are trying to support a condition variable that could accept any kind of lock. That sounds like condition_variable_any, a class that is not implemented in Interprocess yet. The interface of condition_variable might suggest that it supports any kind of lock, but it is not true. I think I should state clearly this requirement in the documentation and the code and maybe try to support condition_variable_any in the future. Best, Ion

Hi Ion,
Yes that makes sense.
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>?
Cheers,
-John
2011/2/4 Ion Gaztañaga
El 04/02/2011 1:20, Ion Gaztañaga escribió:
El 04/02/2011 0:59, John Ky escribió:
Hi Ion,
What do you mean by "a mutex and a condition variable should know each other".
In the proposed interprocess_upgradable_mutex implementation, the condition variable is associated with the underlying interprocess_mutex, so it should be fine right?
But upgradable mutex could be implemented without using interprocess_mutex, that's an implementation detail. I don't see the need to use an upgradable lock. POSIX does not support condition variables with read-write locks (although I think Windows Vista does) so Interprocess does not offer any support for this.
I think you are trying to support a condition variable that could accept any kind of lock. That sounds like condition_variable_any, a class that is not implemented in Interprocess yet. The interface of condition_variable might suggest that it supports any kind of lock, but it is not true. I think I should state clearly this requirement in the documentation and the code and maybe try to support condition_variable_any in the future.
Best,
Ion _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

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

Thanks Howard for the very well written response. I appreciate the effort.
I will definitely look at this condition_variable_any class. It is a good
design and I want to stay close to the standard as well.
Cheers,
-John
On 4 February 2011 13:05, Howard Hinnant
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
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

El 04/02/2011 3:05, Howard Hinnant escribió:
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
Thanks Howard! Just two comments: a) Windows Vista condition variables natively supports Slim Reader/Writer Locks (http://msdn.microsoft.com/en-us/library/ms686304%28v=VS.85%29.aspx), the implementation could take advantage of this if shared_mutex is based on this primitive. b) Is there any reason to store shared_ptr<mutex> instead of a mutex? Best, Ion

On Feb 4, 2011, at 12:54 PM, Ion Gaztañaga wrote:
El 04/02/2011 3:05, Howard Hinnant escribió:
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
Thanks Howard! Just two comments:
a) Windows Vista condition variables natively supports Slim Reader/Writer Locks (http://msdn.microsoft.com/en-us/library/ms686304%28v=VS.85%29.aspx), the implementation could take advantage of this if shared_mutex is based on this primitive.
<nod> Agreed.
b) Is there any reason to store shared_ptr<mutex> instead of a mutex?
Yes. I missed this subtlety for years. I think it was Peter Dimov who pointed it out to me: Thread A notfies the condition_variable_any, which thread B is waiting on. Then thread A destructs the condition_variable_any before thread B wakes and returns from the wait. This is supposed to work. The POSIX condition variable also works this way. The shared_ptr is used to share ownership of the mutex between the condition_variable_any, and the thread running the wait function. If the condition_variable_any destructs while the wait is running, the mutex stays alive long for the wait function to lock and unlock it, and then destructs when the wait returns. -Howard
participants (3)
-
Howard Hinnant
-
Ion Gaztañaga
-
John Ky