Topic: Thread: condition variable wait prototypes


Author: viboes <vicente.botet@wanadoo.fr>
Date: Sun, 19 Sep 2010 16:55:10 CST
Raw View
On Sep 16, 1:17=A0am, Howard Hinnant <howard.hinn...@gmail.com> wrote:
> On Sep 15, 11:05=A0am, viboes <vicente.bo...@wanadoo.fr> wrote:
>
> > Hi,
>
> > Why condition_variable::wait has a unique_lock<mutex> as parameter
> > and
> > condition_variable_any::wait has just a Lockable?
>
> > Why condition_variable::wait hasn't =A0just a mutex parameter or
> > condition_variable_any::wait a unique_lock<Lockable>?
>
> The use case is not as convenient for condition_variable::wait(mutex&)
> as it is for condition_variable::wait(unique_lock<mutex>&). =A0Consider:
>
> mutex m;
> condition_variable cv;
>
> void f()
> {
> =A0 =A0 unique_lock<mutex> lock(m);
> =A0 =A0 // do stuff
> =A0 =A0 while (!not_ready_to_go_on())
> =A0 =A0 =A0 =A0 =A0cv.wait(lock);
> =A0 =A0 // do more stuff
>
> }
>
> The above is completely exception safe. =A0If "do stuff" or "do more
> stuff" throws an exception, m is unlocked as the exception propagates
> out of f(). =A0If instead we had condition_variable::wait(mutex&), then
> the above example would have to change to:
>
> void f()
> {
> =A0 =A0 unique_lock<mutex> lock(m);
> =A0 =A0 // do stuff
> =A0 =A0 while (!not_ready_to_go_on())
> =A0 =A0 =A0 =A0 =A0cv.wait(*lock.mutex());
> =A0 =A0 // do more stuff
>
> }
>
> or worse yet, it might encourage people to code in the following
> exception-unsafe way:
>
> void f()
> {
> =A0 =A0 m.lock();
> =A0 =A0 // do stuff
> =A0 =A0 while (!not_ready_to_go_on())
> =A0 =A0 =A0 =A0 =A0cv.wait(m);
> =A0 =A0 // do more stuff
> =A0 =A0 m.unlock();
>
> }
>
> As for condition_variable_any: =A0All it does is unlock and lock its
> template parameter. =A0The same exception safety considerations apply.
> But we want to allow many more uses than just unique_lock<some
> mutex>. =A0For example see this reference:
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#sh...
> ock_rationale
>
> for example code (using slightly different names) waits on a
> condition_variable_any with a read/write mutex locked in read-mode. =A0A
> gratuitous wrapping of shared_lock<shared_mutex> by unique_lock would
> only tend to irritate programmers, with no added benefits.

Hi,

Thanks for the explanations. I understand the the exception safety
argument, and why we want to allow many more uses than just
unique_lock<some mutex> for condition_variable_any::wait.

What I don't see yet is why the same argument don't apply to
condition_variable::wait. I would like to be able to use
condition_variable::wait with my own Lock as follows

mutex m;
condition_variable cv;
...
{
   my_lock<mutex> lock(m);
   // do stuff
   while (!not_ready_to_go_on())
        cv.wait(lock);
   // do more stuff
}

With the current interface my_lock<Lockable> must inherit from
unique_lock<Lockable>.
my_lock could also wrap a unique_lock and give access to the
unique_look

{
   my_lock<mutex> lock(m);
   // do stuff
   while (!not_ready_to_go_on())
        cv.wait(lock.get_unique_lock());
   // do more stuff
}

But as you said this would only tend to irritate programmers.

Looking at the requirements of the lock parameter
condition_variable::wait I would say that the lock parameter should be
a Lock that allows to retrieve the underlying Lockable through
boost::mutex* m=lock.mutex(), i.e. the nested typedef mutex_type is
boost::mutex.

Resuming,  if I've not missed something, the current requirements for
condition_variable::wait lock parameter could be relaxed without any
impact on code using already this interface, even the
condition_variable::wait implementations shouldn't be impacted (other
than the interface change).

Best,
Vicente



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: viboes <vicente.botet@wanadoo.fr>
Date: Wed, 15 Sep 2010 12:05:12 CST
Raw View
Hi,

Why condition_variable::wait has a unique_lock<mutex> as parameter
and
condition_variable_any::wait has just a Lockable?

Why condition_variable::wait hasn't  just a mutex parameter or
condition_variable_any::wait a unique_lock<Lockable>?

--
Vicente

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Wed, 15 Sep 2010 17:17:10 CST
Raw View
On Sep 15, 11:05=A0am, viboes <vicente.bo...@wanadoo.fr> wrote:
> Hi,
>
> Why condition_variable::wait has a unique_lock<mutex> as parameter
> and
> condition_variable_any::wait has just a Lockable?
>
> Why condition_variable::wait hasn't =A0just a mutex parameter or
> condition_variable_any::wait a unique_lock<Lockable>?

The use case is not as convenient for condition_variable::wait(mutex&)
as it is for condition_variable::wait(unique_lock<mutex>&).  Consider:

mutex m;
condition_variable cv;

void f()
{
    unique_lock<mutex> lock(m);
    // do stuff
    while (!not_ready_to_go_on())
         cv.wait(lock);
    // do more stuff
}

The above is completely exception safe.  If "do stuff" or "do more
stuff" throws an exception, m is unlocked as the exception propagates
out of f().  If instead we had condition_variable::wait(mutex&), then
the above example would have to change to:

void f()
{
    unique_lock<mutex> lock(m);
    // do stuff
    while (!not_ready_to_go_on())
         cv.wait(*lock.mutex());
    // do more stuff
}

or worse yet, it might encourage people to code in the following
exception-unsafe way:

void f()
{
    m.lock();
    // do stuff
    while (!not_ready_to_go_on())
         cv.wait(m);
    // do more stuff
    m.unlock();
}

As for condition_variable_any:  All it does is unlock and lock its
template parameter.  The same exception safety considerations apply.
But we want to allow many more uses than just unique_lock<some
mutex>.  For example see this reference:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#shared_l=
ock_rationale

for example code (using slightly different names) waits on a
condition_variable_any with a read/write mutex locked in read-mode.  A
gratuitous wrapping of shared_lock<shared_mutex> by unique_lock would
only tend to irritate programmers, with no added benefits.

-Howard

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]