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