Sorry some shortcut sent my message before I was able to finish it.

On Sun, May 17, 2009 at 5:12 PM, Ovanes Markarian <om_boost@keywallet.com> wrote:
Hello *,

I wrote a code which used a RAII idiom to lock multiple mutex instances in ctor and unlock them in dtor.

This resulted in the class similar to:

struct lock_many
{

       lock_many() : //default init members
       {}

    lock_many(mutex& m1, mutex& m2, ...)
       : m1_(m1), ...
    {
       boost::lock(*m1_, *m2_, ...);
    }

    ~lock_many()
    {
        //some asserts here, which ensure that either all mutex pointers are NULL or unequl to each other
        if(m1_==NULL && m2_==NULL && ...)
           return; // all are NULL no unlock needed

        m1_->unlock(), m2_->unlock, ...;
    }


   private:
     mutex* m1_;
     mutex* m2_;
};


Now I used the swap to lock/unlock a member variable:

class
{

  public:

     void lock()
     {
        using namespace std;
        swap(many_locked_, lock_many(m1_, m2_...));
     }

     void unlock()
     {
        using namespace std;
        swap(many_locked_, lock_many());
     }

  private:
    lock_many      many_locked_;
};


As I found out, unlock did not unlock, due to std::swap implemenation.

swap has a temporary, which gets the many_locked_ assigned at the end of swap the dtor is called and unlocks the mutexes. Leaving the swap(many_locked_, lock_many()) sentence cause lock_many() temporary to go out of scope and calls unlock again. Now mutexes get lock and my app dead locks. Should that at least be asserted somehow, that calling subsequent unlock is not a good idea?

Ahh, my boost version is 1.36 and I am using MSVC 2008


Many thanks,
Ovanes