Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to design a good platform abstraction layer?

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.

like image 787
Borph Avatar asked Dec 06 '12 12:12

Borph


People also ask

What is platform abstraction layer?

The Platform Abstraction Layer (PAL) addresses this heterogeneity and provides the container with a uniform interface for accessing the relevant hardware and operating system information, thus allowing the rest of the container to run unmodified on any supported platform.

What are the three abstraction layers of a computer system?

There are three different layers of abstraction in computer system such as the concrete architecture at the system level, the abstract and concrete architecture at the processor level, and the abstract and concrete architecture at the micro-machine level.

What is abstraction layer example?

Examples of software models that use layers of abstraction include the OSI model for network protocols, OpenGL, and other graphics libraries, which allow the separation of concerns to facilitate interoperability and platform independence.


Video Answer


2 Answers

Option 1 using pointers is a bad idea. Use either boost::scoped_ptr or, 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 a pimpl_ptr<T, Size, Align=default> that does the casting, copying, destructor call for you and checks that you have chosen the right Size.

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.

like image 94
ipc Avatar answered Oct 11 '22 06:10

ipc


Why even have an Implementation object? Your code will not just change on the same platform, you'll be using the same implementation on the platform that your currently using at the time. Define the interface in the header, and provide various *.cpp files for the implementation for each platform you are targeting for. Using #ifndef, #else, etc.

e.g. Your file system may look like this:

include/
    RwMutex.hpp
    // etc...
src/
    RwMutex/
       RwMutexWin32.cpp
       RwMutexUnix.cpp
       // etc... 

Here's what RwMutexWin32.cpp may look like:

#ifdef MYLIBPREFIX_PLATFORM_WIN32
#include "RwMutex.hpp"

#include <Windows.h>

// implement the Windows version of the RwMutex class

Another example may be to look at SDL, or some other cross-platform library written in C or C++. They mainly use the preprocessor system. It's not likely you'd want to change what the Impl object points to (i.e. a Unix implementation on a Windows machine wouldn't make sense, nor would it compile).

And of course, if you really want to do this, I'd recommend using CMake. But as other people have suggested, you should try to use other libraries, such as boost or the standard library, it's already written for you.

like image 20
miguel.martin Avatar answered Oct 11 '22 07:10

miguel.martin