We have central classes and functions in our big project to abstract from the actual platform types, e.g. mutex, file, thread etc. instead of having “fopen” everywhere in the code. While this is good, I would like to go even further and don’t have any system includes in the header files (like #include <windows.h>), which would be true platform abstraction and faster compilation. On the downside you cannot just typedef to a system type (e.g. Windows HANDLE).
Option 1: PImpl-idiom
class RwMutex
{
// .....
private:
struct Impl;
Impl* m_Impl;
}
- Pro: Implementation and platform types well hidden in Cpp.
- Con: Involves 2-stage construction (the ‘new’, we don’t have exception) which can fail. Laborious to do.
Option 2: Namespace functions
class RwMutex {
public:
bool LockRead() {return RwMutexLockRead( this );}
private:
char m_AnonymousMember[ 16 ];
}
bool RwMutexLockRead( RwMutex* p );
- Pro: The implementation can be just linked to it, ideal for placing it into a library on its own.
- Con: Involves reinterpret_cast of the space which holds the member. Not nice in the debugger. Also a lot of work.
Maybe I’m to eager on it, but it would be cool if the huge amount of project code would be clean of any platform-dependent includes, maybe enforced by the -nostdinc option.
Option 1 using pointers is a bad idea. Use either
boost::scoped_ptror, if you can,std::unique_ptr.Option 2, as you implement it, should not be used. See GotW #28: The Fast Pimpl Idiom. In C++11 however, this can be done correctly using
std::aligned_storage<>. I once wrote apimpl_ptr<T, Size, Align=default>that does the casting, copying, destructor call for you and checks that you have chosen the rightSize.In general, use pimpl unless you have profiled and shown that this is the bottleneck.
But as always, don’t reinvent the wheel. Mutex and Threads are part of the new C++11 standard, so either upgrade the compiler or use Boost instead. For files use Boost. The reasoning is, that many parts of the new C++11 library are taken from Boost.