Boost logo

Boost :

From: Lee Brown (lee_at_[hidden])
Date: 2002-01-16 21:47:08


On Wednesday 16 January 2002 05:56, you wrote:

> > class Lock {
> > Lock(mutex& m) : m_(m) {
> > disable_cancel();
> > m_.lock();
> > push_cleanup(m_ , &muxtex::unlock)
> > enable_cancel();
> > }
> >
> > ~Lock() {
> > disable_cancel();
> > pop_cleanup();
> > enable_cancel();
> > }
>
> Perhaps you miss just one rather simple thing. We are not
> supposed to wait on mutex - condition variables are designed
> for waits. Now, when our threads return from cond.wait (even
> if wait was cancelled), mutex is *always* locked. I just fail
> to understand how it is supposed to work if mutex would itself
> be a cancel.point! I need mutex on cancel to restore shared
> data invariants (waiters count, etc...) So, what is the point
> in making e.g. monitor lock a cancel.point by default if I
> could always invoke pthread_testcancel() if I really want
> it, and again - NOT SUPPOSED TO SPEND TOO MUCH TIME ON MUTEX
> to make it worth being a cancel.point.
>
> regards,
> alexander.

I was not my contention that mutex_lock is a cancelation point. Nor
was it my contention that mutexs should be held for long periods.
Locking a mutex is not a cancel point. But it is neccessary to do
before waiting on a condition. This is info from an info page
that I have read many times.
 
<>
     `pthread_cond_wait' atomically unlocks the MUTEX (as per
     `pthread_unlock_mutex') and waits for the condition variable COND
     to be signaled. The thread execution is suspended and does not
     consume any CPU time until the condition variable is signaled. The
***** MUTEX must be locked by the calling thread on entrance to ******
     `pthread_cond_wait'. Before returning to the calling thread,
     `pthread_cond_wait' re-acquires MUTEX (as per
     `pthread_lock_mutex').

 

  `pthread_cond_wait' and `pthread_cond_timedwait' are cancellation
points. If a thread is cancelled while suspended in one of these
functions, the thread immediately resumes execution, relocks the mutex
specified by MUTEX, and finally executes the cancellation.
Consequently, cleanup handlers are assured that MUTEX is locked when
they are called.
</>

So again using the above Lock class.

extern mutex mutex_;
extern condition condition_;
extern int x;

thread_func()
{
        Lock l(mutex_);
        wait(condition_, mutex_); //or timed wait
        // do your thing with x
} //exit

Constructors an destructors are just functions.
The equivalent C code is:

struct c_lock {
   mutex* m_;
};

C_thread_func()
{
    struct c_lock l;
    c_lock_init(&l, &mutex_);

    wait(&condition_, &mutex_);
    // do thing with x

   c_lock_destroy(&l);
}

void c_lock_init(struct c_lock* l, mutex* m)
{
    l.m_ = m;
    disable_cancel();
    thread_lock(&l.m);
    push_cleanup(&thread_unlock, &l.m);
    enable_cancel();
}


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