Boost logo

Boost Users :

From: Mark Sizer (boost_at_[hidden])
Date: 2003-10-21 10:14:56


Weston Markham wrote:

> It strikes me as odd that waiting on a condition variable is not const. It
> seems to me that, although one does expect the condition variable to change
> state, one is not actually requesting the change, but instead is merely
> detecting a change made by another thread.
>
> I can understand that, internally, the condition variable is probably
> keeping lists of waiting threads, which would need to be modified in order
> to satisfy the wait() call. From the point of view of the calling code,
> however, I think that this is irrelevant.
>
> Is there some other sense in which calling wait() can be considered to
> modify the condition variable?
>
> Weston Markham

The condition wait() requires a lock, which requires a mutex. The mutex
state is toggled from acquired to free to acquired whilst the wait() is
waiting.

It's the same problem that having a lock creates on a method such as
this one:

ThreadedQueue::bMessageAvailable() const
{
   { boost::mutex::scoped_lock( _mutexQueue )
     return !_queue.empty();
   }
}

The only way to make that work is to declare the _mutexQueue as "mutable".

In the case above, I agree with you: In terms of logical "const-ness",
these methods are (or can be) const. In terms of physical "const-ness",
they are not. Solve the problem with "mutable".

However, the condition case is a bit more subtle.

ThreadedQueue::messageNext() const
{
   { boost::mutex::scoped_lock lockQueue( _mutexQueue );
     if ( _queueOut.empty() )
     {
       // (the lock is released before blocking,
       // then re-locked before continuing)
       _conditionMessageReady.wait( lockQueue );
     }
     // get a message
   }
}

Is that really const? if the _mutexQueue and _conditionMessageReady are
made "mutable" we can MAKE the method const (as shown), but is it?

I'd say there is a EXPLICIT state change in the object: Into the waiting
state. This is a change, therefore non-const. In the bMessageAvailable()
case, there is no explicit state change, you're returning the existing
state of the object. There is an implicit state change required to
safely do so, which we've decided to hide. The only way this can block
forever is bad coding - deadlock.

When using a condition.wait(), you are making 2 big state changes:
  Both the object and the thread involved go from a "running" state into
a "blocked" state, perhaps forever if nothing notifies (which is
reasonable if the event never occurrs, not a coding deadlock error).
That doesn't seem "const" to me.

- Mark


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net