Re: RAII object in constructor
 
On Wednesday, 9 October 2013 21:48:50 UTC+1, Marcel M=FCller  wrote:
I have a mutex lock that is implemented as RAII. I need to acquire the 
mutex as long as the constructor runs. But for the /entire/ constructor=
 
run not just the construction of the derived class.
Example:
#include <stdio.h>
// some mutex class
class Mutex
{
public:
   // hold the Mutex (RAII)
   struct Lock
   { Lock(Mutex& mtx)
     { puts("Lock()\n");
       //...
     }
     ~Lock()
     { puts("~Lock()\n");
       //...
     }
   };
   //...
};
How is this fundamentally different from `std::mutex` and
`std::lock_guard`?
// set of configuration parameters
struct Parameters
{ //...
};
class WorkerBase
{ //...
protected:
   WorkerBase(const Parameters& params)
   { // do something with params...
   }
};
class Worker : public WorkerBase
{
private:
   static Parameters GlobalParams;
   static Mutex ParamMtx; // protect the above
public:
   // synchronized public access to the parameters
   struct AccessParams : Mutex::Lock
   { AccessParams() : Mutex::Lock(ParamMtx) {}
     operator Parameters&() { return GlobalParams; }
   };
   Worker() : WorkerBase(AccessParams())
   { AccessParams params; // !!! Mutex acquired twice!
     // do something with params...
   }
};
The simplest solution (that I know) is to make the constructor
to Worker take an `AccessParams` argument:
    Worker::Worker( AccessParams const& params = AccessParams() )
        : WorkerBase( params )
    {
    }
There are a number of variants on this, depending on whether
`Worker` requires more arguments or not, but the basic idea is
for the most derived class' constructor to have the special
argument.
Note that if you ever use `Worker` as a temporary, the lock will
be held until the end of the full expression.  This can be a bit
of a bother, if e.g. client code does something like:
    func( Worker() );
The lock will be held during the entire call to func, which
could be a problem.
-- 
James